From 4eca5ac96c017b617ad300f789c2952963850da9 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sat, 20 Jun 2026 18:10:49 -0400 Subject: [PATCH 1/3] feat(#1452): add workflow.context_guard_mode to guard execute-phase against context exhaustion Proactive checkpoint guard fires at each wave boundary before spawning agents. Self-assesses context pressure against context-budget.md degradation tiers and warns (warn, default) or auto-invokes /gsd:pause-work (auto) when POOR tier (70%+) is detected. Config key validated; defaults to \"warn\". Co-Authored-By: Claude Sonnet 4.6 --- .changeset/1452-context-guard-mode.md | 5 + .../bin/shared/config-defaults.manifest.json | 3 +- .../bin/shared/config-schema.manifest.json | 1 + gsd-core/references/context-budget.md | 14 +- gsd-core/references/planning-config.md | 1 + gsd-core/workflows/execute-phase.md | 17 ++ src/config.cts | 7 + tests/feat-1452-context-guard-mode.test.cjs | 206 ++++++++++++++++++ tests/workflow-size-baseline.json | 2 +- 9 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 .changeset/1452-context-guard-mode.md create mode 100644 tests/feat-1452-context-guard-mode.test.cjs diff --git a/.changeset/1452-context-guard-mode.md b/.changeset/1452-context-guard-mode.md new file mode 100644 index 000000000..aacfa6713 --- /dev/null +++ b/.changeset/1452-context-guard-mode.md @@ -0,0 +1,5 @@ +--- +type: Added +pr: 1452 +--- +**`workflow.context_guard_mode` config key** — proactive context-exhaustion guard for `execute-phase`. Before each wave, the orchestrator self-assesses context pressure using the degradation signals defined in `context-budget.md`. Values: `warn` (default — emit warning and recommend `/gsd:pause-work` when POOR tier detected), `auto` (automatically invoke `/gsd:pause-work` before next wave), `off` (disable). Set via `gsd config-set workflow.context_guard_mode auto` for fully autonomous checkpoint behaviour. (#1452) diff --git a/gsd-core/bin/shared/config-defaults.manifest.json b/gsd-core/bin/shared/config-defaults.manifest.json index ed814b074..81818a03a 100644 --- a/gsd-core/bin/shared/config-defaults.manifest.json +++ b/gsd-core/bin/shared/config-defaults.manifest.json @@ -53,7 +53,8 @@ "post_planning_gaps": true, "security_enforcement": true, "security_asvs_level": 1, - "security_block_on": "high" + "security_block_on": "high", + "context_guard_mode": "warn" }, "planning": { "commit_docs": true, diff --git a/gsd-core/bin/shared/config-schema.manifest.json b/gsd-core/bin/shared/config-schema.manifest.json index fdd268892..c05f1be4d 100644 --- a/gsd-core/bin/shared/config-schema.manifest.json +++ b/gsd-core/bin/shared/config-schema.manifest.json @@ -56,6 +56,7 @@ "workflow.test_command", "workflow.build_command", "workflow.mvp_mode", + "workflow.context_guard_mode", "executor.stall_detect_interval_minutes", "executor.stall_threshold_minutes", "workflow.inline_plan_threshold", diff --git a/gsd-core/references/context-budget.md b/gsd-core/references/context-budget.md index b078f6271..7223976d0 100644 --- a/gsd-core/references/context-budget.md +++ b/gsd-core/references/context-budget.md @@ -29,14 +29,14 @@ Every workflow that spawns agents or reads significant content must follow these ## Context Degradation Tiers -Monitor context usage and adjust behavior accordingly: +Monitor context usage and adjust behavior accordingly. The `workflow.context_guard_mode` config key (values: `auto`, `warn`, `off`; default `warn`) controls how `execute-phase.md` responds when the guard fires at a wave boundary. -| Tier | Usage | Behavior | -|------|-------|----------| -| PEAK | 0-30% | Full operations. Read bodies, spawn multiple agents, inline results. | -| GOOD | 30-50% | Normal operations. Prefer frontmatter reads, delegate aggressively. | -| DEGRADING | 50-70% | Economize. Frontmatter-only reads, minimal inlining, warn user about budget. | -| POOR | 70%+ | Emergency mode. Checkpoint progress immediately. No new reads unless critical. | +| Tier | Usage | Behavior | Trigger Action (execute-phase) | +|------|-------|----------|-------------------------------| +| PEAK | 0-30% | Full operations. Read bodies, spawn multiple agents, inline results. | None | +| GOOD | 30-50% | Normal operations. Prefer frontmatter reads, delegate aggressively. | None | +| DEGRADING | 50-70% | Economize. Frontmatter-only reads, minimal inlining, warn user about budget. | Emit warning, continue | +| POOR | 70%+ | Emergency mode. Checkpoint progress immediately. No new reads unless critical. | `warn`: emit warning + recommend `/gsd:pause-work`. `auto`: invoke pause-work before next wave. `off`: proceed anyway. | ## Context Degradation Warning Signs diff --git a/gsd-core/references/planning-config.md b/gsd-core/references/planning-config.md index 6b35fc763..8ba0a5b5a 100644 --- a/gsd-core/references/planning-config.md +++ b/gsd-core/references/planning-config.md @@ -267,6 +267,7 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research": | `workflow.test_command` | string\|null | `null` | Any shell command | Regression/test gate command run by verify-phase, execute-phase, audit-fix, and post-merge-gate. Unset → GSD auto-detects (Makefile / package.json / Cargo.toml / go.mod / pyproject.toml). | | `workflow.build_command` | string\|null | `null` | Any shell command | Build gate command run by the post-merge gate. Unset → build step auto-detected/skipped. | | `workflow.mvp_mode` | boolean | `false` | `true`, `false` | Persist the MVP-mode flag in config so every phase defaults to MVP framing without requiring `--mvp` on the CLI. Resolved via the chain: `--mvp` CLI flag → ROADMAP.md `**Mode:** mvp` field → this config value → `false`. When `true`, the planner, executor, verifier, and discovery surfaces (progress, stats, graphify) all treat the phase as an MVP vertical slice (UI → API → DB) of one user-visible capability. | +| `workflow.context_guard_mode` | string | `"warn"` | `"auto"`, `"warn"`, `"off"` | Context exhaustion guard mode for `execute-phase`. Before each wave, the orchestrator self-assesses context pressure using degradation signals from `context-budget.md`. `"warn"` (default): emit a warning and recommend `/gsd:pause-work` when POOR tier is detected. `"auto"`: automatically invoke `/gsd:pause-work` before the next wave when POOR tier is detected. `"off"`: disable the guard. The guard is heuristic — no programmatic context-% API exists. | | `workflow.plan_chunked` | boolean | `false` | `true`, `false` | Enable chunked planning mode. When `true`, the plan-phase orchestrator splits the single long-lived planner Task into a short outline Task followed by N short per-plan Tasks (~3–5 min each). Each plan is committed individually for crash resilience. Particularly useful on Windows where long-lived Tasks may hang on stdio. Also activated by the `--chunked` flag. | | `workflow.code_review_command` | string\|null | `null` | Any shell command | External code-review command integrated into `/gsd:ship`. The diff is piped to the command via stdin; the command must output JSON with a `verdict` field (`"APPROVED"` or `"REVISE"`). Non-zero exit or `"REVISE"` verdict blocks the ship workflow. When unset, the built-in review flow runs. Example: `my-review-tool --review`. | | `workflow.inline_plan_threshold` | number | `2` | `0`–`10` | Plans with ≤N tasks execute inline instead of spawning a subagent | diff --git a/gsd-core/workflows/execute-phase.md b/gsd-core/workflows/execute-phase.md index ee99bb170..ee14707c6 100644 --- a/gsd-core/workflows/execute-phase.md +++ b/gsd-core/workflows/execute-phase.md @@ -493,6 +493,23 @@ increases monotonically across waves. `{status}` is `complete` (success), @~/.claude/gsd-core/references/execute-phase-wave-guard.md +0. **Context exhaustion guard — `context_guard` (BEFORE spawning, #1452):** + + Before spawning any agents for this wave, self-assess context pressure using the + degradation signals in `references/context-budget.md`. Signs of POOR tier (70%+): + increasing vagueness, skipped steps, silent partial completion. + + Read `workflow.context_guard_mode` from `.planning/config.json` (default `warn`). + + | Tier | `warn` (default) | `auto` | `off` | + |------|-----------------|--------|-------| + | PEAK / GOOD | No output | No output | No output | + | DEGRADING (50-70%) | Emit: "⚠ Context pressure DEGRADING — switching to frontmatter-only reads for remaining waves." Continue. | Same as warn | Skip | + | POOR (70%+) | Emit: "🛑 Context pressure POOR — risk of context exhaustion. Run `/gsd:pause-work` to checkpoint before this wave, then resume in a fresh session." Continue (user decides). | Invoke `/gsd:pause-work` immediately and halt. Do NOT spawn wave agents. | Skip | + + The guard is heuristic — no programmatic context-percentage API exists. Use your + assessment of degradation signals, not a fixed token count. + 1. **Intra-wave files_modified overlap check (BEFORE spawning):** Before spawning any agents for this wave, inspect the `files_modified` list of all plans diff --git a/src/config.cts b/src/config.cts index 652f1df60..493aecc88 100644 --- a/src/config.cts +++ b/src/config.cts @@ -239,6 +239,7 @@ function buildNewProjectConfig(userChoices: Record): Record { + test('is a recognized config key', () => { + const { VALID_CONFIG_KEYS } = require('../gsd-core/bin/lib/config.cjs'); + assert.ok( + VALID_CONFIG_KEYS.has('workflow.context_guard_mode'), + 'workflow.context_guard_mode should be in VALID_CONFIG_KEYS', + ); + }); +}); + +// ─── Default value ──────────────────────────────────────────────────────────── + +describe('workflow.context_guard_mode default value', () => { + let tmpDir; + beforeEach(() => { tmpDir = createTempProject(); }); + afterEach(() => { cleanup(tmpDir); }); + + test('defaults to warn in new project config', () => { + const result = runGsdTools('config-ensure-section', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `config-ensure-section failed: ${result.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual( + config.workflow.context_guard_mode, + 'warn', + 'workflow.context_guard_mode should default to "warn" — proactive checkpoint warning without auto-pausing workflows', + ); + }); +}); + +// ─── Round-trip ────────────────────────────────────────────────────────────── + +describe('workflow.context_guard_mode config round-trip', () => { + let tmpDir; + beforeEach(() => { + tmpDir = createTempProject(); + runGsdTools('config-ensure-section', tmpDir, { HOME: tmpDir }); + }); + afterEach(() => { cleanup(tmpDir); }); + + test('config-set warn persists to config.json', () => { + const setResult = runGsdTools('config-set workflow.context_guard_mode warn', tmpDir); + assert.ok(setResult.success, `config-set failed: ${setResult.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.context_guard_mode, 'warn'); + }); + + test('config-set auto persists to config.json', () => { + const setResult = runGsdTools('config-set workflow.context_guard_mode auto', tmpDir); + assert.ok(setResult.success, `config-set failed: ${setResult.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.context_guard_mode, 'auto'); + }); + + test('config-set off persists to config.json', () => { + const setResult = runGsdTools('config-set workflow.context_guard_mode off', tmpDir); + assert.ok(setResult.success, `config-set failed: ${setResult.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.context_guard_mode, 'off'); + }); + + test('persists in config.json as string', () => { + runGsdTools('config-set workflow.context_guard_mode warn', tmpDir); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.context_guard_mode, 'warn'); + assert.strictEqual(typeof config.workflow.context_guard_mode, 'string'); + }); + + test('rejects unknown mode values with clear error', () => { + const result = runGsdTools('config-set workflow.context_guard_mode aggressive', tmpDir); + assert.strictEqual(result.success, false); + assert.match(result.error, /Invalid workflow\.context_guard_mode 'aggressive'/); + assert.match(result.error, /auto, warn, off/); + }); + + test('rejects partial match values', () => { + const result = runGsdTools('config-set workflow.context_guard_mode warnmode', tmpDir); + assert.strictEqual(result.success, false); + assert.match(result.error, /Invalid workflow\.context_guard_mode 'warnmode'/); + }); +}); + +// ─── execute-phase contract ─────────────────────────────────────────────────── + +describe('execute-phase.md documents the context_guard step', () => { + let executePhase; + + beforeEach(() => { + executePhase = fs.readFileSync( + path.join(REPO_ROOT, 'gsd-core', 'workflows', 'execute-phase.md'), + 'utf-8', + ); + }); + + test('references workflow.context_guard_mode by canonical name', () => { + assert.ok( + executePhase.includes('workflow.context_guard_mode'), + 'execute-phase.md must reference workflow.context_guard_mode so runtimes resolve the config-driven behavior', + ); + }); + + test('defines context_guard step at wave boundaries', () => { + assert.ok( + executePhase.includes('context_guard') || executePhase.includes('context-guard'), + 'execute-phase.md must define a context_guard step that fires before each wave', + ); + }); + + test('references context-budget.md tiers in the guard step', () => { + assert.ok( + executePhase.includes('context-budget') || executePhase.includes('POOR') || executePhase.includes('DEGRADING'), + 'execute-phase.md context_guard must reference context-budget.md degradation tiers', + ); + }); +}); + +// ─── context-budget.md contract ────────────────────────────────────────────── + +describe('context-budget.md documents POOR-tier trigger action', () => { + let contextBudget; + + beforeEach(() => { + contextBudget = fs.readFileSync( + path.join(REPO_ROOT, 'gsd-core', 'references', 'context-budget.md'), + 'utf-8', + ); + }); + + test('defines POOR tier', () => { + assert.ok( + contextBudget.includes('POOR'), + 'context-budget.md must define the POOR tier', + ); + }); + + test('connects POOR tier to pause-work', () => { + assert.ok( + contextBudget.includes('pause-work') || contextBudget.includes('pause_work'), + 'context-budget.md POOR-tier rule must reference pause-work as the trigger action', + ); + }); + + test('documents context_guard_mode values', () => { + assert.ok( + contextBudget.includes('context_guard_mode'), + 'context-budget.md must document the workflow.context_guard_mode config key', + ); + }); +}); + +// ─── planning-config.md reference parity ───────────────────────────────────── + +describe('planning-config.md documents workflow.context_guard_mode', () => { + test('includes the key in the reference table', () => { + const planningConfig = fs.readFileSync( + path.join(REPO_ROOT, 'gsd-core', 'references', 'planning-config.md'), + 'utf-8', + ); + assert.ok( + planningConfig.includes('workflow.context_guard_mode'), + 'planning-config.md reference must include workflow.context_guard_mode so users know the config knob exists', + ); + }); +}); diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index 59a6de090..80f23b7d2 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -24,7 +24,7 @@ "docs-update.md": 55662, "edit-phase.md": 12883, "eval-review.md": 9923, - "execute-phase.md": 92851, + "execute-phase.md": 93995, "execute-plan.md": 31365, "explore.md": 10497, "extract-learnings.md": 12849, From a77f3c4b3ad005ca9abbd7c2216e8ac186c6b309 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sat, 20 Jun 2026 18:12:03 -0400 Subject: [PATCH 2/3] docs(#1452): document workflow.context_guard_mode in CONFIGURATION.md Co-Authored-By: Claude Sonnet 4.6 --- docs/CONFIGURATION.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index a21244574..71d37d540 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -262,6 +262,7 @@ All workflow toggles follow the **absent = enabled** pattern. If a key is missin | `workflow.tdd_mode` | boolean | `false` | Enable TDD pipeline as a first-class execution mode. When `true`, the planner aggressively applies `type: tdd` to eligible tasks (business logic, APIs, validations, algorithms) and the executor enforces RED/GREEN/REFACTOR gate sequence. An end-of-phase collaborative review checkpoint verifies gate compliance. Added in v1.36 | | `workflow.mvp_mode` | boolean | `false` | Persist the MVP-mode flag in config so every phase defaults to MVP framing without requiring `--mvp` on the CLI. Resolved via the precedence chain: `--mvp` CLI flag → ROADMAP.md `**Mode:** mvp` field → this config value → `false`. When `true`, the planner, executor, verifier, and discovery surfaces treat the phase as an MVP vertical slice (UI → API → DB) of one user-visible capability instead of a horizontal layer. | | `workflow.human_verify_mode` | string | `'end-of-phase'` | Controls human verification checkpoints. `'end-of-phase'` (default since #3309) suppresses `checkpoint:human-verify` tasks and embeds checks into `` blocks for end-of-phase review. `'mid-flight'` restores blocking checkpoint tasks. `checkpoint:decision` and `checkpoint:human-action` are unaffected. See [Checkpoints Reference](../gsd-core/references/checkpoints.md#checkpoint_types). | +| `workflow.context_guard_mode` | string | `'warn'` | Context exhaustion guard for `execute-phase`. Before each wave, the orchestrator self-assesses context pressure using the degradation signals defined in `context-budget.md`. `'warn'` (default) emits a warning and recommends `/gsd:pause-work` when POOR tier (70%+) is detected. `'auto'` automatically invokes `/gsd:pause-work` before the next wave. `'off'` disables the guard. Set via: `gsd config-set workflow.context_guard_mode auto`. Added in #1452. | | `workflow.cross_ai_execution` | boolean | `false` | Delegate phase execution to an external AI CLI instead of spawning local executor agents. Useful for leveraging a different model's strengths for specific phases. Added in v1.36 | | `workflow.cross_ai_command` | string | (none) | Shell command template for cross-AI execution. Receives the phase prompt via stdin. Must produce SUMMARY.md-compatible output. Required when `cross_ai_execution` is `true`. Added in v1.36 | | `workflow.cross_ai_timeout` | number | `300` | Timeout in seconds for cross-AI execution commands. Prevents runaway external processes. Added in v1.36 | From b63a500fad33f33dda01be2adf5289b411f1669a Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sat, 20 Jun 2026 18:38:20 -0400 Subject: [PATCH 3/3] fix(#1505): extract context_guard step to reference file; fix allow-test-rule see ref - Extract execute-phase.md context_guard step prose to gsd-core/references/execute-phase-context-guard.md (@-ref lazy load), bringing execute-phase.md back under the ADR-857 phase-6 size ceiling (92914 < 93166 bytes) - Fix allow-test-rule comment: add `see #1452` per ADR-456 lint rule - Update feat-1452 tests to check the reference file for extracted content - Register execute-phase-context-guard.md in INVENTORY-MANIFEST.json and INVENTORY.md Workflow References section - Regenerate workflow-size-baseline.json after file shrinkage Co-Authored-By: Claude Sonnet 4.6 --- docs/INVENTORY-MANIFEST.json | 1 + docs/INVENTORY.md | 1 + .../references/execute-phase-context-guard.md | 16 ++++++++++++++++ gsd-core/workflows/execute-phase.md | 17 +---------------- tests/feat-1452-context-guard-mode.test.cjs | 19 +++++++++++++------ tests/workflow-size-baseline.json | 2 +- 6 files changed, 33 insertions(+), 23 deletions(-) create mode 100644 gsd-core/references/execute-phase-context-guard.md diff --git a/docs/INVENTORY-MANIFEST.json b/docs/INVENTORY-MANIFEST.json index a08c253ea..3a0826733 100644 --- a/docs/INVENTORY-MANIFEST.json +++ b/docs/INVENTORY-MANIFEST.json @@ -214,6 +214,7 @@ "edge-probe.md", "execute-mvp-tdd.md", "execute-phase-between-wave-reset.md", + "execute-phase-context-guard.md", "execute-phase-wave-guard.md", "executor-examples.md", "gate-prompts.md", diff --git a/docs/INVENTORY.md b/docs/INVENTORY.md index a81c459ec..8d22872ed 100644 --- a/docs/INVENTORY.md +++ b/docs/INVENTORY.md @@ -301,6 +301,7 @@ Full roster at `gsd-core/references/*.md`. References are shared knowledge docum |-----------|------| | `agent-contracts.md` | Formal interface between orchestrators and agents. | | `context-budget.md` | Context window budget allocation rules. | +| `execute-phase-context-guard.md` | Context exhaustion guard step for `execute-phase` wave loop — `workflow.context_guard_mode` dispatch table (warn/auto/off) and POOR-tier pause-work trigger (#1452). | | `continuation-format.md` | Session continuation/resume format. | | `domain-probes.md` | Domain-specific probing questions for discuss-phase. | | `edge-probe.md` | Spec-phase edge-completeness probe — 8-category edge taxonomy, shape classification, and the `requirements → checks → verifier` resolution model (Step 5.5). | diff --git a/gsd-core/references/execute-phase-context-guard.md b/gsd-core/references/execute-phase-context-guard.md new file mode 100644 index 000000000..97b86021b --- /dev/null +++ b/gsd-core/references/execute-phase-context-guard.md @@ -0,0 +1,16 @@ +0. **Context exhaustion guard — `context_guard` (BEFORE spawning, #1452):** + + Before spawning any agents for this wave, self-assess context pressure using the + degradation signals in `references/context-budget.md`. Signs of POOR tier (70%+): + increasing vagueness, skipped steps, silent partial completion. + + Read `workflow.context_guard_mode` from `.planning/config.json` (default `warn`). + + | Tier | `warn` (default) | `auto` | `off` | + |------|-----------------|--------|-------| + | PEAK / GOOD | No output | No output | No output | + | DEGRADING (50-70%) | Emit: "⚠ Context pressure DEGRADING — switching to frontmatter-only reads for remaining waves." Continue. | Same as warn | Skip | + | POOR (70%+) | Emit: "🛑 Context pressure POOR — risk of context exhaustion. Run `/gsd:pause-work` to checkpoint before this wave, then resume in a fresh session." Continue (user decides). | Invoke `/gsd:pause-work` immediately and halt. Do NOT spawn wave agents. | Skip | + + The guard is heuristic — no programmatic context-percentage API exists. Use your + assessment of degradation signals, not a fixed token count. diff --git a/gsd-core/workflows/execute-phase.md b/gsd-core/workflows/execute-phase.md index ee14707c6..07af88c7d 100644 --- a/gsd-core/workflows/execute-phase.md +++ b/gsd-core/workflows/execute-phase.md @@ -493,22 +493,7 @@ increases monotonically across waves. `{status}` is `complete` (success), @~/.claude/gsd-core/references/execute-phase-wave-guard.md -0. **Context exhaustion guard — `context_guard` (BEFORE spawning, #1452):** - - Before spawning any agents for this wave, self-assess context pressure using the - degradation signals in `references/context-budget.md`. Signs of POOR tier (70%+): - increasing vagueness, skipped steps, silent partial completion. - - Read `workflow.context_guard_mode` from `.planning/config.json` (default `warn`). - - | Tier | `warn` (default) | `auto` | `off` | - |------|-----------------|--------|-------| - | PEAK / GOOD | No output | No output | No output | - | DEGRADING (50-70%) | Emit: "⚠ Context pressure DEGRADING — switching to frontmatter-only reads for remaining waves." Continue. | Same as warn | Skip | - | POOR (70%+) | Emit: "🛑 Context pressure POOR — risk of context exhaustion. Run `/gsd:pause-work` to checkpoint before this wave, then resume in a fresh session." Continue (user decides). | Invoke `/gsd:pause-work` immediately and halt. Do NOT spawn wave agents. | Skip | - - The guard is heuristic — no programmatic context-percentage API exists. Use your - assessment of degradation signals, not a fixed token count. +@~/.claude/gsd-core/references/execute-phase-context-guard.md 1. **Intra-wave files_modified overlap check (BEFORE spawning):** diff --git a/tests/feat-1452-context-guard-mode.test.cjs b/tests/feat-1452-context-guard-mode.test.cjs index 0e7031016..7d19d4619 100644 --- a/tests/feat-1452-context-guard-mode.test.cjs +++ b/tests/feat-1452-context-guard-mode.test.cjs @@ -1,4 +1,4 @@ -// allow-test-rule: source-text-is-the-product +// allow-test-rule: source-text-is-the-product see #1452 // The execute-phase.md workflow and context-budget.md reference ARE the runtime // contract loaded by AI runtimes. Asserting that the canonical wording for // `workflow.context_guard_mode` is present in those files is the only way to @@ -126,32 +126,39 @@ describe('workflow.context_guard_mode config round-trip', () => { describe('execute-phase.md documents the context_guard step', () => { let executePhase; + let contextGuardRef; beforeEach(() => { executePhase = fs.readFileSync( path.join(REPO_ROOT, 'gsd-core', 'workflows', 'execute-phase.md'), 'utf-8', ); + // The step body is extracted to a reference file loaded via @-ref in execute-phase.md. + // Both files together constitute the execute-phase wave-boundary contract. + const refPath = path.join(REPO_ROOT, 'gsd-core', 'references', 'execute-phase-context-guard.md'); + contextGuardRef = fs.existsSync(refPath) ? fs.readFileSync(refPath, 'utf-8') : ''; }); test('references workflow.context_guard_mode by canonical name', () => { + const combined = executePhase + '\n' + contextGuardRef; assert.ok( - executePhase.includes('workflow.context_guard_mode'), - 'execute-phase.md must reference workflow.context_guard_mode so runtimes resolve the config-driven behavior', + combined.includes('workflow.context_guard_mode'), + 'execute-phase.md (or its @-referenced execute-phase-context-guard.md) must reference workflow.context_guard_mode so runtimes resolve the config-driven behavior', ); }); test('defines context_guard step at wave boundaries', () => { assert.ok( executePhase.includes('context_guard') || executePhase.includes('context-guard'), - 'execute-phase.md must define a context_guard step that fires before each wave', + 'execute-phase.md must define a context_guard step (or @-ref to it) that fires before each wave', ); }); test('references context-budget.md tiers in the guard step', () => { + const combined = executePhase + '\n' + contextGuardRef; assert.ok( - executePhase.includes('context-budget') || executePhase.includes('POOR') || executePhase.includes('DEGRADING'), - 'execute-phase.md context_guard must reference context-budget.md degradation tiers', + combined.includes('context-budget') || combined.includes('POOR') || combined.includes('DEGRADING'), + 'execute-phase.md context_guard (or its @-referenced file) must reference context-budget.md degradation tiers', ); }); }); diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index 80f23b7d2..3f880b5cd 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -24,7 +24,7 @@ "docs-update.md": 55662, "edit-phase.md": 12883, "eval-review.md": 9923, - "execute-phase.md": 93995, + "execute-phase.md": 92914, "execute-plan.md": 31365, "explore.md": 10497, "extract-learnings.md": 12849,