* fix(#2289): context-monitor emits injection envelope only for supported events
gsd-context-monitor is wired to Codex Stop/SubagentStart/SubagentStop/PreCompact
(#772), but it emitted a hookSpecificOutput.additionalContext envelope for every
event. Codex's Stop schema rejects that shape ("hook returned invalid stop hook
JSON output") exactly when context is low.
Use a positive allowlist: emit only for context-injection events (PostToolUse,
AfterTool, and the pre-existing Gemini missing-name fallback); exit 0 silently
for Stop and every other event. Debounce and critical-session bookkeeping still
run on silenced events. Behavioral regression tests drive the real hook.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(#2289): backfill PR number 2324 into changeset
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(#2285): de-flake per-plan use_worktree property test on duplicate briefs
The fast-check property in claude-orchestration.test.cjs located each plan's
agent() call via indexOf on the brief, but only plan IDs were unique — briefs
could collide (fast-check shrinks toward short strings). On a colliding seed the
lookup found the first duplicate's line and misattributed its isolation, failing
"use_worktree:true must carry isolation" intermittently (surfaced on macOS CI).
emitWorkflowScript is correct for duplicate briefs (verified); suffix the unique
id onto each agent() label so the test probe is unambiguous.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The claude-orchestration capability (#1143) shipped registered 'active'
but fully inert: detectWorkflowBackend/emitWorkflowScript had no caller
outside their own CLI router, and execute-phase.md declared an
execute:wave:pre hook point that the workflow body never rendered — so
claude_orchestration.enabled:true had zero effect on real runs.
Approach B (maintainer-chosen):
- execute-phase.md now renders the execute:wave:pre hook
(gsd_run loop render-hooks execute:wave:pre) at a new step 2.75,
immediately before each wave's Agent() dispatch — fixing the latent
dead-hook gap for any pre-wave capability.
- Move the claude-orchestration contribution execute:wave:post ->
execute:wave:pre (a pre-wave backend selector belongs before dispatch,
not after); rename fragments/execute-wave-post.md -> execute-wave-pre.md
with prose instructing the orchestrator to call resolve-wave-dispatch
before step 3. Unrelated wave:post contributions (ui.safety-gate, drift,
external-job, mempalace) untouched.
- New .cts seam resolveWaveDispatch(input) composes detectWorkflowBackend
+ emitWorkflowScript into one {backend:'inline'|'workflow', ...} result;
exposed as gsd-tools claude-orchestration resolve-wave-dispatch. This is
a real non-CLI-router, non-test caller of both functions.
Fail-closed: any gate miss (disabled, non-Claude runtime, Workflow tool
absent, SDK below floor, execution_backend:inline, malformed input) or an
emit failure resolves to inline with a byte-identical result shape — no
regression to the default-off execute-phase path.
Regression tests (tests/fix-2285-*) cover happy-path activation + SDK-floor
BVA, the fail-closed gate-miss table with detectWorkflowBackend parity, a
fast-check composition property, capability.json contribution assertions,
and a source-contract guard that execute:wave:pre is now actually rendered.
Dependent registry-shape assertions updated in-scope.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- compareSemver: implement full SemVer 2.0.0 §11 pre-release identifier
comparison (two pre-releases of the same triple now order correctly; was 0).
- capability description + fragment: scope the plan-checker/verifier claim
(this capability delivers the parallel-execution backend; those gates remain
inline until separately wired). Correct the 'each wave is one barrier' prose
(a wave splits into multiple sequential parallel() barriers on files_modified
overlap). Frame detect-backend CLI as a simulation harness; the pure function
with the live host descriptor is the real detection seam.
- partitionStages docstring: 'near-minimal via greedy first-fit' (not 'fewest');
document empty-files_modified behavior.