* fix(#3087): restore 10 demoted directive phrases in gsd-planner.md CRITICAL/MANDATORY/ALWAYS/MUST emphasis was systematically removed in v1.38.4 (PR #2489) without documentation. Conflicts with PR #2489's own stated intent (sycophancy-hardening). Downstream effect: weaker adherence to user decisions and requirement coverage in v1.38.4-v1.40.x. Restored: CRITICAL: User Decision Fidelity (heading) CRITICAL: Never Simplify User Decisions (heading) Multi-Source Coverage Audit (MANDATORY in every plan set) Audit ALL four source types before finalizing Discovery is MANDATORY unless you can prove... ALWAYS split if: requirements MUST list requirement IDs from ROADMAP CRITICAL: Every requirement ID MUST appear in at least one plan ALWAYS use the Write tool to create files CRITICAL — File naming convention (enforced) Regression test: tests/bug-3087-planner-directive-language.test.cjs (10 assertions, one per restored directive — all pass). Suite: 6983/6983. Closes #3087. * fix(changeset+test): fix pr field to 3138, wrap readFileSync in try/catch
This commit is contained in:
5
.changeset/fix-3087-planner-directive-language.md
Normal file
5
.changeset/fix-3087-planner-directive-language.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 3138
|
||||
---
|
||||
**`gsd-planner.md` directive language restored** — 10 instances of `CRITICAL`/`MANDATORY`/`ALWAYS`/`MUST` emphasis were silently removed in v1.38.4 (PR #2489) without documentation, conflicting with that release's stated sycophancy-hardening intent. Downstream effect: planner output in v1.38.4–v1.40.x exhibited weaker adherence to user decisions and requirement coverage, as observed in #3087. Restored: `CRITICAL: User Decision Fidelity`, `CRITICAL: Never Simplify User Decisions`, `Multi-Source Coverage Audit (MANDATORY in every plan set)`, `Audit ALL four source types`, `Discovery is MANDATORY`, `ALWAYS split if:`, `requirements MUST list`, `CRITICAL: Every requirement ID MUST appear`, `ALWAYS use the Write tool`, and `CRITICAL — File naming convention`. Closes #3087.
|
||||
@@ -49,7 +49,7 @@ Before planning, discover project context:
|
||||
</project_context>
|
||||
|
||||
<context_fidelity>
|
||||
## User Decision Fidelity
|
||||
## CRITICAL: User Decision Fidelity
|
||||
|
||||
The orchestrator provides user decisions in `<user_decisions>` tags from `/gsd-discuss-phase`.
|
||||
|
||||
@@ -73,7 +73,7 @@ The orchestrator provides user decisions in `<user_decisions>` tags from `/gsd-d
|
||||
</context_fidelity>
|
||||
|
||||
<scope_reduction_prohibition>
|
||||
## Never Simplify User Decisions — Split Instead
|
||||
## CRITICAL: Never Simplify User Decisions — Split Instead
|
||||
|
||||
**PROHIBITED language/patterns in task actions:**
|
||||
- "v1", "v2", "simplified version", "static for now", "hardcoded for now"
|
||||
@@ -94,11 +94,11 @@ Do NOT silently omit features. Instead:
|
||||
3. The orchestrator presents the split to the user for approval
|
||||
4. After approval, plan each sub-phase within budget
|
||||
|
||||
## Multi-Source Coverage Audit
|
||||
## Multi-Source Coverage Audit (MANDATORY in every plan set)
|
||||
|
||||
@~/.claude/get-shit-done/references/planner-source-audit.md for full format, examples, and gap-handling rules.
|
||||
|
||||
Perform this audit for every plan set before finalizing. Check all four source types: **GOAL** (ROADMAP phase goal), **REQ** (phase_req_ids from REQUIREMENTS.md), **RESEARCH** (RESEARCH.md features/constraints), **CONTEXT** (D-XX decisions from CONTEXT.md).
|
||||
Audit ALL four source types before finalizing: **GOAL** (ROADMAP phase goal), **REQ** (phase_req_ids from REQUIREMENTS.md), **RESEARCH** (RESEARCH.md features/constraints), **CONTEXT** (D-XX decisions from CONTEXT.md).
|
||||
|
||||
Every item must be COVERED by a plan. If ANY item is MISSING → return `## ⚠ Source Audit: Unplanned Items Found` to the orchestrator with options (add plan / split phase / defer with developer confirmation). Never finalize silently with gaps.
|
||||
|
||||
@@ -160,7 +160,7 @@ Plan -> Execute -> Ship -> Learn -> Repeat
|
||||
|
||||
## Mandatory Discovery Protocol
|
||||
|
||||
Discovery is required unless you can prove current context exists.
|
||||
Discovery is MANDATORY unless you can prove current context exists.
|
||||
|
||||
**Level 0 - Skip** (pure internal work, existing patterns only)
|
||||
- ALL work follows established codebase patterns (grep confirms)
|
||||
@@ -362,7 +362,7 @@ Plans should complete within ~50% context (not 80%). No context anxiety, quality
|
||||
|
||||
## Split Signals
|
||||
|
||||
**Split if any of these apply:**
|
||||
**ALWAYS split if:**
|
||||
- More than 3 tasks
|
||||
- Multiple subsystems (DB + API + UI = separate plans)
|
||||
- Any task with >5 file modifications
|
||||
@@ -477,7 +477,7 @@ After completion, create `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md`
|
||||
| `depends_on` | Yes | Plan IDs this plan requires |
|
||||
| `files_modified` | Yes | Files this plan touches |
|
||||
| `autonomous` | Yes | `true` if no checkpoints |
|
||||
| `requirements` | Yes | Requirement IDs from ROADMAP. Every roadmap requirement ID MUST appear in at least one plan. |
|
||||
| `requirements` | Yes | **MUST** list requirement IDs from ROADMAP. Every roadmap requirement ID MUST appear in at least one plan. |
|
||||
| `user_setup` | No | Human-required setup items |
|
||||
| `must_haves` | Yes | Goal-backward verification criteria |
|
||||
|
||||
@@ -582,7 +582,7 @@ Only include what Claude literally cannot do.
|
||||
## The Process
|
||||
|
||||
**Step 0: Extract Requirement IDs**
|
||||
Read ROADMAP.md `**Requirements:**` line for this phase. Strip brackets if present (e.g., `[AUTH-01, AUTH-02]` → `AUTH-01, AUTH-02`). Distribute requirement IDs across plans — each plan's `requirements` frontmatter field lists the IDs its tasks address. Every requirement ID MUST appear in at least one plan. Plans with an empty `requirements` field are invalid.
|
||||
Read ROADMAP.md `**Requirements:**` line for this phase. Strip brackets if present (e.g., `[AUTH-01, AUTH-02]` → `AUTH-01, AUTH-02`). Distribute requirement IDs across plans — each plan's `requirements` frontmatter field MUST list the IDs its tasks address. **CRITICAL:** Every requirement ID MUST appear in at least one plan. Plans with an empty `requirements` field are invalid.
|
||||
|
||||
**Security (when `security_enforcement` enabled — absent = enabled):** Identify trust boundaries in this phase's scope. Map STRIDE categories to applicable tech stack from RESEARCH.md security domain. For each threat: assign disposition (mitigate if ASVS L1 requires it, accept if low risk, transfer if third-party). Every plan MUST include `<threat_model>` when security_enforcement is enabled.
|
||||
|
||||
@@ -1056,9 +1056,9 @@ Present breakdown with wave structure. Wait for confirmation in interactive mode
|
||||
<step name="write_phase_prompt">
|
||||
Use template structure for each PLAN.md.
|
||||
|
||||
Use the Write tool to create files — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
||||
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
||||
|
||||
**File naming convention (enforced):**
|
||||
**CRITICAL — File naming convention (enforced):**
|
||||
|
||||
The filename MUST follow the exact pattern: `{padded_phase}-{NN}-PLAN.md`
|
||||
|
||||
|
||||
46
tests/bug-3087-planner-directive-language.test.cjs
Normal file
46
tests/bug-3087-planner-directive-language.test.cjs
Normal file
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
// Regression guard for bug #3087.
|
||||
//
|
||||
// Between v1.38.3 and v1.38.4, agents/gsd-planner.md had 10 instances of
|
||||
// CRITICAL/MANDATORY/ALWAYS/MUST directive emphasis systematically removed.
|
||||
// The change was undocumented and conflicts with the stated intent of PR #2489
|
||||
// (the sycophancy-hardening pass that shipped in the same release). This test
|
||||
// enforces the restored directive language so the demotion cannot recur silently.
|
||||
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const ROOT = path.join(__dirname, '..');
|
||||
let src;
|
||||
try {
|
||||
src = fs.readFileSync(path.join(ROOT, 'agents', 'gsd-planner.md'), 'utf8');
|
||||
} catch (err) {
|
||||
throw new Error(`agents/gsd-planner.md not found — was the file renamed? (${err.message})`);
|
||||
}
|
||||
|
||||
const directives = [
|
||||
{ desc: 'User Decision Fidelity heading is CRITICAL', pattern: /## CRITICAL: User Decision Fidelity/ },
|
||||
{ desc: 'Never Simplify heading is CRITICAL', pattern: /## CRITICAL: Never Simplify User Decisions/ },
|
||||
{ desc: 'Multi-Source Audit heading is MANDATORY', pattern: /## Multi-Source Coverage Audit \(MANDATORY in every plan set\)/ },
|
||||
{ desc: 'Source audit uses "Audit ALL" imperative', pattern: /Audit ALL four source types before finalizing/ },
|
||||
{ desc: 'Discovery is MANDATORY', pattern: /Discovery is MANDATORY unless/ },
|
||||
{ desc: 'Split signals use ALWAYS', pattern: /\*\*ALWAYS split if:\*\*/ },
|
||||
{ desc: 'requirements field doc uses MUST', pattern: /\*\*MUST\*\* list requirement IDs from ROADMAP/ },
|
||||
{ desc: 'Step 0 has CRITICAL requirement ID directive', pattern: /\*\*CRITICAL:\*\* Every requirement ID MUST appear/ },
|
||||
{ desc: 'Write tool directive uses ALWAYS', pattern: /\*\*ALWAYS use the Write tool to create files\*\*/ },
|
||||
{ desc: 'File naming convention heading is CRITICAL', pattern: /\*\*CRITICAL — File naming convention \(enforced\):\*\*/ },
|
||||
];
|
||||
|
||||
for (const { desc, pattern } of directives) {
|
||||
test(`gsd-planner.md: ${desc}`, () => {
|
||||
assert.ok(
|
||||
pattern.test(src),
|
||||
`Directive enforcement missing from gsd-planner.md: "${desc}" — pattern ${pattern} not found. ` +
|
||||
`This language was demoted in v1.38.4 (PR #2489) without documentation, conflicting with ` +
|
||||
`the sycophancy-hardening intent of that release. See bug #3087.`,
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user