feat(workflow): H1->SpecDD auto-advance — sentinel hook + dispatch script + M3 imperatives (Phase 1)#103
Conversation
Validates chosen_preview.json.lock + design-approved.json + idea.spec.json in <run_dir>; emits dispatch JSON for SPEC_LEAD on success (exit 0), exit 2 + stderr on missing/empty artifact, exit 1 on bad arg. Mirrors scripts/h1-modal-helper.sh contract style (single-line JSON via python3 for fail-closed encoding). Phase 1 of 2 — addresses user-reported gap where /pf:new did not auto-advance into SpecDD after H1 freeze.
…son (Phase 1) PostToolUse hook on Write tool: when runs/<id>/design-approved.json is written and chosen_preview.json.lock already exists, drops a .h1-frozen-signal sentinel and appends a Blackboard h1.frozen row so M1 run-supervisor's standup loop can dispatch SpecDD without user re-prompting. Bounded stdin read (4MiB cap, MemoryError catch — W1.3 hardening). Always exits 0 (advisory). Registered in hooks.json PostToolUse with matcher Write; existing hook entries preserved.
…Phase 1) - chief-engineer-pm.md §3.9: imperative Task block for auto-dispatching SPEC_LEAD immediately after design-approved.json lock; references scripts/dispatch-spec-cycle.sh for verification. - run-supervisor.md §1: standup-tick polling rule for runs/*/.h1-frozen-signal sentinel with idempotent runs/.last-spec-dispatch marker. - commands/new.md L11: replaces vague 'after design approval' phrasing with explicit immediate-dispatch contract (zero-input, verifiable). LLM trust hardening — three places that previously implied auto-advance now state it imperatively, matching the README 'human clicks twice' promise.
…poll (codex P1) Without an initial 'runs/.last-spec-dispatch' file, 'find -newer' returns no matches (and exits 1) on fresh installs, making the first H1 signal invisible to the standup polling loop. Document an epoch-0 touch guard so the find always starts with a discoverable baseline. Addresses codex P1 from Phase 1 review.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 21 minutes and 14 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06eedbdfff
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| 검증 스크립트: | ||
| ```bash | ||
| bash scripts/dispatch-spec-cycle.sh runs/<id>/ |
There was a problem hiding this comment.
Call dispatch validator via plugin-root absolute path
The new imperative uses bash scripts/dispatch-spec-cycle.sh runs/<id>/, but Preview Forge sessions run from user workspaces (created by pf init) where scripts/ is not present, and M1 pre-flight explicitly avoids operating inside the plugin repo. In that normal runtime context this command becomes No such file or directory, so H1→SpecDD auto-advance cannot produce the dispatch JSON. Use the same ${CLAUDE_PLUGIN_ROOT}/../../scripts/... form already used in this file for other scripts.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
지적 정확합니다. 사용자 workspace(pf init로 생성된 환경)에는 plugin repo의 scripts/ 디렉터리가 없으므로 bare scripts/dispatch-spec-cycle.sh 호출은 No such file or directory로 실패합니다.
§3.9 검증 스크립트 호출을 같은 파일의 다른 §3 helper들(generate-gallery.sh, open-browser.sh, h1-modal-helper.sh, generate-spec-anchor-audit.py)과 동일한 ${CLAUDE_PLUGIN_ROOT}/../../scripts/... 절대 경로 형태로 통일했습니다 (commit 3d2c75b).
전체 회귀 suite (verify-plugin / security / e2e standard·pro·max / advocate-boilerplate / lesson07 / cache-concurrency 3종 / filled-ratio-gating / h1-modal-swap / spec-anchor-convergence) 모두 그린 확인했습니다.
- chief-engineer-pm.md §3.9: replace bare `scripts/dispatch-spec-cycle.sh`
with `${CLAUDE_PLUGIN_ROOT}/../../scripts/dispatch-spec-cycle.sh` so the
H1->SpecDD auto-advance validator works in user workspaces (where the
plugin repo's `scripts/` directory is not present), matching the form
already used by generate-gallery.sh / open-browser.sh / h1-modal-helper.sh
/ generate-spec-anchor-audit.py in this same file.
Refs PR #103 review comments
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d2c75bfe1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| 검증 스크립트 (다른 §3 helper와 동일한 plugin-root 절대 경로 형태 — 사용자 workspace에서 `scripts/`가 없을 때도 동작): | ||
| ```bash | ||
| bash "${CLAUDE_PLUGIN_ROOT}/../../scripts/dispatch-spec-cycle.sh" runs/<id>/ |
There was a problem hiding this comment.
Whitelist dispatch validator in M3 Bash scope
§3.9 now requires M3 to run dispatch-spec-cycle.sh, but this agent’s own allowed_scope still limits Bash to generate-gallery.sh and open-browser.sh; that contradiction means the model can legitimately refuse the new command and stall H1→SpecDD auto-advance even when the hook signal exists. Please add this script to the Bash allowlist (or move execution to an agent that already allows it) so the new imperative is actually executable.
Useful? React with 👍 / 👎.
| tool = payload.get("tool_name") or payload.get("tool") or "" | ||
| if tool != "Write": | ||
| return 0 |
There was a problem hiding this comment.
Detect H1 completion on Edit writes too
The new hook only handles Write, so if design-approved.json is updated through Edit (e.g., rerunning or correcting Gate H1 on an existing run file), no .h1-frozen-signal is emitted and the SpecDD auto-dispatch path is skipped. This should mirror the existing post-write hooks that handle multiple edit tools to avoid missing valid freeze events.
Useful? React with 👍 / 👎.
Summary
Phase 1 of 2 — addresses user-reported gap:
/pf:newdid not auto-advance into SpecDD after H1 freeze (design-approved.jsonlock written but no Task dispatch). Phase 2 (preview server after H2) follows in a separate PR.Three-layer fix:
scripts/dispatch-spec-cycle.sh— machine-verifiable lock validator. Mirrorsscripts/h1-modal-helper.shstyle (single-line JSON viapython3for fail-closed encoding).plugins/preview-forge/hooks/post-h1-signal.py— PostToolUse hook on Write. Whenruns/<id>/design-approved.jsonis written andchosen_preview.json.lockis already present, dropsruns/<id>/.h1-frozen-signal+ appends a Blackboardh1.frozenrow. Bounded stdin (4 MiB cap, MemoryError catch — W1.3 hardening). Always exits 0.hooks.json(added new PostToolUse Write matcher; existing entries preserved),chief-engineer-pm.md§3.9 (imperative Task block),run-supervisor.md§1 (sentinel polling rule),commands/new.mdL11 (zero-input dispatch contract).Side-effect / breaking-change table
/pf:newruns that auto-advanced via M3 markdownhooks.jsonexisting PostToolUse entries (askuser-enforcement,auto-retro-trigger)runs/*/design-approved.jsonANDchosen_preview.json.lockexists.tests/test-advocate-boilerplate.shrun-supervisor.mdpolling rule executable in M1's mental model?findpolling pattern already used elsewhere in this file (Blackboard polling §3). Theruns/.last-spec-dispatchwatermark is now seeded with an epoch-0 touch on first poll (codex P1 fix below).Verification
Unit:
bash scripts/dispatch-spec-cycle.sh <empty_dir>→ exit 2 + stderr (correct).bash scripts/dispatch-spec-cycle.sh <dir_with_3_files>→ exit 0 + JSON byte-shape{"action":"dispatch","agent":"SPEC_LEAD","input_dir":"...","run_id":"..."}(correct).python3 -c 'import json; json.load(open("plugins/preview-forge/hooks/hooks.json"))'— passes.post-h1-signal.pyintegration: with both lock files present +CLAUDE_PLUGIN_ROOTpointed at the plugin, sentinel + Blackboard row both written. Withoutchosen_preview.json.lock, no sentinel written (correctly silent).Regression (all green):
scripts/verify-plugin.sh— Pass 57 / Fail 0tests/fixtures/security/verify-security.shtests/test-advocate-boilerplate.shfor p in standard pro max; do tests/e2e/mock-bootstrap.sh "$p"; done— all PASStests/fixtures/lesson07-regression/verify-lesson07.shtests/fixtures/cache-concurrency/test-{race-window,self-heal,5way}.shtests/fixtures/filled-ratio-gating/verify.shtests/fixtures/h1-modal-swap/verify.shtests/fixtures/spec-anchor-convergence/verify.shCodex review
One pass. P1: 1 (applied), P2: 2 (deferred), P3: 0.
P1 (applied)
.last-spec-dispatchbefore polling H1 signals (run-supervisor.md). Fresh install had no watermark →find -newerreturned 0 + exit 1, making the first H1 signal invisible. Fix: documented[ -f runs/.last-spec-dispatch ] || touch -t 197001010000 runs/.last-spec-dispatchguard before the pollingfindso the baseline is always discoverable.P2 (deferred to follow-up PR)
runs/.last-spec-dispatchcan lose events if multiple runs reach H1 between polls. Mitigation suggestion: switch idempotency marker toruns/<id>/.spec-dispatchedper-run flag. Defer because (a) Preview Forge's standard usage is one run at a time and (b) Phase 2 will revisit the standup loop anyway.mitigations.jsonindispatch-spec-cycle.sh.spec-lead.mdtreats it as required input and/pf:designcan regenerate it after override; current validator passes without it. Defer because (a) the current 3-file gate matches what the plan explicitly enumerated and (b) tightening to 4 files is a separable spec/policy change worth its own review.Refs
noble-enchanting-floyd):/pf:newdid not auto-advance into SpecDD after H1 freeze.🤖 Generated with Claude Code