fix(v2): three project-knowledge ship-blockers#182
Conversation
RED phase — new describe block in legacy-knowledge-purge.test.ts covers the format-discriminator approach (self-learning: source marker) and TOCTOU hardening. Migration registry tests in migrations.test.ts assert v3 entry presence, ordering, description, and independent execution when v2 is already applied. Part of v2.0.0 ship-blocker rollup.
GREEN phase — adds purgeAllPreV2Knowledge() to legacy-knowledge-purge.ts using a format discriminator: any ## ADR-NNN: or ## PF-NNN: section lacking "- **Source**: self-learning:" is pre-v2 seeded content and is removed. Fixes the gap where the v2 migration's hardcoded allow-list only covered 4 of 10 seeded entries, leaving 7 in upgraded projects. Also adds MIGRATION_PURGE_LEGACY_KNOWLEDGE_V3 to migrations.ts registry (per-project scope, runs independently of v2 on each devflow init). v2 function and migration entry are untouched — already-applied migrations remain stable. Part of v2.0.0 ship-blocker rollup.
8 new tests in reconcile-manifest — self-heal (Fix 2) describe block: - anchor in file + ready log entry + missing manifest → status=created, manifest reconstructed - anchor in file, no matching log entry → no-op (user-curated) - anchor heading does not match any ready log pattern → no-op - multiple log entries match same anchor → no-op silently (D-D ambiguity guard) - pitfalls.md scanned with PF- prefix - multiple anchors healed in a single reconcile pass - registerUsageEntry called with correct anchorId - result JSON always includes healed counter (including zero case) Co-Authored-By: Claude <noreply@anthropic.com>
…ow (Fix 2) Closes the crash window between render-ready writing the knowledge file (~line 1305) and updating the log/manifest (~lines 1337/1340). If the process dies in that window, the anchor exists in decisions.md/pitfalls.md but the log still shows status=ready and the manifest has no entry — next render-ready re-appends a duplicate. Changes: - Add findUnmanagedAnchors() helper: scans decisions.md + pitfalls.md for ADR-NNN / PF-NNN anchors not tracked in the manifest. Uses literal regexes (not dynamic) to avoid ReDoS surface (Snyk-clean for new code). - Add heal block in reconcile-manifest handler: for each unmanaged anchor, find a matching ready log observation by normalized pattern. If exactly one match (D-D ambiguity guard), upgrade status=created, reconstruct manifest entry, call registerUsageEntry(), increment healed counter. - Add healed counter to all result JSON shapes (main path + early-return paths). - Strip anchorId in sectionRe construction via safeAnchorId for defense-in-depth. No new locks: heal block runs inside the existing .learning.lock already held by reconcile-manifest. registerUsageEntry reads/writes .knowledge-usage.json directly (same as render-ready, which also skips the knowledge-usage lock). Co-Authored-By: Claude <noreply@anthropic.com>
Tests assert structural invariants across all three resolve surfaces (base command, teams variant, ambient orchestration skill) and resolver agent: KNOWLEDGE_CONTEXT propagation, D-A filtering instructions, D-B citation aggregation, and Apply Knowledge section constraints. Also unit-tests the Deprecated/Superseded filter algorithm directly. Co-Authored-By: Claude <noreply@anthropic.com>
Adds KNOWLEDGE_CONTEXT propagation across all three resolve surfaces
(base command, teams variant, ambient orchestration skill) and the
shared Resolver agent:
- resolve.md: Step 0d reads decisions.md + pitfalls.md per worktree,
strips Deprecated/Superseded sections (D-A), passes KNOWLEDGE_CONTEXT
to Phase 4 Resolver spawn; Phase 5 extracts citations; Phase 8 output
artifact gains ## Knowledge Citations section (D-B)
- resolve-teams.md: identical Step 0d + teammate prompt KNOWLEDGE_CONTEXT
variable + Phase 5 citation extraction + ## Knowledge Citations artifact
- resolve:orch SKILL.md: Phase 1.5 loads knowledge for ambient single-project
context; Phase 4 passes KNOWLEDGE_CONTEXT; Phase 6 includes citations section
- resolver.md: KNOWLEDGE_CONTEXT declared optional in Input Context;
Apply Knowledge section added with ADR/PF citation format and explicit
hallucination guard ("Cite only IDs that appear verbatim — do not fabricate")
Co-Authored-By: Claude <noreply@anthropic.com>
…p-blocker fixes Documents three v2.0.0 fixes already implemented on this branch: - Fix 1: /resolve reads decisions.md + pitfalls.md and cites ADR/PF IDs inline; aggregates Knowledge Citations section in resolution-summary.md - Fix 2: reconcile-manifest self-heals render-ready crash-window duplicates; adds healed counter to output - Fix 3: purge-legacy-knowledge-v3 migration removes all pre-v2 seeded entries via source-marker discriminator, replacing the v2 hardcoded allow-list Co-Authored-By: Claude <noreply@anthropic.com>
Eliminate the tldrUpdated intermediate variable in purgeAllPreV2Knowledge by changing const to let for updatedContent, matching the established pattern in purgeLegacyKnowledgeEntries. Removes naming asymmetry between the two functions.
Three findings from the 9-pillar self-review of the ship-blocker fix branch:
MEDIUM (Fix 2 robustness): findUnmanagedAnchors now requires the
"- **Source**: self-learning:" marker on each candidate section.
Pre-v2 seeded entries lack this marker; without the check, a current
ready obs whose pattern normalises to an old seed heading (e.g.,
"use result types everywhere") could be falsely paired with the
seeded anchor ID. The v3 migration would later delete that seeded
entry, leaving the manifest pointing at a missing anchor and
deprecating the obs unfairly. Added regression test "heal: pre-v2
anchor lacking self-learning source marker → no-op even when log
obs would match".
LOW (Fix 1 robustness): resolver.md Apply Knowledge now explicitly
guards against the literal "(none)" value that the orchestrator
emits when knowledge files are absent or empty. Previous wording
("if KNOWLEDGE_CONTEXT is non-empty") was strictly true for "(none)"
as a string and could lead an LLM to scan a no-op marker.
LOW (docs accuracy): CLAUDE.md and docs/self-learning.md referred to
the v2 migration as "purge-legacy-knowledge" (no -v2 suffix). The
actual registry ID is "purge-legacy-knowledge-v2". Both occurrences
corrected. CLAUDE.md self-heal description updated to mention the
marker requirement; self-learning.md heal step 1 updated similarly.
Tests: 943 → 944 passing (one new regression test).
Review Summary: 4 Blocking Issues FoundBased on comprehensive code review across 9 specialized reviewers, I found 4 blocking issues that must be addressed before merge. All are ≥80% confidence and require architectural or correctness fixes. 1. Architecture (88%): Heal path skipped when manifest doesn't existFile: The reconcile-manifest handler exits early when the manifest file is missing, skipping the heal block entirely. This creates a scenario gap for the first-ever render-ready crash: when render-ready crashes between writing the knowledge file and writing the manifest, the next session's reconcile sees no manifest and skips healing. The subsequent render-ready run then re-renders the same observation, producing the duplicate anchor Fix 2 is supposed to prevent. Required fix: Allow reconcile to run even without a manifest. Construct an empty in-memory manifest when the log file exists but the manifest doesn't, so the heal block can still pair orphan anchors with ready observations. Add a regression test for this first-render scenario. 2. Complexity (88%): Reconcile-manifest handler exceeds ALL HIGH thresholdsFile: The case handler now hits three HIGH-severity complexity criteria simultaneously:
The handler weaves four distinct phases (validation, deletion-and-edit, heal, commit/release) into a single function body, making it impossible to unit-test heal logic independently or reason about phase ordering. Required fix: Extract the four phases to named helper functions (, , , ) so the case body becomes pure orchestration. Each helper becomes independently testable. 3. Security (85%): Lost-write race onFile: The heal block calls
This is a data-integrity bug affecting the manifest's secondary index. Required fix: Acquire 4. Performance (90%): KNOWLEDGE_CONTEXT fan-out without filteringFile: The orchestrator loads ~30KB (~7.5K tokens) of concatenated decisions.md + pitfalls.md content and passes it verbatim to every Resolver spawned in Phase 4. On a large review with N parallel Resolvers and ~10 batches, this means 10 × 7.5K = 75K tokens of duplicate knowledge context paid regardless of relevance. As knowledge corpus grows toward the stated ceiling (100 entries per file), per-Resolver token cost can double. This is not a correctness bug but a design issue that blocks v2.0.0 ship. Required fix (recommended): Pre-filter KNOWLEDGE_CONTEXT per-batch by file/area before passing to each Resolver. Orchestrator can match batch issues to knowledge sections by file mentions or use cite counts from Summary Table
All four require code changes before merge. Estimated effort: 2-4 hours for architectural refactoring (#1, #2, #3); 1-2 hours for performance design (#4). Review Artifacts: All detailed findings available in:
|
Additional Findings: Should-Fix & Pre-existingThe 4 blocking issues above require merge-blocking fixes. Beyond those, the reviews identified 10 should-fix issues and 8 pre-existing issues that should be addressed in this PR or tracked for follow-up. Should-Fix Issues (Lower confidence or smaller scope)Architecture
Complexity
Security
Testing
TypeScript
Consistency
Documentation
Pre-existing Issues (Not Blocking This PR)These were in the codebase before this PR and are noted for the maintenance backlog:
Recommendation Summary
Action: Address the 4 blocking issues in this PR. Should-fix items can ride in a follow-up cleanup PR if time is tight, but doing them now improves quality and reduces future drift. Pre-existing issues belong in the maintenance backlog (many are already tracked as PF-NNN pitfalls in All review reports (security, architecture, performance, complexity, consistency, regression, testing, typescript, documentation) are available at: |
Review Process SummaryReviewed by: 9 specialized agents (security, architecture, performance, complexity, consistency, regression, testing, typescript, documentation) Review scope: 14 files, +1277 / -14 lines, 9 commits Confidence filtering: Only findings ≥80% confidence posted as blockers. 60-79% confidence items consolidated into the should-fix list above. Deduplication strategy:
Test coverage verification:
Rate limit awareness:
Known limitations:
Next steps for maintainer:
Review reports saved at:
Total review content: 1,478 lines of detailed analysis |
Three bullets mistakenly added to the sealed [2.0.0] entry are moved to [Unreleased] under the correct Keep-a-Changelog categories: - /resolve knowledge integration → ### Added - Reconciler self-heal → ### Fixed (expanded with marker-gating detail) - Legacy purge v3 migration → ### Fixed The self-heal bullet now documents that heal is gated by the "- **Source**: self-learning:" marker, preventing false-positive heals against pre-v2 seeded entries (bd1c92f correctness fix, previously only in code/tests but absent from the changelog). Co-Authored-By: Claude <noreply@anthropic.com>
…, rename purge function, tighten types, fix regex, add concurrency tests
Con1: MIGRATION_PURGE_LEGACY_KNOWLEDGE_V3 now uses named infos binding before
returning, matching the named-binding pattern used by v2 and shadow-overrides.
C2: Extract withKnowledgeFiles(memoryDir, filePrefixPairs, rewriteContent)
shared helper owning lock acquire, file loop, TL;DR rewrite, and finally-cleanup.
Both purge functions delegate to it with their respective predicates, eliminating
~90% of duplicated logic.
Con2: Rename purgeAllPreV2Knowledge to purgeAllPreV2KnowledgeEntries to restore
the Entries suffix symmetry with its sibling purgeLegacyKnowledgeEntries.
Update the sole caller in migrations.ts.
Con3: Add comment block above MIGRATIONS array documenting -vN and -vN-{tag}
suffix conventions and the append-only constraint.
TS1: Change (decisions|pitfalls) to (?:decisions|pitfalls) in both TL;DR regex
replacements — capture group was unused.
TS2: Replace [string, string][] with KnowledgeFilePair = readonly [string, 'ADR' | 'PF']
so the prefix discriminant is type-enforced at call sites (avoids PF-005).
T4: Add concurrent-caller tests verifying two simultaneous callers serialize via
the mkdir lock and produce exactly one removal between them.
Co-Authored-By: Claude <noreply@anthropic.com>
… heal missing-manifest path
Addresses 7 issues from batch-1-json-helper-refactor:
A1 (HIGH): Heal path now runs when manifest is absent. The early-exit guard only
requires the log file; a missing manifest is treated as an empty one so the heal
block can reconstruct it from the log + knowledge files.
A2 (HIGH): Extract shared sliceKnowledgeSection(content, anchorId) helper used by
reconcileExisting (anchored hash path) and the heal block, eliminating the three
duplicated inline regex constructions.
A3 (MEDIUM): Thread fileContent through findUnmanagedAnchors return descriptor so
the heal block reuses the bytes already read — no second fs.readFileSync per anchor.
C1 (HIGH): Replace 140-line reconcile-manifest case with three logical sections
(loadReconcileState, reconcileExisting, healUnmanagedAnchors), collapsing nesting
depth from 4 to 3 and reducing decision points substantially.
C3 (MEDIUM): Introduce emptyReconcileResult() factory — eliminates five inline
copies of { deletions: 0, edits: 0, unchanged: 0, healed: 0 }.
P2 (MEDIUM): Add early-exit guard in findUnmanagedAnchors — pass logMap and skip
file scanning when no ready observations exist.
T3 (MEDIUM): Export djb2 once from tests/learning/helpers.ts; remove two duplicate
inline function definitions from reconcile.test.ts.
Test: add 'heal: manifest absent + knowledge file + ready obs → heal triggers (A1)'
case; all 954 tests pass.
Co-Authored-By: Claude <noreply@anthropic.com>
The `parts.length === 0` guard already handles the empty case; the subsequent `|| '(none)'` fallback was dead code from an earlier draft.
Failing tests covering: - loadKnowledgeIndex formatting (populated, filtered, title/area truncation, unknown-status, missing-area) - CLI dispatch: index/full/bare/unknown subcommands - Observability: stderr log on successful invocation
Adds:
- extractIndexEntries(raw): parses ADR/PF sections after D-A filter into
{id, title, status, area} records
- loadKnowledgeIndex(worktreePath, opts): returns ~250-token index with
Decisions/Pitfalls blocks, per-entry [status] tags, 60/80-char truncation,
and a footer explaining how to Read full bodies on demand
- CLI subcommand dispatch: index/full/bare(deprecated)/unknown following
json-helper.cjs pattern
- Observability: stderr [knowledge-context] mode=... worktree=... entries=N
log on successful non-(none) invocation
- Exports extractIndexEntries alongside existing exports
Failing tests covering: - File existence at shared/skills/apply-knowledge/SKILL.md - Frontmatter: name, description, allowed-tools: Read - 5-step algorithm markers: Scan, Identify, Read body, Cite, verbatim IDs - Worked example with PF-004 - Citation format: applies ADR-NNN / avoids PF-NNN - Skip guard: omit when (none)
Canonical 5-step consumer algorithm for KNOWLEDGE_CONTEXT index: 1. Scan the index 2. Identify plausibly-relevant entries 3. Read the full body on demand 4. Cite inline (applies ADR-NNN / avoids PF-NNN) 5. Verbatim IDs only — never fabricate Includes worked example with PF-004 and skip guard for (none) context. Frontmatter: allowed-tools: Read (agents read file bodies on demand).
Failing tests covering: - 7 command files invoke knowledge-context.cjs index - 4 orch skills invoke knowledge-context.cjs index - debug:orch: KNOWLEDGE_CONTEXT present but NOT in Explore spawn blocks - 5 consumer agents reference devflow:apply-knowledge in frontmatter - KNOWLEDGE_CONTEXT present in all four command surfaces + 3 new orch skills - plan:orch and review:orch have knowledge-loading phases
…eview surfaces Implements index+on-demand Read for all four knowledge-consuming commands and their ambient orch equivalents. Closes PF-011. Commands wired: - /self-review: replaces full Read with knowledge-context.cjs index - /code-review + code-review-teams: adds Phase 1b with index load; passes KNOWLEDGE_CONTEXT to each Reviewer; teams variant updates all 4 reviewer prompts to use devflow:apply-knowledge instead of reading pitfalls.md - plan.md + plan-teams.md: already wired in prior commit (preserved) - resolve.md + resolve-teams.md: already wired in prior commit (preserved) Orch skills wired (previously missing, closes ambient parity gaps): - plan:orch: adds Phase 0 knowledge loading + passes to Explore and Designer - review:orch: adds Phase 2b knowledge loading + KNOWLEDGE_CONTEXT in Phase 4 - debug:orch: adds Phase 0 knowledge loading (orchestrator-local, NOT fanned to Explore sub-agents — mirrors /debug behavior) - resolve:orch: already wired in prior commit (preserved) Consumer agents (apply-knowledge skill reference): - resolver.md: adds verbatim-only hallucination guard to Apply Knowledge section - reviewer.md: promotes inline reference to ## Apply Knowledge section + adds CITATION-SENTENCE markers for propagation test - designer.md, simplifier.md, scrutinizer.md: already wired in prior commit Plugin registration: - devflow-core-skills plugin.json: adds apply-knowledge skill - src/cli/plugins.ts: adds apply-knowledge to core-skills + LEGACY_SKILL_NAMES All 1020 tests pass.
…ttern - CHANGELOG: adds entry under [Unreleased] ### Changed describing the index+on-demand Read refactor across all four commands and skill extraction - CLAUDE.md: updates /resolve, /plan, /self-review, /code-review roster entries to mention devflow:apply-knowledge consumption pattern - docs/self-learning.md: adds "Knowledge Index + On-Demand Read Pattern" subsection describing the two-step flow and which commands use it
- Remove dead `statusTag` variable in `formatAdrLine` (computed then immediately overridden by `tag` on the next line). - Inline the `SUBCOMMANDS` array that existed only to feed the `KNOWN_SUBCOMMANDS` Set — eliminated unnecessary intermediate. - Extract duplicated `loadFile` + `extractSection` helpers from `command-adoption.test.ts` into `tests/knowledge/helpers.ts` so the knowledge test suite has a single source of truth for these utilities. - Remove two dead try/catch blocks in the deprecation-notice test that captured stderr into variables that were never read before the actual capture happened.
Scrutinizer 9-pillar review surfaced four consistency issues where the
spawn-block descriptions, default literals, and plan-teams teammate
prompts still reflected the old "full corpus" language rather than the
new "compact index + on-demand Read via devflow:apply-knowledge" pattern
introduced in the preceding commits.
- resolve.md: Phase 4 spawn block described KNOWLEDGE_CONTEXT as
"filtered decisions.md + pitfalls.md content" — now "knowledge index
from Step 0d" with explicit devflow:apply-knowledge instruction to
each Resolver. Architecture diagram already correct.
- resolve-teams.md: teammate prompt template matched. Added the
apply-knowledge instruction as sub-bullet of step 1 so the teammate
reads the skill alongside devflow:patterns.
- resolve:orch SKILL.md: Phase 4 Each-receives bullet said "Filtered
content from Phase 1.5" — now "Knowledge index from Phase 1.5" with
devflow:apply-knowledge reference.
- self-review.md: Simplifier/Scrutinizer spawn blocks used the literal
'None' as placeholder default, while the apply-knowledge skip guard
and every other consumer expects '(none)'. A Simplifier/Scrutinizer
receiving 'None' would fail the skip-guard equality check and try to
process it as a real index. Unified to '(none)' and added the
apply-knowledge reference inline.
- plan-teams.md: PF-008 lockstep violation — the four exploration
teammate prompts and the Phase 5 gap-analysis designer input list
still said "Project knowledge: {Phase 2 decisions + pitfalls}" with
no reference to the new skill. Now KNOWLEDGE_CONTEXT with the
apply-knowledge instruction on each teammate, matching plan.md
structurally.
- plan.md + plan-teams.md architecture diagrams: "Read decisions.md +
pitfalls.md" updated to "Load knowledge index (knowledge-context.cjs
index)" to match the actual Phase 2 mechanism.
All 1020 tests still pass; no test changes needed since the adoption
tests only require `knowledge-context.cjs index` and
`devflow:apply-knowledge` to be present somewhere in each surface — the
fixes bring the inline teammate/spawn-block descriptions into alignment
with what the tests already enforce at the surface level.
Two evaluator-flagged misalignments resolved:
1. tests/resolve/knowledge-citation.test.ts — prune six redundant
structural-prose assertions (decisions.md/pitfalls.md references,
Deprecated/Superseded stripping) that coincidentally passed because
the new knowledge-context.cjs prose retains matching substrings.
Also prune two Apply Knowledge assertions (citation format,
hallucination guard) already owned by apply-knowledge-skill.test.ts.
Replaced coverage is owned by tests/knowledge/command-adoption.test.ts
and tests/knowledge/apply-knowledge-skill.test.ts. Unit blocks for
filterKnowledgeContext and loadKnowledgeContext are kept intact.
2. shared/agents/reviewer.md — rewrite CITATION-SENTENCE block from
old direct-file-read prose ("from .memory/knowledge/decisions.md…")
to the index+Read pattern ("via the KNOWLEDGE_CONTEXT index, per
devflow:apply-knowledge skill"). Markers preserved.
tests/skill-references.test.ts updated: byte-identity check for
reviewer.md replaced with content-based assertions matching the new
sentence (reviewer legitimately uses a different access pattern than
coder, which still reads files directly).
Co-Authored-By: Claude <noreply@anthropic.com>
Code Review CommentsI've analyzed the 8 review reports and identified HIGH/CRITICAL confidence findings (≥80%) for inline comments. Below are the blocking issues that should be addressed before merge. BLOCKING FINDINGS (≥80% confidence)1. Inconsistent Worktree Placeholder (96% confidence)Location: All 8 orchestration surfaces invoke
Silent Failure Mode: If an LLM substitutes the wrong template, knowledge loading exits silently with Fix: Standardize on 2. Shell-Substitution Placeholder Leak (88% confidence)Location: All 8 surfaces contain: Worktree paths come from Fix: Use WT=$(printf %q "<worktree>")
KNOWLEDGE_CONTEXT=$(node scripts/hooks/lib/knowledge-context.cjs index -- "$WT")Also add guidance in 3. Hardcoded Paths Contradict Index Footer (86% confidence)Location: The skill's Step 1 says: "the path is in the footer of KNOWLEDGE_CONTEXT — Read that file." But Step 3 then hardcodes: "Read The problem: the footer emits absolute paths (computed from Fix: Remove hardcoded paths. Replace with: "Read the file path listed in the footer of KNOWLEDGE_CONTEXT." The footer is the single source of truth. 4. Fragile CLI Dispatch Heuristic (88% confidence)Location: The dispatch logic uses
Fix: Use structural detection instead of path-shape inference: if (HANDLERS[firstArg]) {
mode = firstArg;
worktreeArg = argv[1];
} else if (argv.length === 1) {
// Bare deprecated form
mode = 'bare';
worktreeArg = firstArg;
} else {
usageExit();
}5. Contradictory CHANGELOG Entries (95% confidence - CRITICAL)Location: The
But the
Both cannot describe current reality. The Added entry was relocated from 2.0.0 without updating the wording. Fix: Either rewrite the Added entry in index-pattern terms, or fold it into Changed. This misrepresents the feature to downstream readers. 6. Stale Token Claim (92% confidence)Location: Docstring claims
Fix: Update to honest language: // Compact summary, ~30 tokens per entry (e.g., 12 entries ≈ 450 tokens).
// Scales O(n) with active ADR + PF count.7. Inconsistent
|
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.
Summary
Three v2.0.0 ship-blocker fixes for the project knowledge subsystem, bundled as one PR:
purge-legacy-knowledge-v3sweeps all pre-v2 ADR/PF sections using- **Source**: self-learning:as a format discriminator — any section lacking the marker is removed. User-editedself-learning:manual_xxxentries survive (opt-in preservation).json-helper.cjs:1305writes file before log/manifest). At next session start, reconcile-manifest now scans knowledge files for anchors missing from the manifest; if exactly onestatus: 'ready'log observation matches, it upgrades tostatus: 'created', reconstructs the manifest entry, and registers usage. Zero matches = user-curated (no-op); multiple = ambiguous, silent skip (D-D). Addshealedcounter to reconcile output. Also requires- **Source**: self-learning:marker on the file section to prevent false-positive heals against pre-v2 entries (scrutiny fix)./resolvereads & cites project knowledge. Orchestrator readsdecisions.md+pitfalls.mdper worktree, strips Deprecated/Superseded sections (D-A), passes asKNOWLEDGE_CONTEXTto each Resolver. Resolvers citeapplies ADR-NNN/avoids PF-NNNinline in Reasoning cells (verbatim-only constraint prevents hallucination). Phase 5 aggregates citations into## Knowledge Citationsat the top ofresolution-summary.md(D-B). Applied to three surfaces:resolve.md,resolve-teams.md,resolve:orch/SKILL.md.Docs (CLAUDE.md, docs/self-learning.md, CHANGELOG.md) updated in sync (D-C).
Implementation notes
writeFileAtomicExclusive, reused existing lock protocol (acquireMkdirLock), no new CLI surface (v3 runs invisibly ondevflow init).Test plan
npm run build— cleannpm test— 943/943 passing(none)literal guard)devflow init, verify v3 purge result/resolveon a branch with seeded knowledge; verify citations appear inline and in summary header