Skip to content

feat: auto-remap codebase after significant phase execution (closes #2003)#2605

Merged
trek-e merged 6 commits intomainfrom
feat/2003-codebase-drift-detector
Apr 23, 2026
Merged

feat: auto-remap codebase after significant phase execution (closes #2003)#2605
trek-e merged 6 commits intomainfrom
feat/2003-codebase-drift-detector

Conversation

@trek-e
Copy link
Copy Markdown
Collaborator

@trek-e trek-e commented Apr 22, 2026

Closes #2003

Summary

Adds a post-execute structural drift detector. After the last wave of
/gsd:execute-phase commits, the workflow compares the diff between
last_mapped_commit (stored in YAML frontmatter on each
.planning/codebase/*.md map file) and HEAD against the contents of
.planning/codebase/STRUCTURE.md. When the number of new structural
elements meets the configured threshold, GSD either warns the user or
auto-remaps the affected subtrees.

Four drift categories, with priority ordering (migration > route > barrel > new_dir) so each file is counted once at the most specific
level:

  1. New directory outside mapped paths
  2. New barrel export at (packages|apps)/<name>/src/index.*
  3. New migration file (supabase / prisma / drizzle / src/migrations / …)
  4. New route module under routes/ or api/

Non-blocking by contract. Four layers (detector try/catch, CLI
try/catch, SDK handler try/catch, workflow || echo fallback) ensure any
failure path — missing STRUCTURE.md, non-git cwd, mapper spawn failure,
invalid config — returns { skipped: true } and the phase continues to
verification. Drift detection cannot fail /gsd:execute-phase.

Changes

  • Detector libraryget-shit-done/bin/lib/drift.cjs (new). Pure:
    accepts parsed git-diff input + STRUCTURE.md content, returns a
    structured result. Exports classifyFile, detectDrift,
    chooseAffectedPaths, sanitizePaths, readMappedCommit,
    writeMappedCommit.
  • CLIverify codebase-drift subcommand in gsd-tools.cjs,
    implemented by cmdVerifyCodebaseDrift in verify.cjs.
  • SDKverifyCodebaseDrift handler in sdk/src/query/verify.ts,
    registered as verify.codebase-drift in sdk/src/query/index.ts.
    Delegates to the CJS implementation to keep drift logic in one place.
  • Configworkflow.drift_threshold (integer, default 3) and
    workflow.drift_action (warn | auto-remap, default warn) added
    to VALID_CONFIG_KEYS with enum/integer validation in config-set.
  • Workflow — new codebase_drift_gate step in execute-phase.md
    between schema_drift_gate and verify_phase_goal.
  • Mapper--paths <p1,p2,...> scope hint documented in both
    agents/gsd-codebase-mapper.md and get-shit-done/workflows/map-codebase.md,
    with traversal / absolute / metacharacter rejection.
  • Frontmatter round-triplast_mapped_commit stored at the top of
    each .planning/codebase/*.md file.

Documentation

  • docs/CONFIGURATION.md — rows for both new keys (docs-parity passes).
  • docs/ARCHITECTURE.md — post-execute drift gate section.
  • docs/AGENTS.md--paths flag on gsd-codebase-mapper.
  • docs/USER-GUIDE.md — behavior note + toggle commands.
  • docs/FEATURES.md — new 27a section with REQ-DRIFT-01..06.
  • docs/INVENTORY.md + docs/INVENTORY-MANIFEST.jsondrift.cjs
    listed (count 26 → 27).

Tests

  • tests/drift-detection.test.cjs (new) — 55 tests: classification,
    threshold gating at 2/3/4 elements, warn vs. auto-remap routing,
    affected-path scoping, --paths sanitization, frontmatter
    round-trip, defensive paths (missing STRUCTURE.md, malformed input,
    non-git repos), CLI JSON output, documentation parity.
  • Full suite: 5044 pass / 0 fail.

Design decisions

  • Frontmatter over sidecar JSON for last_mapped_commit: travels
    with git moves, survives per-document regeneration, no separate file
    lifecycle.
  • Substring match against STRUCTURE.md for isPathMapped: the map
    is free-form markdown, not a structured manifest. Cheap, no parser.
  • Category priority migration > route > barrel > new_dir: each
    file counts once at the most specific level.
  • Empty-tree SHA fallback (4b825dc6…) when last_mapped_commit
    is absent: "no baseline means everything is drift," deterministic.
  • Four layers of non-blocking — detector / CLI / SDK / workflow
    all wrap their logic so any single layer failing still produces a
    valid skipped result.
  • SDK handler delegates to gsd-tools.cjs rather than re-porting
    the detector to TypeScript, keeping drift logic in one canonical
    place.

Test plan

  • npm test — full suite green
  • node --test tests/drift-detection.test.cjs — 55 new tests pass
  • Manual: project with .planning/codebase/STRUCTURE.md
    gsd-sdk query verify.codebase-drift returns
    action_required: false immediately after mapping
  • Manual: introduce 3+ new barrels → rerun → action_required: true
    with directive: warn
  • Manual: set workflow.drift_action=auto-remap → rerun → confirm
    spawn_mapper: true and affected_paths populated
  • config-set workflow.drift_action sometimes rejected;
    config-set workflow.drift_threshold many rejected

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Incremental path-scoped codebase mapping via an optional --paths hint and a non-blocking post-execution drift detector that can warn or auto-remap affected subtrees.
    • New verify subcommand to check for codebase structural drift.
  • Documentation

    • Updated guides, architecture, workflows, and feature docs to describe drift detection, incremental mapping, config keys, and non-blocking behavior.
  • Tests

    • Added comprehensive tests for drift detection, path sanitization, config validation, and CLI integration.
  • Chores

    • Inventory/manifest updated to register drift tooling.

Adds a post-phase structural drift detector that compares the committed tree
against `.planning/codebase/STRUCTURE.md` and either warns or auto-remaps
the affected subtrees when drift exceeds a configurable threshold.

## Summary
- New `bin/lib/drift.cjs` — pure detector covering four drift categories:
  new directories outside mapped paths, new barrel exports at
  `(packages|apps)/*/src/index.*`, new migration files, and new route
  modules. Prioritizes the most-specific category per file.
- New `verify codebase-drift` CLI subcommand + SDK handler, registered as
  `gsd-sdk query verify.codebase-drift`.
- New `codebase_drift_gate` step in `execute-phase` between
  `schema_drift_gate` and `verify_phase_goal`. Non-blocking by contract —
  any error logs and the phase continues.
- Two new config keys: `workflow.drift_threshold` (int, default 3) and
  `workflow.drift_action` (`warn` | `auto-remap`, default `warn`), with
  enum/integer validation in `config-set`.
- `gsd-codebase-mapper` learns an optional `--paths <p1,p2,...>` scope hint
  for incremental remapping; agent/workflow docs updated.
- `last_mapped_commit` lives in YAML frontmatter on each
  `.planning/codebase/*.md` file; `readMappedCommit`/`writeMappedCommit`
  round-trip helpers ship in `drift.cjs`.

## Tests
- 55 new tests in `tests/drift-detection.test.cjs` covering:
  classification, threshold gating at 2/3/4 elements, warn vs. auto-remap
  routing, affected-path scoping, `--paths` sanitization (traversal,
  absolute, shell metacharacter rejection), frontmatter round-trip,
  defensive paths (missing STRUCTURE.md, malformed input, non-git repos),
  CLI JSON output, and documentation parity.
- Full suite: 5044 pass / 0 fail.

## Documentation
- `docs/CONFIGURATION.md` — rows for both new keys.
- `docs/ARCHITECTURE.md` — section on the post-execute drift gate.
- `docs/AGENTS.md` — `--paths` flag on `gsd-codebase-mapper`.
- `docs/USER-GUIDE.md` — user-facing behavior note + toggle commands.
- `docs/FEATURES.md` — new 27a section with REQ-DRIFT-01..06.
- `docs/INVENTORY.md` + `docs/INVENTORY-MANIFEST.json` — drift.cjs listed.
- `get-shit-done/workflows/execute-phase.md` — `codebase_drift_gate` step.
- `get-shit-done/workflows/map-codebase.md` — `parse_paths_flag` step.
- `agents/gsd-codebase-mapper.md` — `--paths` directive under parse_focus.

## Design decisions
- **Frontmatter over sidecar JSON** for `last_mapped_commit`: keeps the
  baseline attached to the file, survives git moves, survives per-doc
  regeneration, no extra file lifecycle.
- **Substring match against STRUCTURE.md** for `isPathMapped`: the map is
  free-form markdown, not a structured manifest; any mention of a path
  prefix counts as "mapped territory". Cheap, no parser, zero false
  negatives on reasonable maps.
- **Category priority migration > route > barrel > new_dir** so a file
  matching multiple rules counts exactly once at the most specific level.
- **Empty-tree SHA fallback** (`4b825dc6…`) when `last_mapped_commit` is
  absent — semantically correct (no baseline means everything is drift)
  and deterministic across repos.
- **Four layers of non-blocking** — detector try/catch, CLI try/catch, SDK
  handler try/catch, and workflow `|| echo` shell fallback. Any single
  layer failing still returns a valid skipped result.
- **SDK handler delegates to `gsd-tools.cjs`** rather than re-porting the
  detector to TypeScript, keeping drift logic in one canonical place.

Closes #2003

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds a non-blocking post-execution codebase drift detector and an incremental remap flow: a new drift library and verify command detect structural changes vs .planning/codebase/STRUCTURE.md, annotate mapping files with last_mapped_commit, and optionally auto-spawn the mapper with a validated --paths hint.

Changes

Cohort / File(s) Summary
Core drift detection library
get-shit-done/bin/lib/drift.cjs
New module classifying added files into drift categories, sanitizing and collapsing affected paths, computing action directives, and reading/writing last_mapped_commit frontmatter.
Verification command & SDK integration
get-shit-done/bin/lib/verify.cjs, sdk/src/query/verify.ts, sdk/src/query/index.ts
Adds verify codebase-drift CLI handler and SDK query verify.codebase-drift to run non-blocking drift detection and return structured JSON results.
Workflows & mapper prompts
get-shit-done/workflows/execute-phase.md, get-shit-done/workflows/map-codebase.md, agents/gsd-codebase-mapper.md
Execute-phase adds a non-blocking drift gate with optional auto-remap spawn; map-codebase introduces --paths parsing/validation and propagates scope hints to mapper prompts; mapper docs updated to accept --paths.
Configuration & CLI
get-shit-done/bin/lib/config.cjs, get-shit-done/bin/lib/config-schema.cjs, get-shit-done/bin/gsd-tools.cjs
Adds workflow.drift_threshold and workflow.drift_action keys with validation and CLI verify codebase-drift subcommand routing.
Tests
tests/drift-detection.test.cjs
Comprehensive unit and integration tests for file classification, detectDrift behavior, sanitization, frontmatter read/write, config validation, and CLI integration.
Docs & inventory
docs/AGENTS.md, docs/ARCHITECTURE.md, docs/CONFIGURATION.md, docs/FEATURES.md, docs/USER-GUIDE.md, docs/INVENTORY-MANIFEST.json, docs/INVENTORY.md
Documentation updates describing the drift gate, config keys, mapper --paths, last_mapped_commit frontmatter, and inventory/manifest additions.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ExecutePhase as Execute Phase
    participant DriftVerifier as Drift Verifier (verify tool)
    participant GitRepo as Git Repo
    participant StructureFile as STRUCTURE.md
    participant DriftDetector as Drift Detector (drift.cjs)
    participant Config as Config
    participant Mapper as GSD Mapper (auto-remap)

    Client->>ExecutePhase: /gsd:execute-phase completes
    ExecutePhase->>DriftVerifier: query verify.codebase-drift
    DriftVerifier->>StructureFile: read .planning/codebase/STRUCTURE.md
    StructureFile-->>DriftVerifier: content + last_mapped_commit
    DriftVerifier->>GitRepo: git diff last_mapped_commit..HEAD
    GitRepo-->>DriftVerifier: list of changed file paths
    DriftVerifier->>DriftDetector: detectDrift({files, structureMd, threshold})
    DriftDetector->>DriftDetector: classify files, sanitize/collapse paths
    DriftDetector-->>DriftVerifier: {actionRequired, directive, affectedPaths, message}
    DriftVerifier->>Config: read workflow.drift_action
    Config-->>DriftVerifier: 'warn' or 'auto-remap'
    alt action_required && directive == 'auto-remap'
        DriftVerifier->>Mapper: spawn gsd-codebase-mapper --paths [affectedPaths]
        Mapper->>StructureFile: update .planning/codebase/*.md
        StructureFile->>StructureFile: write last_mapped_commit: HEAD
    else action_required && directive == 'warn'
        DriftVerifier-->>Client: warning with suggested /gsd-map-codebase --paths
    end
    DriftVerifier-->>ExecutePhase: result (non-blocking)
    ExecutePhase->>Client: continue to verify_phase_goal
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

area: core, review: needs discussion

Suggested reviewers

  • glittercowboy

Poem

🐰 I hopped through diffs with eager paws,

found new paths, barrels, migrations and laws.
A little hint, a scoped remap dance—
commit in hand, we give mapping a chance.
Hop, remap, sync: the repo sings—✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.59% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding structural drift detection with auto-remapping capability after phase execution.
Description check ✅ Passed The pull request description comprehensively covers the feature with summary, changes, documentation, tests, design decisions, and test plan.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from #2003: structural drift detection comparing committed files against STRUCTURE.md, four drift categories (new directories, barrel exports, migrations, routes), configurable threshold triggering, and auto-remap vs warn actions.
Out of Scope Changes check ✅ Passed All changes are scoped to the drift detection feature: detector library, CLI/SDK handlers, config validation, workflow integration, mapper path hints, frontmatter utilities, tests, and documentation updates directly support the #2003 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/2003-codebase-drift-detector

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
get-shit-done/bin/lib/drift.cjs (1)

349-355: Potential issue: writeMappedCommit throws if file doesn't exist.

Unlike readMappedCommit which catches the exception and returns null, writeMappedCommit will throw if the file doesn't exist (line 350's readFileSync). This is likely intentional since you'd only call writeMappedCommit after the mapper has produced the file, but the asymmetry is worth noting.

If this is intentional (callers must ensure file exists), consider adding a brief comment. If it should be defensive, wrap in try/catch.

💡 Optional: Add defensive file existence check
 function writeMappedCommit(filePath, commitSha, isoDate) {
+  if (!fs.existsSync(filePath)) {
+    // Create minimal file with frontmatter only
+    const data = { last_mapped_commit: commitSha };
+    if (isoDate) data.last_mapped_at = isoDate;
+    fs.writeFileSync(filePath, serializeFrontmatter(data, ''));
+    return;
+  }
   const content = fs.readFileSync(filePath, 'utf8');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@get-shit-done/bin/lib/drift.cjs` around lines 349 - 355, writeMappedCommit
currently calls fs.readFileSync(filePath, 'utf8') and will throw if the file is
missing, creating an asymmetry with readMappedCommit which returns null on
missing files; either document the intended precondition or make it defensive by
checking existence or catching ENOENT: update writeMappedCommit (and its callers
if needed) so it first checks fs.existsSync(filePath) or wraps readFileSync in
try/catch, return a sensible value or no-op (or rethrow with clearer message)
when file is absent; reference the writeMappedCommit function and its use of
fs.readFileSync, fs.writeFileSync, parseFrontmatter and serializeFrontmatter
when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@agents/gsd-codebase-mapper.md`:
- Around line 101-103: The fenced code block containing the line "--paths
<p1>,<p2>,..." triggers MD040; add a language tag to the opening ``` fence (for
example "text") so the block becomes ```text and resolves the lint rule,
updating the block that contains the exact string "--paths <p1>,<p2>,..." in
agents/gsd-codebase-mapper.md.

In `@docs/CONFIGURATION.md`:
- Line 170: The docs row for workflow.drift_action uses colon-style command
tokens `/gsd:execute-phase` and `/gsd:map-codebase` which is inconsistent with
the rest of the guide; update those tokens to the standard space-separated
command format (e.g., `/gsd execute-phase` and `/gsd map-codebase --paths …`)
and keep them in inline code/backticks so the config key workflow.drift_action
and related workflow.drift_threshold text matches the repo's existing command
formatting.

In `@get-shit-done/workflows/execute-phase.md`:
- Around line 1296-1309: The two new fenced code blocks in
get-shit-done/workflows/execute-phase.md are missing language identifiers and
trigger markdownlint MD040; update both blocks by adding a language tag (use
"text") after the opening backticks—one for the block starting with "Codebase
drift detected: {N} structural element(s)..." and the other for the block
starting with "Task("—repeat the same fix for the second occurrence around lines
1316-1328.
- Line 1326: The auto-remap prompt references the undefined placeholder
AGENT_SKILLS_MAPPER which can leak into runtime; either define
AGENT_SKILLS_MAPPER (e.g., build it from the initialized AGENT_SKILLS
array/mapping) before the prompt or remove the placeholder from the template and
directly use AGENT_SKILLS; update the code that constructs the prompt to replace
"${AGENT_SKILLS_MAPPER}" with a real string (for example by adding a
mapper-building step that iterates AGENT_SKILLS and assigns the result to
AGENT_SKILLS_MAPPER) so the prompt never contains the literal placeholder.

In `@get-shit-done/workflows/map-codebase.md`:
- Around line 30-47: The workflow defines incremental-remap semantics in the
parse_paths_flag step but doesn't create a single normalized variable to
propagate validated paths to mappers; add a normalized shell variable (e.g.,
SCOPED_PATHS) that holds the validated comma-separated prefixes (or empty),
compute a PATH_SCOPE_HINT="--paths $SCOPED_PATHS" only when SCOPED_PATHS is
non-empty, and ensure every place that launches mappers (notably the
spawn_agents and sequential_mapping routines and any Task-mode prompt
construction that invokes gsd-codebase-mapper) appends ${PATH_SCOPE_HINT} into
the agent prompt/command so all spawned mappers receive the same deterministic
scope; keep the existing validation rules (reject .., leading /, shell
metacharacters) and preserve stamping behavior via
bin/lib/drift.cjs:writeMappedCommit.

---

Nitpick comments:
In `@get-shit-done/bin/lib/drift.cjs`:
- Around line 349-355: writeMappedCommit currently calls
fs.readFileSync(filePath, 'utf8') and will throw if the file is missing,
creating an asymmetry with readMappedCommit which returns null on missing files;
either document the intended precondition or make it defensive by checking
existence or catching ENOENT: update writeMappedCommit (and its callers if
needed) so it first checks fs.existsSync(filePath) or wraps readFileSync in
try/catch, return a sensible value or no-op (or rethrow with clearer message)
when file is absent; reference the writeMappedCommit function and its use of
fs.readFileSync, fs.writeFileSync, parseFrontmatter and serializeFrontmatter
when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8fe5d8c0-c253-422c-ae3e-c12595094a14

📥 Commits

Reviewing files that changed from the base of the PR and between 1f2850c and f48fe7d.

📒 Files selected for processing (18)
  • agents/gsd-codebase-mapper.md
  • docs/AGENTS.md
  • docs/ARCHITECTURE.md
  • docs/CONFIGURATION.md
  • docs/FEATURES.md
  • docs/INVENTORY-MANIFEST.json
  • docs/INVENTORY.md
  • docs/USER-GUIDE.md
  • get-shit-done/bin/gsd-tools.cjs
  • get-shit-done/bin/lib/config-schema.cjs
  • get-shit-done/bin/lib/config.cjs
  • get-shit-done/bin/lib/drift.cjs
  • get-shit-done/bin/lib/verify.cjs
  • get-shit-done/workflows/execute-phase.md
  • get-shit-done/workflows/map-codebase.md
  • sdk/src/query/index.ts
  • sdk/src/query/verify.ts
  • tests/drift-detection.test.cjs

Comment thread agents/gsd-codebase-mapper.md Outdated
Comment thread docs/CONFIGURATION.md Outdated
| `workflow.subagent_timeout` | number | `600` | Timeout in seconds for individual subagent invocations. Increase for long-running research or execution phases |
| `workflow.inline_plan_threshold` | number | `3` | Maximum number of tasks in a phase before the planner generates a separate PLAN.md file instead of inlining tasks in the prompt |
| `workflow.drift_threshold` | number | `3` | Minimum number of new structural elements (new directories, barrel exports, migrations, route modules) introduced during a phase before the post-execute codebase-drift gate takes action. See [#2003](https://github.com/gsd-build/get-shit-done/issues/2003). Added in v1.39 |
| `workflow.drift_action` | string | `warn` | What to do when `workflow.drift_threshold` is exceeded after `/gsd:execute-phase`. `warn` prints a message suggesting `/gsd:map-codebase --paths …`; `auto-remap` spawns `gsd-codebase-mapper` scoped to the affected paths. Added in v1.39 |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix command name formatting in the new drift-action docs.

The new row uses : command syntax, which is inconsistent with the rest of the docs and likely to mislead copy/paste usage.

✏️ Suggested doc fix
-| `workflow.drift_action` | string | `warn` | What to do when `workflow.drift_threshold` is exceeded after `/gsd:execute-phase`. `warn` prints a message suggesting `/gsd:map-codebase --paths …`; `auto-remap` spawns `gsd-codebase-mapper` scoped to the affected paths. Added in v1.39 |
+| `workflow.drift_action` | string | `warn` | What to do when `workflow.drift_threshold` is exceeded after `/gsd-execute-phase`. `warn` prints a message suggesting `/gsd-map-codebase --paths …`; `auto-remap` spawns `gsd-codebase-mapper` scoped to the affected paths. Added in v1.39 |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| `workflow.drift_action` | string | `warn` | What to do when `workflow.drift_threshold` is exceeded after `/gsd:execute-phase`. `warn` prints a message suggesting `/gsd:map-codebase --paths …`; `auto-remap` spawns `gsd-codebase-mapper` scoped to the affected paths. Added in v1.39 |
| `workflow.drift_action` | string | `warn` | What to do when `workflow.drift_threshold` is exceeded after `/gsd-execute-phase`. `warn` prints a message suggesting `/gsd-map-codebase --paths …`; `auto-remap` spawns `gsd-codebase-mapper` scoped to the affected paths. Added in v1.39 |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/CONFIGURATION.md` at line 170, The docs row for workflow.drift_action
uses colon-style command tokens `/gsd:execute-phase` and `/gsd:map-codebase`
which is inconsistent with the rest of the guide; update those tokens to the
standard space-separated command format (e.g., `/gsd execute-phase` and `/gsd
map-codebase --paths …`) and keep them in inline code/backticks so the config
key workflow.drift_action and related workflow.drift_threshold text matches the
repo's existing command formatting.

Comment thread get-shit-done/workflows/execute-phase.md Outdated
Comment thread get-shit-done/workflows/execute-phase.md
Comment thread get-shit-done/workflows/map-codebase.md
trek-e added 5 commits April 22, 2026 20:32
…Rabbit)

Comment 3127255180. Matches the convention used by every other command
reference in docs/CONFIGURATION.md.
Two CodeRabbit findings on the auto-remap branch of the drift gate:

- 3127255186 (must-fix): the mapper Task prompt referenced
  ${AGENT_SKILLS_MAPPER} but only AGENT_SKILLS (for gsd-executor) is
  loaded at init_context (line 72). Without this fix the literal
  placeholder string would leak into the spawned mapper's prompt.
  Add an explicit gsd-sdk query agent-skills gsd-codebase-mapper step
  right before the Task spawn.
- 3127255183: tag the warn-message and Task() fenced code blocks as
  text to satisfy markdownlint MD040.
CodeRabbit (review id 4158286952, comment 3127255190) flagged that the
parse_paths_flag step defined incremental-remap semantics but did not
inject a normalized variable into the spawn_agents and sequential_mapping
mapper prompts, so incremental remap could silently regress to a
whole-repo scan.

- Define SCOPED_PATHS / PATH_SCOPE_HINT in parse_paths_flag.
- Inject ${PATH_SCOPE_HINT} into all four spawn_agents Task prompts.
- Document the same scope contract for sequential_mapping mode.
CodeRabbit (review id 4158286952, drift.cjs:349-355 nitpick) noted that
readMappedCommit returns null on ENOENT but writeMappedCommit threw — an
asymmetry that breaks first-time stamping of a freshly produced doc that
the caller has not yet written.

- Catch ENOENT on the read; treat absent file as empty content.
- Add a regression test that calls writeMappedCommit on a non-existent
  path and asserts the file is created with correct frontmatter.
  Test was authored to fail before the fix (ENOENT) and passes after.
@github-actions github-actions Bot added size/XL and removed size/XL labels Apr 23, 2026
@trek-e
Copy link
Copy Markdown
Collaborator Author

trek-e commented Apr 23, 2026

CodeRabbit review response (review id 4158286952)

Finding Severity Action Commit / Reason
agents/gsd-codebase-mapper.md:101-103 — fenced block missing language (MD040) Minor Fixed 547c492 — tag fence as ```text
docs/CONFIGURATION.md:170 — drift_action row uses /gsd: colon syntax inconsistent with rest of docs Minor Fixed 447f67b — switched to /gsd-execute-phase / /gsd-map-codebase
get-shit-done/workflows/execute-phase.md:1296-1328 — two new fenced blocks missing language (MD040) Minor Fixed ced212d — tagged both as ```text
get-shit-done/workflows/execute-phase.md:1326${AGENT_SKILLS_MAPPER} referenced but never initialized; would leak literal placeholder into mapper prompt Major Fixed ced212d — added AGENT_SKILLS_MAPPER=$(gsd-sdk query agent-skills gsd-codebase-mapper 2>/dev/null || true) next to the existing AGENT_SKILLS initialization
get-shit-done/workflows/map-codebase.md:30-47--paths propagation not deterministic across spawn_agents/sequential_mapping Major Fixed f12e83f — defined SCOPED_PATHS + PATH_SCOPE_HINT in parse_paths_flag; injected ${PATH_SCOPE_HINT} into all four spawn_agents Task prompts and added an explicit scope contract to sequential_mapping
get-shit-done/bin/lib/drift.cjs:349-355writeMappedCommit throws ENOENT while readMappedCommit returns null (asymmetric) Nitpick Fixed 36b31ba — caught ENOENT on the read so absent files are treated as empty content; added regression test (writeMappedCommit creates the file when it does not exist) authored to fail before the fix and pass after

Verification: npm run test:coverage — 5045 tests pass, drift.cjs at 98.14% line coverage.

@trek-e trek-e merged commit 1a694fc into main Apr 23, 2026
11 of 12 checks passed
@github-actions github-actions Bot deleted the feat/2003-codebase-drift-detector branch April 23, 2026 01:21
trek-e added a commit that referenced this pull request Apr 23, 2026
…4811455435)

PR #2604 was rebased onto main before #2605 (drift.cjs) merged. The
pull_request CI runs against the merge ref (refs/pull/2604/merge),
which now contains 28 .cjs files in get-shit-done/bin/lib/, but
docs/INVENTORY.md headline still said "(27 shipped)".

inventory-counts.test.cjs failed with:
  AssertionError: docs/INVENTORY.md "CLI Modules (27 shipped)" disagrees
  with get-shit-done/bin/lib/ file count (28)

Rebased branch onto current origin/main (picks up drift.cjs row, which
was already added by #2605) and bumped the headline to 28.

Full suite: 5200/5200 pass.
trek-e added a commit that referenced this pull request Apr 23, 2026
…eview integrations (closes #2529) (#2604)

* feat(#2529): /gsd-settings-integrations — third-party integrations command

Adds /gsd-settings-integrations for configuring API keys, code-review CLI
routing, and agent-skill injection. Distinct from /gsd-settings (workflow
toggles) because these are connectivity, not pipeline shape.

Three sections:
- Search Integrations: brave_search / firecrawl / exa_search API keys,
  plus search_gitignored toggle.
- Code Review CLI Routing: review.models.{claude,codex,gemini,opencode}
  shell-command strings.
- Agent Skills Injection: agent_skills.<agent-type> free-text input,
  validated against [a-zA-Z0-9_-]+.

Security:
- New secrets.cjs module with ****<last-4> masking convention.
- cmdConfigSet now masks value/previousValue in CLI output for secret keys.
- Plaintext is written only to .planning/config.json; never echoed to
  stdout/stderr, never written to audit/log files by this flow.
- Slug validators reject path separators, whitespace, shell metacharacters.

Tests (tests/settings-integrations.test.cjs — 25 cases):
- Artifact presence / frontmatter.
- Field round-trips via gsd-tools config-set for all four search keys,
  review.models.<cli>, agent_skills.<agent-type>.
- Config-merge safety: unrelated keys preserved across writes.
- Masking: config-set output never contains plaintext sentinel.
- Logging containment: plaintext secret sentinel appears only in
  config.json under .planning/, nowhere else on disk.
- Negative: path-traversal, shell-metachar, and empty-slug rejected.
- /gsd:settings workflow mentions /gsd:settings-integrations.

Docs:
- docs/COMMANDS.md: new command entry with security note.
- docs/CONFIGURATION.md: integration settings section (keys, routing,
  skills injection) with masking documentation.
- docs/CLI-TOOLS.md: reviewer CLI routing and secret-handling sections.
- docs/INVENTORY.md + INVENTORY-MANIFEST.json regenerated.

Closes #2529

* fix(#2529): mask secrets in config-get; address CodeRabbit review

cmdConfigGet was emitting plaintext for brave_search/firecrawl/exa_search.
Apply the same isSecretKey/maskSecret treatment used by config-set so the
CLI surface never echoes raw API keys; plaintext still lives only in
config.json on disk.

Also addresses CodeRabbit review items in the same PR area:
- #3127146188: config-get plaintext leak (root fix above)
- #3127146211: rename test sentinels to concat-built markers so secret
  scanners stop flagging the test file. Behavior preserved.
- #3127146207: add explicit 'text' language to fenced code blocks (MD040).
- nitpick: unify masked-value wording in read_current legend
  ('****<last-4>' instead of '**** already set').
- nitpick: extend round-trip test to cover search_gitignored toggle.

New regression test 'config-get masks secrets and never echoes plaintext'
verifies the fix for all three secret keys.

* docs(#2529): bump INVENTORY counts post-rebase (commands 84→85, workflows 82→83)

* fix(test): bump CLI Modules count 27→28 after rebase onto main (CI #24811455435)

PR #2604 was rebased onto main before #2605 (drift.cjs) merged. The
pull_request CI runs against the merge ref (refs/pull/2604/merge),
which now contains 28 .cjs files in get-shit-done/bin/lib/, but
docs/INVENTORY.md headline still said "(27 shipped)".

inventory-counts.test.cjs failed with:
  AssertionError: docs/INVENTORY.md "CLI Modules (27 shipped)" disagrees
  with get-shit-done/bin/lib/ file count (28)

Rebased branch onto current origin/main (picks up drift.cjs row, which
was already added by #2605) and bumped the headline to 28.

Full suite: 5200/5200 pass.
trek-e added a commit that referenced this pull request Apr 23, 2026
…r progressive disclosure (closes #2551) (#2607)

* refactor(workflows): extract discuss-phase modes/templates/advisor for progressive disclosure (closes #2551)

Splits 1,347-line workflows/discuss-phase.md into a 495-line dispatcher plus
per-mode files in workflows/discuss-phase/modes/ and templates in
workflows/discuss-phase/templates/. Mirrors the progressive-disclosure
pattern that #2361 enforced for agents.

- Per-mode files: power, all, auto, chain, text, batch, analyze, default, advisor
- Templates lazy-loaded at the step that produces the artifact (CONTEXT.md
  template at write_context, DISCUSSION-LOG.md template at git_commit,
  checkpoint.json schema when checkpointing)
- Advisor mode gated behind `[ -f $HOME/.claude/get-shit-done/USER-PROFILE.md ]`
  — inverse of #2174's --advisor flag (don't pay the cost when unused)
- scout_codebase phase-type→map selection table extracted to
  references/scout-codebase.md
- New tests/workflow-size-budget.test.cjs enforces tiered budgets across
  all workflows/*.md (XL=1700 / LARGE=1500 / DEFAULT=1000) plus the
  explicit <500 ceiling for discuss-phase.md per #2551
- Existing tests updated to read from the new file locations after the
  split (functional equivalence preserved — content moved, not removed)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(#2607): align modes/auto.md check_existing with parent (Update it, not Skip)

CodeRabbit flagged drift between the parent step (which auto-selects "Update
it") and modes/auto.md (which documented "Skip"). The pre-refactor file had
both — line 182 said "Skip" in the overview, line 250 said "Update it" in the
actual step. The step is authoritative. Fix the new mode file to match.

Refs: PR #2607 review comment 3127783430

* test(#2607): harden discuss-phase regression tests after #2551 split

CodeRabbit identified four test smells where the split weakened coverage:

- workflow-size-budget: assertion was unreachable (entered if-block on match,
  then asserted occurrences === 0 — always failed). Now unconditional.
- bug-2549-2550-2552: bounded-read assertion checked concatenated source, so
  src.includes('3') was satisfied by unrelated content in scout-codebase.md
  (e.g., "3-5 most relevant files"). Now reads parent only with a stricter
  regex. Also asserts SCOUT_REF exists.
- chain-flag-plan-phase: filter(existsSync) silently skipped a missing
  modes/chain.md. Now fails loudly via explicit asserts.
- discuss-checkpoint: same silent-filter pattern across three sources. Now
  asserts each required path before reading.

Refs: PR #2607 review comments 3127783457, 3127783452, plus nitpicks for
chain-flag-plan-phase.test.cjs:21-24 and discuss-checkpoint.test.cjs:22-27

* docs(#2607): fix INVENTORY count, context.md placeholders, scout grep portability

- INVENTORY.md: subdirectory note said "50 top-level references" but the
  section header now says 51. Updated to 51.
- templates/context.md: footer hardcoded XX-name instead of declared
  placeholders [X]/[Name], which would leak sample text into generated
  CONTEXT.md files. Now uses the declared placeholders.
- references/scout-codebase.md: no-maps fallback used grep -rl with
  "\\|" alternation (GNU grep only — silent on BSD/macOS grep). Switched
  to grep -rlE with extended regex for portability.

Refs: PR #2607 review comments 3127783404, 3127783448, plus nitpick for
scout-codebase.md:32-40

* docs(#2607): label fenced examples + clarify overlay/advisor precedence

- analyze.md / text.md / default.md: add language tags (markdown/text) to
  fenced example blocks to silence markdownlint MD040 warnings flagged by
  CodeRabbit (one fence in analyze.md, two in text.md, five in default.md).
- discuss-phase.md: document overlay stacking rules in discuss_areas — fixed
  outer→inner order --analyze → --batch → --text, with a pointer to each
  overlay file for mode-specific precedence.
- advisor.md: add tie-breaker rules for NON_TECHNICAL_OWNER signals — explicit
  technical_background overrides inferred signals; otherwise OR-aggregate;
  contradictory explanation_depth values resolve by most-recent-wins.

Refs: PR #2607 review comments 3127783415, 3127783437, plus nitpicks for
default.md:24, discuss-phase.md:345-365, and advisor.md:51-56

* fix(#2607): extract codebase_drift_gate body to keep execute-phase under XL budget

PR #2605 added 80 lines to execute-phase.md (1622 -> 1702), pushing it over
the XL_BUDGET=1700 line cap enforced by tests/workflow-size-budget.test.cjs
(introduced by this PR). Per the test's own remediation hint and #2551's
progressive-disclosure pattern, extract the codebase_drift_gate step body to
get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md and leave
a brief pointer in the workflow. execute-phase.md is now 1633 lines.

Budget is NOT relaxed; the offending workflow is tightened.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auto-remap codebase after significant phase execution

1 participant