Skip to content

fix: install skills in flat structure for auto-discovery - #18

Merged
dean0x merged 4 commits into
mainfrom
fix/skills-flat-structure
Nov 4, 2025
Merged

dean0x merged 4 commits into
mainfrom
fix/skills-flat-structure

Conversation

@dean0x

@dean0x dean0x commented Nov 4, 2025

Copy link
Copy Markdown
Owner

Summary

Skills were not auto-activating because they were installed in a nested directory structure that Claude Code couldn't discover. This PR fixes the installation to use a flat structure.

Problem

  • Before: Skills installed to ~/.claude/skills/devflow/pattern-check/SKILL.md
  • Issue: Claude Code expects ~/.claude/skills/pattern-check/SKILL.md
  • Result: Skills existed but were never discovered or activated

Commands and agents support subdirectory namespacing, but skills require flat structure for auto-discovery.

Changes

Installation (init.ts)

  • Install skills directly under ~/.claude/skills/ instead of ~/.claude/skills/devflow/
  • Add migration cleanup for old nested structure
  • Preserve user's personal skills during upgrade

Uninstallation (uninstall.ts)

  • Remove individual skill directories (pattern-check, test-design, etc.)
  • Clean up old nested structure if it exists
  • Show count of removed skills in output

Documentation

  • Update CLAUDE.md with technical explanation of flat structure requirement
  • Keep README.md clean (users don't need implementation details)

Testing

  • ✅ Skills now appear in Claude's <available_skills>
  • ✅ All 7 skills discovered: pattern-check, test-design, code-smell, research, debug, input-validation, error-handling
  • ✅ Install/uninstall cycle works correctly
  • ✅ Migration from old nested structure works automatically
  • ✅ User's personal skills preserved during upgrade

Impact

Before this fix:

  • Skills were dormant (installed but not discovered)
  • No auto-activation
  • Users had non-functional skill system

After this fix:

  • Skills are discovered by Claude Code
  • Auto-activation works as documented
  • Clean migration for existing installations

🎯 This unblocks the core value proposition of DevFlow's quality enforcement system.

Dean Sharon added 4 commits November 3, 2025 22:54
Skills must be directly under ~/.claude/skills/ for Claude Code to
discover them. The nested devflow/ subdirectory was preventing
skill auto-activation.

Changes:
- Install skills to ~/.claude/skills/ (flat) instead of ~/.claude/skills/devflow/
- Add migration cleanup for old devflow/ subdirectory
- Preserve user's personal skills during cleanup
- Keep commands and agents in devflow/ subdirectories (working correctly)

Result:
- Skills are now discoverable: ~/.claude/skills/pattern-check/SKILL.md
- Old structure cleaned automatically during upgrade
- Commands still work: /devflow:code-review, /devflow:commit, etc.

Fixes auto-activation for all 7 skills:
- pattern-check, test-design, code-smell
- research, debug, input-validation, error-handling
Previously uninstall tried to remove ~/.claude/skills/devflow/ which
no longer exists since skills are now in flat structure.

Changes:
- Remove individual skill directories instead of devflow/ subdirectory
- Remove all 7 skills: pattern-check, test-design, code-smell, research, debug, input-validation, error-handling
- Also clean up old devflow/ subdirectory if it exists (migration)
- Show count of removed skills in output

Result:
- Uninstall now properly removes all skills
- Install/uninstall cycle works correctly
- Clean migration from old nested to new flat structure
Skills are now installed flat for Claude Code auto-discovery.
Updated documentation to reflect the correct structure.

Changes:
- README.md: Update installation path descriptions
- CLAUDE.md: Update file structure and installation paths
- Add note explaining why skills use flat structure

Before: ~/.claude/skills/devflow/pattern-check/
After:  ~/.claude/skills/pattern-check/
Users don't need to know about flat structure - that's an internal
implementation detail. Removed '(flat structure for auto-discovery)'
comments from README as they add confusion without user value.
@dean0x
dean0x merged commit 248ef8f into main Nov 4, 2025
@dean0x
dean0x deleted the fix/skills-flat-structure branch November 4, 2025 07:14
dean0x pushed a commit that referenced this pull request Mar 14, 2026
Batch 1 — Mechanical fixes:
- Fix duplicate step 5→6 in 4 explorer prompts (implement-teams.md)
- Fix fractional 2.5→3 renumbering in 4 reviewer prompts (code-review-teams.md)
- Fix fractional 1.5→2 renumbering in reviewer.md responsibilities
- Update stale counts: 24→31 skills, 8→17 plugins (file-organization.md)
- Add missing ambient-prompt.sh to hooks listing (file-organization.md)

Batch 2 — DRY extraction via knowledge-persistence skill:
- Create shared/skills/knowledge-persistence/SKILL.md with canonical procedure
  (ADR/PF formats, lock protocol, capacity cap, dedup, TL;DR update)
- Replace 8 inline extraction procedures with skill references in
  implement, code-review, debug, resolve (base + teams variants)
- Register skill in 4 plugin manifests (plugin.json + plugins.ts)

Batch 3 — Hook improvements:
- Collapse head+sed+grep into single sed -n for TL;DR extraction
- Guard section joins to prevent leading newlines when Section 1 skipped

Batch 4 — Quick fixes:
- Add TL;DR-only rationale comment to skimmer.md step 6
- Log createMemoryDir errors in verbose mode instead of silent catch
- Add 3 hook integration tests (TL;DR injection, no leading newlines,
  no knowledge section when files absent)

Issues dismissed: #9 (TL;DR sanitization — trust model), #10 (integrity
verification — instruction-enforced), #17 (mkdir failure test — low value),
#18 (phase ordering cosmetic), #19 (intentional scope exclusion)
dean0x pushed a commit that referenced this pull request Apr 16, 2026
Review walkthrough across 4 sessions resolved all 31 issues from the
2026-04-15_1022 code review (19 fixed, 5 rejected, 1 deferred, 6
pre-resolved).

Blocking fixes (sessions 1-2):
- CHANGELOG contradiction rewritten (#1)
- Worktree placeholder unified on "{worktree}" across 11 sites (#3)
- /debug migrated to index pattern (#4)
- KNOWLEDGE_CONTEXT quoting standardized, no inline fallback (#6)
- apply-knowledge skill defers to footer for paths (#7)
- Simplifier dropped from knowledge consumers; 4 agents canonicalized (#8)
- lstat+isFile guard on legacy-knowledge-purge unlink (#9)

Architecture + consistency fixes (session 2):
- Bare-form CLI removed, dispatch simplified to index-only (#10)
- code-review-teams template+table extraction (#12)
- Designer Apply Knowledge H2 added (#13)
- Teams phase numbering aligned (#14)
- loadKnowledgeContext + full subcommand removed entirely (#16)

Complexity + performance + testing + docs fixes (sessions 3-4):
- D-A filter extracted to isDeprecatedOrSuperseded predicate (#18)
- formatAdrLine/formatPfLine merged into formatEntryLine (#19)
- Shared test fixtures extracted to tests/knowledge/fixtures.ts (#21)
- Token claim "~250 tokens" dropped from 12 sites (#22)
- tmpdir cleanup added to test fixtures (#25)
- self-learning.md example and footer paths corrected (#28, #29)

28 files changed, 333 insertions, 524 deletions. 1021/1021 tests passing.
dean0x added a commit that referenced this pull request Sep 9, 2026
…t harness (#327)

## Problem Being Solved

The command→agent issue seam is untyped and five defects are live:
`/plan` never fetches issues, `/debug` passes an undeclared key, three
sites bypass the Git agent for issue operations, `resolve.mds`
contradicts `git.md`'s D9 authority, and `release.md` promises a step
that does not exist. The harness Phases 1–3 depend on does not exist in
a form that survives an agent rename.

## Key Changes to Highlight

**A1 (4aa15c5)** — Prompt-text fixes (19 edits) incl. the
`fetch-issues-batch` single-query rewrite [DR-07]

**A2 (b9d36ed)** — Two golden fixtures (git-agent, github-status-lines)
captured from the post-A1 tree

**A3 (6d595b6, 83594b9)** — Resolver, seam test, D11 union, guard-gap
closures, numeric-floor manifest [DR-27a], CI integration

**A4 (e8c4055)** — Docs sweep (platform-assumptions.md, CHANGELOG, KB
citations)

**Pipeline gate commits** — integration-test isolation, Simplify,
Scrutinize, alignment fixes, cleanup, knowledge write-back

**Post-review fixes (75f13e7a2207ac)** — containment gaps in
`setup-task` and batch template, Gate 0 / Step 0 contradiction in
`plan.mds`, `learn-conventions` commit step, `.claudeignore` gitignore
(marker v4), seam and guard repairs, golden re-capture, CHANGELOG
expansion, KB update

**Internal seam corrections (not user-visible):**
- `gh issue` routing through the Git agent (AC-0.4)
- D9 caller collapse (AC-0.5)

## Thirteen User-Visible Behaviour Changes

| # | Before | After |
|---|---|---|
| 1 | `/plan #42` parsed the reference and consumed a body it never
fetched | `/plan #42` spawns `OPERATION: fetch-issue`; `/plan #12 #15
#18` spawns `OPERATION: fetch-issues-batch` (one query, `≤50`,
`TRUNCATED ({n} not processed)`) |
| 2 | `/debug #42` passed `ISSUE: {issue number}` — a key `fetch-issue`
does not declare; the issue path never worked | `/debug #42` passes
`ISSUE_INPUT: {issue reference}` and the issue path works |
| 3 | `fetch-issue`/`fetch-issues-batch`: issue title, body, labels,
ACs, and dependencies reached Design agents unwrapped | All
remote-sourced fields per issue wrapped in `<untrusted-issue-body>` with
a data-only note appended; `### Suggested Branch` (locally-derived)
stays outside the block |
| 4 | `resolution-summary.md` emitted a bare `Tracked = (pending)` |
`Tracked = (pending)` names the DEGRADED reason, at all four sites |
| 5 | `release.md` promised *"close milestone"* — a step that does not
exist | The untruthful claim is deleted |
| 6 | `resolve.mds` authorised the Git agent to auto-resolve threads on
any of three verdicts: `FIXED`, `FALSE_POSITIVE`, or `BY_DESIGN` |
Auto-resolution authorised only when verdict is `FIXED` **and**
`commit_sha` is non-empty — matching the D9 contract `git.md` had always
enforced, closing a live divergence (closes PF-024) |
| 7 | `setup-task` emitted issue title, description, and ACs as bare
bullets; `fetch-issues-batch` template showed the wrapper on the first
issue only, leaving up to 49 uncontained; no op defended against remote
content containing the literal `</untrusted-issue-body>` closing marker
| `setup-task` wraps all remote-sourced fields; batch template
explicitly shows the wrapper on every entry; Principle 8 mandates
neutralising any closing marker found in remote content before wrapping,
with pointers from all four affected operations |
| 8 | `plan.mds` declared "Do not spawn any agents until Gate 0 is
confirmed" with no exception, directly contradicting the Step 0 issue
fetch — a session honouring the ban could silently skip the fetch | The
Gate 0 ban names the Step 0 issue fetch as its sole exception |
| 9 | `learn-conventions` wrote `.devflow/conventions.md` — a
git-tracked carve-out path — but included no commit step, leaving `??
.devflow/conventions.md` in `git status` on every fresh project |
`setup-task` step 4b commits `.devflow/conventions.md` after `git
checkout -b`, on the feature branch and never on the base branch, via
`git -C … commit --only -- .devflow/conventions.md` (never `git add -A`,
never push, never force, never amend), reporting `CONVENTIONS_COMMIT: …`
non-blockingly; `learn-conventions` no longer commits |
| 10 | `devflow init` wrote `.claudeignore` into any git repo but never
ignored the file, leaving `?? .claudeignore` in `git status` on every
fresh install | `.claudeignore` is a line of the devflow-managed
`.gitignore` block (marker `v4`); block presence is detected only by the
devflow-unique `!.devflow/conventions.md` sentinel — a user-authored
`.claudeignore` or `!.claudeignore` line is respected (the block is
appended without its own `.claudeignore` line; an un-ignore is never
overridden); the TypeScript function and the `ensure-root-gitignore`
shell twin are byte-identical and idempotent across 15 parity rows |

| 11 | `/plan`, `/debug` and the dynamic-build wave reader had no branch
for a `TRACEABILITY: DEGRADED` return from the Git agent — the status
line could be consumed as issue content | `/plan` warns, carries the
line verbatim into the report and runs Gate 0 with the bare issue
reference; `/debug` reports it verbatim and asks for the bug description
before generating hypotheses; the wave reader returns empty
ready/blocked sets with the DEGRADED rationale and the wave stops
(AC-0.6) |
| 12 | `fetch-issue` sent `#42` down the text-search path (first open
match for the literal `#42` — the wrong issue, or none);
`fetch-issues-batch` left `#`-prefixed tokens unspecified | Both strip a
leading `#` (`#42` ≡ `42`) before the numeric/text branch (AC-0.3) |
| 13 | A null GraphQL alias (unresolvable reference) in a batch could
abort the whole fetch | The alias is dropped, never aborts the batch,
and is reported as `NOT_FOUND ({refs})` alongside any `TRUNCATED` note;
comments are not fetched in batch mode (AC-0.3) |

**Honest label:** *"no change to the **GitHub rendering** of any
existing traceability artifact."* Not "no behaviour change" — see the
thirteen above.

## Breaking Changes

none.

## Reviewer Focus Areas

1. **Commit order** — A1 (4aa15c5) edits `git.md` only, no test file
touched. A2 (b9d36ed) contains only the two fixtures, captured from the
post-A1 tree. A3a/A3b split is pre-authorised. A4 (e8c4055) is the docs
sweep.

2. **RED proofs** — Verify seam known-bad at
`tests/seams/command-agent-input.test.ts` against the pre-A1 parser. D9
caller at `tests/git-agent.test.ts` asserts `resolve.mds` and
`dist/commands/resolve.md` carry the D9 rule literal from `git.md`.
`manage-debt` D4 at `git-agent.test.ts` (AC-0.6a). `gh issue` scope via
`collectGhIssueProseViolations` at `tests/build-mds.test.ts`. Batch
single-query [DR-07] at `git-agent.test.ts`.

3. **Numeric floor manifest [DR-27a]** —
`tests/guards/numeric-floor-manifest.test.ts` mechanises AC-0.17 against
`tests/fixtures/numeric-floors.json` (18 entries, occurrence-aware).
GREEN: no numeric literal in `tests/` decreases — with one argued
exception (see Deviations from the Plan §1).

4. **Recorded exceptions:**
- `src/assets/commands/release.md:85` — conventions read (allowlisted)
- `src/assets/commands/code-review.mds:77` — `gh pr view` (allowlisted)
- `src/assets/commands/bug-analysis.mds:44` — `gh pr view` (allowlisted)

5. **[DR-03]** — `npm run test:golden:update` requires a named target,
refuses `github-status-lines` without `--unfreeze`, has `--out-dir` so
tests never rewrite the frozen fixture.

## Deviations from the Plan

Four deliberate departures from stated acceptance criteria, each argued
below.

**1. A numeric floor was decreased (AC-0.17 exception).**
`issue-capture-contract-size` in `tests/fixtures/numeric-floors.json`
went from 5 → 3. AC-0.17 states no threshold may be lowered. This is a
deliberate, argued exception: the old value of 5 counted `ISSUE_ID` and
`ISSUE_URL`, neither of which had a producer anywhere in `git.md` or a
consumer in `plan.mds` — the floor was inflated by two erroneous
entries. Lowering from 5 to 3 corrects the manifest to match the actual
seam, not the imagined one. This is the only floor decrease in the
manifest.

**2. The golden regeneration commit (`3a95c92`) is not strictly
fixture-only.**
That commit carries `tests/goldens/github-status-lines.test.ts`
alongside the `.txt` fixture, because that file holds the fixture's own
byte/newline freeze baselines (`17_379→17_914`, `233→246`). Splitting
them would leave the tree red at the commit boundary, which this
branch's own rules forbid (all CI gates must be green at every commit).
The AC's intent — no behaviour change in the golden commit — is
preserved: the test file change is the baseline constant update, not a
logic change.

**3. The frozen `github-status-lines.txt` was unfrozen and re-captured
(AC-0.9 / DR-03).**
Third re-capture within Phase 0 (after `a5dd078` and `38db29e`), on
explicit user authorisation. The diff is exactly three hunks, all
genuine status-line vocabulary introduced by `75f13e7`: `setup-task`
containment, the per-issue batch wrapper, and the external-thread
neutralisation note. Context that matters for Phase 1: the fixture was
previously extracted by hard-coded line offsets, so it broke on any
insertion anywhere above a sampled range — it went red on a 26-line
insertion that changed no status line at all, and would have failed
outright at Phase 1 when `git.md` becomes MDS-generated. `e276175`
re-anchors extraction on content, proven faithful by reproducing the
pre-change fixture byte-for-byte from `b6928e5` before being run against
HEAD.

**4. Phase 0 ships thirteen user-visible changes, not five.**
Scope grew from review findings. Six of the thirteen were always on the
branch (`/plan` fetch, `/debug` key, containment, `Tracked` reason,
`close milestone`, D9 gate — the last was present but undeclared,
explaining why the CHANGELOG previously understated the count). Four are
new: the `setup-task`/batch/marker containment gaps, the Gate 0 / Step 0
contradiction, `learn-conventions` commit step, and `.claudeignore`
gitignore. `97f421a` and `7074733` are isolated commits and can be
lifted out if the reviewer prefers a tighter phase.

**5. Size floors → equality baselines (user decision D1).**
`GIT_MD_LINES`/`GIT_MD_CHARS`/`TOTAL_*` in
`tests/goldens/github-status-lines.test.ts` are equality baselines
against `tests/fixtures/golden/git-agent.md` (992 / 65,677 / TOTAL_CHARS
77,823), re-set in every golden-regeneration commit and deliberately not
registered in `tests/fixtures/numeric-floors.json`; the four `git-md-*`
manifest entries were deleted (17 remain). Red proof with the old
constants: `expected 992 to be 963` and `expected 65677 to be 61018`.

**6. Seam caller floor measured 13, not the planned 14.**
18 `## Operation:` sections, five without a live caller fence
(`learn-conventions`, `create-release`, `gather-release-evidence`,
`backlink-shipped-issues`, `check-ci-status` — the last is prose-only in
implement/resolve); floor raised 10 → 13.

**7. Gitignore append forms.**
Rules "continue an existing block" (v3→+`.claudeignore`,
v2→+conventions) use a no-blank-separator form so five pre-existing
byte-identity assertions stay valid; only "start a new block" inserts
the blank separator. A 15th parity row (a `.gitignore` whose only
content is the legacy `.devflow/` line) pins a `grep -v` exit-status
hazard found while aligning the twins.

**8. Batch step-5 wording.**
The plan's "`{n}` counts fetched issues only" was self-contradictory
against the literal `TRUNCATED ({n} not processed)`; git.md states the
invariant as two disjoint counts instead.

## Test Inventory (AC-0.13)

| Guard | File:Line (verify) | RED Mechanism / Probe Test Name | Status
|
|-------|-------------------|--------|--------|
| Seam forward | `tests/seams/command-agent-input.test.ts` | Forward:
`KEY: passed is declared` | RED on `/plan`, `/debug` undeclared keys |
| Seam reverse | `tests/seams/command-agent-input.test.ts` | Reverse:
`required INPUT is passed` | RED when spawn missing a declared input |
| Seam producer | `tests/seams/command-agent-input.test.ts` | Producer:
`issue_capture_contract()` searches agent source, consumer excluded; RED
proof via `ISSUE_URL` re-add | RED when agent source has no producer
(previously searched consumer — vacuous guard, now repaired) |
| Seam fence counts | `tests/seams/command-agent-input.test.ts` |
Per-agent-type fence count verification | RED when fence count doesn't
match expected |
| D9 caller | `tests/git-agent.test.ts` | `git.md`
`resolve-review-threads` section literal matches `resolve.mds` | RED on
caller contradiction |
| Manage-debt D4 | `tests/git-agent.test.ts` | `60000` char cap +
`DEGRADED` reason presence | RED when cap missing or reason empty |
| Batch bounds | `tests/git-agent.test.ts` | `≤50` issues, `TRUNCATED
({n} not processed)`, `## Issues Batch ({n} issues)` | RED when any
literal missing |
| `gh issue` scope | `tests/build-mds.test.ts` via
`collectGhIssueProseViolations` | 6 hosts checked for `compliance_gate`
adoption | RED when a host omits gate or violates allowlist |
| Batch single-query [DR-07] | `tests/git-agent.test.ts` | Asserts `gh
api graphql` not `gh issue view` loop | RED on incorrect API call
pattern |
| Containment (issue-body) | `tests/git-agent.test.ts` | Named op set:
{`fetch-issue`, `fetch-issues-batch`, `setup-task`}; floor 3 on
issue-body ops | RED: scores 0 on `main` — recorded RED proof
(previously the broad `>= 3` predicate passed on unmodified `main` via
pre-existing `<external-thread>` ops, validating nothing for issue-body;
now split and named) |
| Containment (ext-thread) | `tests/git-agent.test.ts` | Named op set:
{`fetch-review-threads`, `post-resolution-summary`, `post-wave-report`};
stabilisation guard | Labelled stabilisation — cannot fail on `main`
since those ops pre-existed; labelled as such rather than dressed up as
validation |
| D11 forward | `tests/git-agent.test.ts` | `>=8` posting ops +
known-bad synthetic corpus | RED when D11 sink count drops |
| D11 bypass | `tests/git-agent.test.ts` | Negative probe: summary ops
bypass redaction | RED when summary op rewrite adds scrub call |
| `INTERNAL_OPS` | `tests/registry-integrity.test.ts:397-405` |
`fetch-issues-batch` removed with SG-11 rationale | RED if entry present
(AC-0.11) |
| Golden byte-equality | `tests/goldens/git-agent-golden.test.ts` |
`<<<`/`>>>` marker device on mismatch | RED when git.md diverges from
fixture |
| Golden refusal | `tests/goldens/github-status-lines.test.ts` |
`test:golden:update -- github-status-lines` refuses without `--unfreeze`
| RED when refusal logic missing |
| Status-lines frozen | `tests/goldens/github-status-lines.test.ts` |
Fixture byte-equality, mtime unchanged | RED when fixture mutates across
suites |
| Numeric-floor manifest | `tests/guards/numeric-floor-manifest.test.ts`
| Every manifest entry decreases → RED | RED when any floor value
decreases |

| Agent-source resolver | `tests/harness/agent-source-resolver.test.ts`
| `gitAgentSinkCorpus` recursive walk finds nested
`references/tracker/github/fetch-issue.md`; `walkFiles` missing-dir →
`[]` and depth cap; `resolveAllAgents() ⊇ getAllAgentNames()` in
skill-references / agent-name-guards / agent-frontmatter | RED: nested
reference missing on flat `readdir`; resolver missing-`git` fixture |
| Seam caller floor | `tests/seams/command-agent-input.test.ts` | Floor
13 on live caller fences | RED: temporary floor 99 → `expected 13 to be
greater than or equal to 99` |
| Init logic exact-output | `tests/init-logic.test.ts` | Cases (a)–(f)
exact output + idempotency | RED: (a)–(c) returned `null`, (e) returned
a block, (f) `trimEnd` collapsed newlines |
| Shell-hooks parity | `tests/shell-hooks.test.ts` | 15-row parity
(bytes + booleans + TS/shell idempotency) | RED: 5 rows byte-diverged
including `grep -qF` matching `.claudeignore` as substring of
`!.claudeignore` |
| Golden-dimension baselines |
`tests/goldens/github-status-lines.test.ts` | Equality baselines:
`GIT_MD_LINES` 992, `GIT_MD_CHARS` 65,677 | RED: old constants — see
Deviations §5 |
| Conventions-commit guard | `tests/git-agent.test.ts` |
`collectConventionsCommitPlacementViolations` live guard + H10 probe |
RED: 4 violations on synthetic corpus with old learn-conventions commit
block and no step 4b |

## Byte/Char Baselines (P0-S1)

Post-Phase-0 (HEAD `b04e8f7`):
- `src/assets/agents/git.md` = `tests/fixtures/golden/git-agent.md`: 992
lines / 65,677 chars (JS `.length`) / 66,180 bytes (18 `## Operation:`
sections)
- `src/assets/skills/git/SKILL.md`: 9,204 chars / 283 lines
- `src/assets/skills/worktree-support/SKILL.md`: 2,942 chars / 92 lines
- **TOTAL_CHARS**: 77,823
- `tests/fixtures/golden/github-status-lines.txt`: 17,914 bytes / 246
newlines (byte-identical at every commit since `08fbdd4`)

Pre-Phase-0 (`main@e726874`):
- `git.md`: 938 lines / 59,376 bytes / 58,903 chars

Constants live in `tests/goldens/github-status-lines.test.ts` and are
asserted against the live files.

## Prefix-Shippability Evidence (§14 clause i–iv)

**Run on HEAD `a2207ac`:**

- `npm run build` exit 0 (13 MDS hosts compiled, `dist/commands/` 14
files)
- `npx tsc --noEmit` exit 0
- `npm test` exit 0 — 4,127 tests / 114 files
- `npm run test:integration` exit 0 — 48 tests / 5 files (preload suite
7/7: Simplify 18.0s, Scrutinize 13.3s, Review 11.5s, Code 17.2s, Design
13.1s, Git 13.0s, Research 12.6s)
- `npm pack --dry-run` exit 0 — 375 files
- Goldens SHA-256:
`f0e29b82106082b937f1e8804b998ca03e1454c08cb3ccbc1965390a95edd46f`
(status-lines) /
`6382d7698d80cdfdfe248ffe96db734a5836fb615ecd7e2634fbb7306b02384f`
(git-agent), `cmp` exit 0, fixture mtime unchanged across suites
- Clause (iii) negative grep: `PR link line|Branch token` in git.md → 0
· `docs/reference/platform-assumptions.md` first inbound reference added
(CLAUDE.md `## Reference Documents`, commit `90fd060`) — clause (iii)
miss resolved
- `git status --porcelain` empty

**Clause (ii) — file-residue half MECHANISED; prompt half still manual
(see Test Suite Status).**

## Test Suite Status

**Full suite: 4,127 tests / 114 files** — everything this PR modifies is
green.

A full-suite run produced 12 failures across 7 files: `redact-secrets`,
`decisions/ledger-ops`, `shell-hooks` json-helper describe,
`eager-memory-refresh`, `decisions/decisions-usage-scan`, `build-mds`,
`compliance-e2e`. **All 7 files pass 3/3 in isolation, 21 clean runs,
zero isolated failures.** Root cause is load-induced subprocess-spawn
contention under concurrent test workers, not regressions — none of the
7 files is in code this PR modifies.

**Integration: 5 files / 48 tests green.**
`tests/integration/subagent-skill-preload.test.ts` is excluded — it
spawns live `claude` against the developer's real `~/.claude` and has
historically committed to this repo mid-run.

**Clause (ii) mechanisation status:**
- **File-residue (MECHANISED):**
`tests/integration/clause-ii-file-residue.test.ts` packs a real tarball,
installs into a scratch `$HOME`, runs `devflow init --recommended` in a
throwaway git repo, and asserts no `??` untracked entries — with a
positive assertion that `.gitignore` was modified, so it cannot pass by
doing nothing. It found a real violation on first run (`??
.claudeignore`), now fixed by `7074733`.
- **Prompt half (STILL MANUAL):** the "no new prompt" half and the
`/plan → /implement → /code-review → /resolve → /release` walk-through
remain unverified. Remaining manual scope is narrowed to four
model-generalisation questions: (a) does the `<untrusted-issue-body>`
wrapper repeat across all 50 batched issues; (b) is the literal
`TRUNCATED ({n} not processed)` emitted; (c) does the agent build one
GraphQL query or fall back to 50 sequential `gh issue view` calls; (d)
does `plan.mds` Step 0 actually fire.

**CI:** build-and-test PASS (51s) · security/snyk PASS — all checks
green.

## PR-Template Checklist (D-B)

- [x] Test-inventory table present with a recorded red proof per guard
(AC-0.13)
- [x] CHANGELOG enumerates the thirteen user-visible changes with
before/after (AC-0.15)
- [ ] Prefix-shippability command sequence run and pasted — clauses (i),
(iii), (iv) above; **clause (ii) file-residue half mechanised (finds
real violations); prompt half and model-generalisation questions pending
a human**
- [x] AC-0.17 numeric-floor manifest guard green (with one argued
exception — see Deviations from the Plan §1)

## Known Deviations

- 42 commits, not 4 (A1→A2→A3a→A3b→A4 plus pipeline gates and
post-review fixes; A3 split pre-authorised; both goldens fixture-only —
with the exception noted in Deviations from the Plan §2)
- Three `gh pr view` exceptions, not two (code-review.mds:77,
bug-analysis.mds:44, resolve.mds:63 pre-exists on main)
- D9 authority cited as `git.md:resolve-review-threads` section, not a
line number
- `step 1c` retained; retired literal is `issue-first gate`
- P0-S13 landed as v2→v3 marker repair rather than deletion (v3
fast-path pinned by test)
- AC-0.10 split into two named assertions (issue-body and ext-thread)
rather than a single `>=3` floor derivation; see Deviations from the
Plan §1 and Test Inventory for detail
- `tests/integration/**` scope addition forced by wiring
`test:integration` into CI
- Two pre-existing load-sensitive suite timeouts pass in isolation
- `docs/reference/platform-assumptions.md` now has its first inbound
reference (CLAUDE.md `## Reference Documents`, commit `90fd060`) —
clause-(iii) miss resolved

## Commit Subjects

```
4aa15c5 fix(traceability): repair issue-seam prompt defects (A1)
b9d36ed test(golden): capture git-agent and github-status-lines goldens (A2)
6d595b6 test(harness): land A3a — resolver, seam test, golden infra, D11 union, op corrections
83594b9 test(guards): land A3b — guard-gap closures, CI integration, AC-0.7 resolver (P0-S21–S25)
e8c4055 docs(traceability): Phase-0 docs sweep — platform assumptions, CHANGELOG, KB citations (A4)
4df70e8 test(integration): scope subagent transcript scan to the spawned session
71a3ce4 test(integration): pin the spawned session id and diagnose non-spawns in the preload suite
fac739e refactor(tests): simplify harness helpers and guards
b1f38bc fix(tests): scrutinize fixes for Phase-0 harness
ef67f32 refactor(tests): remove unused transcript selector
4a00484 fix(traceability): contain every remote-sourced field in issue-fetch outputs
1ca307d test(harness): re-anchor status-line extraction and consolidate update-golden into tsx
a5dd078 test(golden): re-capture goldens after containment fix
5fc76aa docs(changelog): enumerate the plan's five user-visible changes
fe11930 test(harness): implement missing guards M1–M13 and Guard 6 anchor fix (F2)
21c9a4c test(harness): isolate the resolver fixture in a temp root
98a5bb5 fix(traceability): add D4 degradation to issue-fetch ops and restore body summarisation
1528bf1 test(harness): re-anchor status lines and re-measure byte baselines after D4 fix
38db29e test(golden): re-capture goldens after D4 degradation fix
27191ba docs(changelog): correct the containment before-state
0b44eae test(guards): widen containment and D4 predicates, restore AC-0.10 floor (MIS-1/MIS-2)
27d6fbd test(harness): mechanise literal-path and dist-throw contracts, real-collector probes, seam input scoping (MIS-5–9)
0f65757 docs(knowledge): add test-harness feature knowledge base
a1fe205 docs(changelog): keep the five enumerated user-visible changes
b6928e5 test(harness): relabel char baselines, pin the v3 fast-path, strip fix-round labels
75f13e7 fix(git-agent): contain setup-task issue bodies and harden containment markers
c7bff85 fix(plan): carve Step 0 out of the Gate 0 spawn ban and drop unbacked capture names
97f421a fix(git-agent): commit conventions.md so learn-conventions leaves a clean tree
b0d576a test(golden): regenerate git-agent fixture after containment fixes
948c440 test(integration): mechanise clause (ii) file-residue via tarball install into a scratch HOME
c56c105 test(guards): restore genuine containment validation and pin the matching op sets
0503e89 test(seams): source issue-capture producers from the agent, not the consumer
7074733 fix(init): gitignore the devflow-written .claudeignore (marker v4)
f7ac392 test(integration): assert clause (ii) file-residue now that .claudeignore is ignored
e276175 test(harness): anchor status-line extraction on content instead of line offsets
eec2ae3 docs(changelog): enumerate the full Phase 0 user-visible change set
3a95c92 test(golden): re-capture frozen status-lines fixture after containment changes
df34d77 docs(changelog): cite stable identifiers instead of volatile line numbers
0af035b chore(gitignore): adopt the v4 carve-out block in devflow's own repo
4ce6261 docs(changelog): drop a redundant operation-name repetition
a2207ac docs(knowledge): update test-harness, compliance-feature, installer-shadowing feature knowledge bases
08fbdd4 docs(test): correct stale shape count in hud-git header comments
69568f1 test(harness): resolve extractStatusLines through the agent resolver and walk skill references recursively
ac20850 test(guards): repoint agent enumerations through resolveAllAgents (AC-0.7)
32d0389 test(guards): fix the stale seam-caller rationale and name the retired-wording list a denylist
f4db128 fix(init): detect the devflow gitignore block by its own sentinel and respect user .claudeignore entries
b06a4dd fix(commands): handle TRACEABILITY: DEGRADED at the three issue-fetch callers
ae62d0a fix(git-agent): commit conventions on the feature branch, accept #-prefixed refs, drop unresolved batch refs
23ea357 test(golden): regenerate git-agent fixture after conventions-commit and ref-handling fixes
6b70215 test(golden): pin git.md size to the golden as equality baselines
8de1f3e test(git-agent): guard the conventions-commit placement and the batch NOT_FOUND rule
754379b docs(changelog): describe the caller-side conventions commit, the sentinel semantics, and the new degradation handling
90fd060 docs: describe the tests/ harness, the golden update ritual, and platform assumptions
1070758 refactor(tests): drop unused name binding in skill-references agent loops
d2cebfe docs(changelog): state only what the gitignore and #-ref fixes actually do
19fdea5 docs(init): name both block shapes in the ensureDevflowGitignore contract
5efff97 test(harness): bound walkFiles, repoint the last literal agent reads, and refresh three stale comments
b04e8f7 docs(knowledge): refresh test-harness and installer-shadowing knowledge bases for the Phase-0 gap closure
```

## Related Issues

Closes #322 · Tracking: #321
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant