Repository navigation
feat(tasks): add task status files and scaffolder - #821
Conversation
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
✅ Heimdall Review Status
|
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Review round 1Reviewers: anthropic/claude-opus-5-5, cbhq-openai/gpt-6.1-sol (parallel)
🤖 Reply generated with Toshi |
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Review round 2Reviewers: anthropic/claude-opus-5-5, cbhq-openai/gpt-6.1-sol (parallel)
🤖 Reply generated with Toshi |
Review round 3Reviewers: anthropic/claude-opus-5-5, cbhq-openai/gpt-6.1-sol (parallel)
🤖 Reply generated with Toshi |
Review round 4Reviewers: anthropic/claude-opus-5-5, cbhq-openai/gpt-6.1-sol (parallel)
🤖 Reply generated with Toshi |
0xth4nh
left a comment
There was a problem hiding this comment.
P3 (stale docs, outside the diff): standby/evm/tasks/update-verifier-hashes/README.md:5.
Issue: the README still says "Invocations add only config/<network>/.env and a signer README". With this PR every invocation also needs a task-root status.json: make check-task-status fails without one, and standby archival now refuses a network that is not finalized in status.json (scripts/standby-task.py:151-157). The sibling FACILITATOR.md in the same directory, AGENTS.md and the root README were updated; this README line was not.
Impact: an operator who follows this README alone will get a CI failure or an archive refusal.
Requested change: add that an invocation also needs the task-root status.json, created with make new-task STANDBY_OP=update-verifier-hashes ..., as the FACILITATOR now describes.
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
|
@0xth4nh Fixed in 312b495. 🤖 Reply generated with Toshi |
0xth4nh
left a comment
There was a problem hiding this comment.
Looks Good to Thanh's Toshi
What changed? Why?
Every task now carries a machine-readable
status.jsonthat humans and the contract-ops bot both read and update, and one make target scaffolds new tasks with it. Today a task's progress (which step each network is at, its PR, BlockSec ticket, signatures, execution) lives only in people's heads, Slack threads and the signer README'sStatus:line, so nothing can tell at a glance what is waiting on whom.Status file.
status.jsonsits at the task root:active/evm/tasks/<task-id>/status.json, orstandby/evm/tasks/<operation>/status.jsonwhile a standby invocation exists. Per network it recordsstep(authoring,validation,review,ready_to_sign,collecting,ready_to_execute,executed,canceled),pr,blocksec_ticket,signatures(collected/required per validation file) andexecuted_tx, plus a task-levellast_updated. The schema isscripts/task-status.schema.json.Check.
scripts/task-status.py check(alsomake check-task-status) validates every status file against the schema with a small stdlib validator, so the schema file is the single source of truth and CI needs no extra Python packages. It also fails when an active task has no status file, network keys differ from theconfig/<network>/directories,executedandexecuted_txdisagree, a README markedEXECUTED/CANCELEDdisagrees with the step (either direction), a standby invocation has no status file, or a canonical standby task has one. It runs in a newvalidate-task-status.ymlworkflow.Scaffolder.
make new-taskwith exactly one selector:TASK_SLUG=<slug> TASK_NETWORK=<network> [TASK_DATE=YYYY-MM-DD]createsactive/evm/tasks/<date>-<slug>/with a Makefile modeled on the Denim task (command-lineTASK_NETWORKguard, global and task.envincludes, signer and task-origin paths), a network-agnosticFACILITATOR.md,script/,config/<network>/.env(emptyBASE_CONTRACTS_COMMITsodepsfails loudly, noRECORD_STATE_DIFF), a signer README withStatus: READY TO SIGN, andstatus.json.TASK_ID=<active task> TASK_NETWORK=<network>adds a network to an existing active task, per the one-task-many-networks rule inAGENTS.md.STANDBY_OP=<operation> TASK_NETWORK=<network>adds a standby invocation (config/<network>/.env, signer README, status entry) without touching canonical files.It refuses overwrites, networks without
config/<network>.env, invalid identifiers or dates, aTASK_NETWORKnot given on the command line, unknown tasks or operations, and zero or multiple selectors.scripts/task-status.py add-network <task-dir> <network>is the same status step on its own, for other setup scripts and for adopting existing tasks.Standby archival.
scripts/standby-task.pytreats rootstatus.jsonas invocation data likeconfig/,records/andsignatures/: it is ignored in the canonical-vs-main comparison, carried into the dated archive and removed from standby.Adoption. The two active tasks on main get a
status.json(both executed on Zeronet; tx hashes from their READMEs, PRs from git history). No other file in them changes.Docs. New "Task status and scaffolding" section in
README.md;AGENTS.mdlifecycle bullets updated.Notes to reviewers
config/<network>/: task-origin signing signs overconfig/<network>(TASK_ORIGIN_DIR), so a status update after signing would change the signed payload. A test asserts scaffolded status files never land inside a config directory.sepoliaentry in the Denimstatus.json, and the tasks added by feat(zeronet): add Denim SystemConfig gas parameters task #808, feat(sepolia): replace BalanceTracker and repoint FeeDisburser (CHAIN-1245) #807 and feat(CHAIN-4644): update Sepolia BalanceTracker profit wallet #768 each need their ownstatus.json. One command each:python3 scripts/task-status.py add-network <task-dir> <network>, then set the step.status.jsonstays out of the signed payload only when a task's Makefile scopesTASK_ORIGIN_DIRtoconfig/<network>, as Denim and the scaffolded Makefile do.2026-10-15-upgrade-l2-predeployskeeps the root default (the whole task directory), which already includes mutablerecords/and other networks' files; its executed Zeronet invocation skips task-origin validation. Any future rollout of that task that collects task-origin signatures should add the same override. This PR leaves its Makefile unchanged.README.md, so expect a small README conflict. That PR moves task Makefiles to a thinTask.mkdispatched fromactive/evm/Makefile, and its dispatcher reads a per-networkconfig/<network>/network.env. The scaffolder writes today's Denim-style Makefile and.env; if feat: add reusable active EVM task workflows #778 lands, the templates inscripts/new-task.pyneed to switch toTask.mkand its config files. Status files and the check do not depend on the Makefile layout.archive-taskso they don't collide textually with where feat: add pause task setup command #789 addssetup-pause-task. Pause tasks it creates will need a status file;setup-pause-task.shcan callscripts/task-status.py add-networkto write it.status.jsonoutsideconfig/<network>means status updates never change the checksum that creators and facilitators sign, so the two checks don't interfere.How has it been tested?
python3 -B -m unittest scripts.tests.test_task_status scripts.tests.test_standby_lifecycle -v: 34 tests pass. New tests drivemake new-taskandcheckin temporary git repos: every refusal, every failing check above, all three scaffold modes passingcheck, the scaffolded Makefile parsing and rejecting a missingTASK_NETWORK, and lossless standby archival with a status file present.python3 -B scripts/task-status.py checkpasses on the repository.validations/,records/,addresses.json) and task-specific Solidity:Generated with Toshi