feat: Memory-Index Frontmatter Validation + Generated-Index Merge Policy + FKF Description-Length Policy#481
Conversation
…description cap Detects malformed frontmatter (glued/unclosed fences) in fab memory-index, failing --check even when drift comparison alone would pass; adds a never-hand-merge policy for generated index/log conflicts; and caps FKF description: values at 500 characters to shrink the conflict surface.
There was a problem hiding this comment.
Pull request overview
This PR hardens fab memory-index against silently-propagated corrupted FKF frontmatter, establishes a “regen, never hand-merge” policy for generated memory indexes/logs, and formalizes a 500-character one-line description: policy (as a routing signal) across FKF spec, kit reference, templates, and hydrate/ship skills.
Changes:
- Add malformed-frontmatter detection (unclosed fence,
description:quote-strip failure) and advisorydescription:length warnings, surfaced asinternal/memoryindexwarnings and integrated intofab memory-index --checkas a separate blocking signal independent of drift. - Document and wire the generated index/log merge policy: resolve topic/seed inputs, re-run
fab memory-index, and take output wholesale (never hand-merge generated files). - Specify and reinforce FKF
description:as a single-line routing summary with a 500-character cap (advisory warning only), wired into templates and hydrate instructions; add tests covering the new behaviors.
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/kit/templates/memory.md | Updates the canonical memory file template to emphasize a one-line description: capped at 500 chars. |
| src/kit/skills/git-pr.md | Adds ship-time guidance to never hand-merge generated index/log conflicts; regenerate instead. |
| src/kit/skills/git-pr-review.md | Adds PR-feedback conflict guidance to never hand-merge generated index/log files; regenerate instead. |
| src/kit/skills/fab-continue.md | Wires the 500-char description: cap and regenerate-not-hand-merge guidance into hydrate behavior. |
| src/kit/skills/docs-hydrate-memory.md | Updates ingest/generate/backfill instructions to enforce the 500-char one-line description: policy and regen merge policy. |
| src/kit/skills/_cli-fab.md | Documents new malformed-frontmatter warnings, advisory length warnings, and --check semantics. |
| src/kit/reference/fkf.md | Updates shipped FKF extract with §3.2 description-length policy + malformed detection and §5 merge policy. |
| src/go/fab/internal/memoryindex/memoryindex.go | Adds warning kinds, frontmatter validation walk, description-length warning, and plumbing for malformed detection. |
| src/go/fab/internal/memoryindex/memoryindex_test.go | Adds tests for malformed-frontmatter warnings, length boundary, and warning ordering/byte-stability. |
| src/go/fab/internal/memoryindex/loss.go | Extends LossReport JSON shape with additive malformed[] while preserving tier/loss contracts. |
| src/go/fab/internal/frontmatter/frontmatter.go | Adds Validate() and structured findings for the two malformed signatures without changing Field extraction behavior. |
| src/go/fab/internal/frontmatter/frontmatter_test.go | Adds regression tests for glued-fence corruption, unclosed fences, and clean/no-frontmatter cases. |
| src/go/fab/cmd/fab/memory_index.go | Integrates malformed findings into --check exit behavior, adds remediation messaging, updates help text/flags. |
| src/go/fab/cmd/fab/memory_index_test.go | Adds integration tests for byte-clean-but-corrupt --check blocking, JSON shape, and advisory length behavior. |
| fab/changes/260715-xu0k-memory-index-validation-fkf-description-policy/plan.md | Captures requirements/tasks/acceptance for the combined feature set (validation + merge policy + cap). |
| fab/changes/260715-xu0k-memory-index-validation-fkf-description-policy/intake.md | Records problem statement, constraints (byte-stability), and integration decisions for malformed vs tiered drift. |
| fab/changes/260715-xu0k-memory-index-validation-fkf-description-policy/.status.yaml | Adds change status metadata for the pipeline. |
| fab/changes/260715-xu0k-memory-index-validation-fkf-description-policy/.history.jsonl | Adds pipeline history events for the change execution. |
| docs/specs/templates.md | Updates memory template/spec guidance to mention 500-char cap and malformed-frontmatter blocking behavior. |
| docs/specs/skills/SPEC-git-pr.md | Mirrors the git-pr skill’s new never-hand-merge pointer for generated index/log conflicts. |
| docs/specs/skills/SPEC-git-pr-review.md | Mirrors the git-pr-review skill’s never-hand-merge pointer for generated index/log conflicts. |
| docs/specs/skills/SPEC-fab-continue.md | Mirrors hydrate-time description cap + regen merge policy wiring. |
| docs/specs/skills/SPEC-docs-hydrate-memory.md | Mirrors docs-hydrate-memory’s updated authoring/regen guidance (cap + merge policy). |
| docs/specs/skills/SPEC-_cli-fab.md | Mirrors CLI documentation updates for fab memory-index warnings and --check semantics. |
| docs/specs/fkf.md | Updates FKF spec with §3.2 500-char description policy + malformed detection and §5 regen merge policy (+ optional merge driver aside). |
| docs/memory/pipeline/schemas.md | Documents exit-code/JSON schema implications of malformed blocking vs advisory length warning. |
| docs/memory/pipeline/index.md | Updates pipeline memory index descriptions to reflect new policies/behavior. |
| docs/memory/pipeline/execution-skills.md | Wires “never hand-merge generated index/log” guidance into execution-skill memory docs. |
| docs/memory/memory-docs/templates.md | Updates memory-docs template guidance to include cap, malformed-blocking, and regen merge policy. |
| docs/memory/memory-docs/index.md | Updates memory-docs index descriptions to reflect new constraints/policies. |
| docs/memory/memory-docs/hydrate.md | Updates hydrate documentation to include the cap and clarify malformed-blocking vs refuse-before-regen behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| case KindDepth: | ||
| return fmt.Sprintf("⚠ %s exceeds depth %d — consider flattening", w.Path, MaxDepth) |
There was a problem hiding this comment.
Fixed — the depth warning now renders the observed depth alongside the threshold (is nested N levels deep (max: 3)), consuming the previously-unused Warning.Depth field; updated the CLI-reference mirror (_cli-fab.md) and the render test to match. (88ca75c)
| @@ -220,6 +274,16 @@ func emitCheckReport(cmd *cobra.Command, report memoryindex.LossReport, jsonOut | |||
| } | |||
| return fmt.Errorf("memory index out of date — run `fab memory-index`") | |||
There was a problem hiding this comment.
Fixed — when a malformed floor co-occurs with benign drift (tier 1), emitCheckReport now returns an error that also names the corruption ("memory index out of date and malformed frontmatter …"), mirroring the tier-0 branch, so callers surfacing only the error text aren't misled into treating it as mere staleness; added a regression test covering the combined case. (88ca75c)
Meta
xu0kexcludes
fab/,docs/· generated by fab-kit v2.15.3Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Summary
Malformed frontmatter (e.g. a hydrate edit that glues the closing
---fence onto adescription:line) was silently propagated into generated memory indexes with no warning, andfab memory-index --checkcouldn't catch it because the check is a pure drift comparison against already-corrupted committed output. Separately, generateddocs/memory/**/index.mdmerge conflicts were routinely hand-merged instead of resolved by regeneration, and oversizeddescription:values were inflating the conflict surface.Changes
fab memory-index(Go): new validation ininternal/frontmatter(unclosed fence, quote-strip failure) surfaced asinternal/memoryindexwarnings;--checknow fails on malformed frontmatter even when the index output is byte-identical to its regenerated form; byte-stable rendering is preserved; tests added acrossfrontmatter,memoryindex, andcmd/fab/memory_index.docs/specs/fkf.md§5 (+ the shippedsrc/kit/reference/fkf.mdextract) now normatively states never-hand-merge for generatedindex.md/log.mdconflicts — resolve topic files, re-runfab memory-index, take its output wholesale. Short pointers added togit-pr.md,git-pr-review.md, and cross-referenced from the hydrate seams, with SPEC mirrors updated.description:frontmatter is now capped at 500 characters (FKF §3.2, bothdocs/specs/fkf.mdandsrc/kit/reference/fkf.md), read at hydrate time to keep descriptions as routing signals rather than summaries of record.