baldart 4.98.3 → 4.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to BALDART will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.99.0] - 2026-07-03
9
+
10
+ **Consumer-lessons wave: four recurring failure patterns surfaced by mayo's nightly/weekly routine reports (20260628-skill-improve + 20260701-doc-graph-align) upstreamed into the base framework.** The consumer had fixed each locally via overlays, but three of the four root causes live in the base payload — every future consumer would have re-discovered them. The overarching meta-defect (#2) is that the lesson pipeline itself had no upstream channel: overlay fixes died in the consumer.
11
+
12
+ 1. **Epic-closure gate in `/new` (skill `new` 1.4.0 → 1.5.0).** `commit.md` step 28c said only "add/update the entry for this card's feature area" — nothing about the card being the LAST open child of a parent epic, so epics stayed `IN_PROGRESS` after closure (3 confirmed occurrences across two audit windows, caught only by the nightly). New deterministic sub-step **28.c-bis**: when the card YAML declares `parent:`, count non-DONE siblings; zero → flip the parent's ssot-registry entry (and its own YAML if present) to DONE in the SAME commit. Idempotent, non-triggers enumerated. Mirrored in `new2.js`'s mechanical commit prompt (step 4b + ROLE BOUNDARY widened to the parent-epic YAML status).
13
+ 2. **`skill-improve` routine + `skill-improver` agent modernized (pre-overlay-era → current model).** The routine prompt (since_version 2.1.0) instructed editing `.claude/skills/**` / `.claude/agents/**` directly — symlinked framework files that the `framework-edit-gate` (v3.3.0+) DENIES in consumers — and read only `*-code-review/doc-review/qa` reports (absent in real consumers; the agent had to improvise onto the nightly reports). Now: write surface = **`.baldart/overlays/`** (skills / agents / root primitives, with section markers); sources = **ALL routine report types** (`doc-graph-align`, `wiki-review`, `i18n-align`, `design-sync`, `ds-drift`, `full-sweep`, + prior skill-improve for context); graceful degradation on missing metrics/report types; and a new mandatory **`## Upstream Candidates`** report section — when a pattern's root cause is in the BASE skill/agent, the overlay fix is applied locally AND the base defect is flagged for the maintainer to carry via `baldart push` (closing the loop this very release exercises).
14
+ 3. **`API_BODY_CONSTRAINT_DRIFT` — contract-value body check in `doc-reviewer`.** A review/security fix that changes a validation constraint (`.max()`/`.min()`/length/regex/enum/default on a route handler, server action, or API schema) landed with the API reference *body* still stating the old value (real case: DoS cap 500 → 100); frontmatter-freshness checks don't catch body-level factual drift. New invariant-table row: verify the documented value EQUALS the code value; the doc-reviewer is the canonical writer and fixes the body directly. Covered per-card (Phase 3) and at the batch-Final doc pass (fixes applied after the per-card doc pass are caught there).
15
+ 4. **`update_triggers:` — declarative synthesis freshness (opt-in).** Coverage-map syntheses (query catalogs, schema coverage maps, endpoint inventories) silently rot when new code lands (3 missing entries across 3 cards in one week, all caught only by the nightly; the consumer hand-wrote a per-project reviewer rule). New OPTIONAL frontmatter field on wiki synthesis pages — path globs + `content:` added-line patterns that OBLIGATE updating the page when a diff matches, else `WIKI_SYNTH_STALE`. SSOT in `agents/llm-wiki-methodology.md § Update triggers`; consumed by three layers: `doc-reviewer` invariant table (per-task, fixes directly), `wiki-curator` (nightly, updates or flags), `doc-graph-align` routine (nightly commit-range cross-check, propose-don't-author). No retroactive obligation — pages without the field are exempt.
16
+
17
+ **MINOR** — adds capability to existing skills/agents/routines (no new agent/skill/command/routine, so README counts unchanged; no install-layout change). **Codex parity: portable** — all changes are markdown skill/agent/protocol/routine bodies shared by both runtimes (`skill-improver`, `doc-reviewer`, `wiki-curator` auto-transpile to `.codex/agents/*.toml` on install/update; `new2.js` is the Claude-only accelerator whose inline `/new` path carries the same gate). **Not a `baldart.config.yml` key** (`update_triggers` is wiki-page frontmatter, not config) → the schema-change propagation rule does NOT apply.
18
+
8
19
  ## [4.98.3] - 2026-07-02
9
20
 
10
21
  **Bugfix: `baldart update` re-flags `multi_tenant_theming` as a "new config key" on every run.** A user reported the schema-drift detector nagging `⚠ New config keys in this version: multi_tenant_theming` at every `baldart update`, even after configuring it. Root cause: `multi_tenant_theming` was the **only** `features.*` key whose autodetected default was hardcoded `null` (`configure.js`), because there is no on-disk signal for per-tenant theming. `mergePreserving` fills it to `false` from the template, but the **non-interactive** configure branch strips every feature whose *detected* value is `null` (the "always-ask, never-assume" contract) — so a `--non-interactive` / `update --auto` / CI / auto-flow configure wrote a config **without** the key, and `update`'s drift detector (`update.js`) then re-flagged it as new on every subsequent run. The interactive path persisted it, so it appeared to "stick sometimes then forget" — a single auto flow in between re-dropped it.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 4.98.3
1
+ 4.99.0
@@ -241,6 +241,8 @@ Run this before any general audit:
241
241
  - new/removed `process.env.VAR` → `env-vars.md`
242
242
  - card DONE → `ssot-registry.md`
243
243
  - architecture/provider/auth/schema/contract decision → ADR
244
+ - **changed validation constraint on a public contract** (a `.max()` / `.min()` / length / regex / enum / default changed in a route handler, server action, or API schema) → the API reference **BODY** for that endpoint: verify the documented value EQUALS the code value — frontmatter freshness alone does not catch this. Mismatch = `API_BODY_CONSTRAINT_DRIFT`; you are the canonical writer, fix the body directly. Classic source: a code-review/security fix applied AFTER the doc was written (e.g. a DoS cap tightened from 500 → 100 with the reference still saying 500).
245
+ - **(when `features.has_wiki_overlay: true`) diff matches a synthesis page's `update_triggers`** → that synthesis page must be updated in the same change (or flagged `WIKI_SYNTH_STALE`). Match each changed path / added line against the `update_triggers:` frontmatter of pages under `${paths.wiki_dir}/syntheses/` — see `agents/llm-wiki-methodology.md § Update triggers`. Pages without the field are exempt (no retroactive obligation).
244
246
  Only read the specific doc that a triggered row points to.
245
247
  6. Check completeness of: data model docs, collection docs, API docs, UI docs, `product-scope.md` only for business-scope changes, `project-status.md`, ADRs when architecture changed, backlog notes, macro-feature SSOT cross-links.
246
248
  7. Write missing docs directly. Prefer extending existing reference docs over creating new files unless the feature is large enough to justify a standalone document. For type-specific checklists, read `.claude/skills/doc-reviewer-support/references/doc-checklists.md` **if it exists**; otherwise apply the doc-type rules and invariant table above and the `doc-writing-for-rag` skill's templates.
@@ -292,7 +294,7 @@ If `.claude/skills/doc-reviewer-support/references/deliverables-format.md` exist
292
294
  - **C. Invariant check** — table of triggered invariants and their resolution (or "all clear").
293
295
  - **D. Docs written/fixed** — concrete file list with one-line description per file.
294
296
  - **E. Doc debt** — `[DOC-DEBT]` tasks opened (or "none").
295
- - **F. Drift flags** — any `DS_*`, `SCHEMA_DRIFT`, `REGISTRY_GAP`, `ENDPOINT_COUNT_MISMATCH`, etc., with disposition.
297
+ - **F. Drift flags** — any `DS_*`, `SCHEMA_DRIFT`, `REGISTRY_GAP`, `ENDPOINT_COUNT_MISMATCH`, `API_BODY_CONSTRAINT_DRIFT`, `WIKI_SYNTH_STALE`, etc., with disposition.
296
298
  - **G. Deferred** — anything not done this pass, factually (no rationalization).
297
299
  - **H. Obsidian Corpus Impact** — whether vault sync / corpus follow-up is needed (assess only; OPTIONAL — see Obsidian note in the Feature Documentation Process).
298
300
 
@@ -1,61 +1,91 @@
1
1
  ---
2
2
  name: skill-improver
3
- description: "Weekly skill improvement agent. Analyzes accumulated review findings and QA results from the past week to identify recurring patterns, then proposes and applies targeted improvements to skill files (.claude/skills/), coding standards (agents/coding-standards.md), and AGENTS.md. Run via weekly cron every Sunday 02:00 UTC. Only modifies .claude/, agents/, AGENTS.md, and docs/ — never application code."
3
+ description: "Weekly skill improvement agent. Analyzes the past week's routine reports (code-review, doc-review, qa, doc-graph-align, wiki-review, i18n-align, design-sync, ds-drift, full-sweep) to identify recurring patterns, then applies targeted improvements to the consumer's overlay layer (.baldart/overlays/) and flags base-framework defects as Upstream Candidates. Run via weekly cron every Sunday 02:00 UTC. Only modifies .baldart/overlays/ and docs/ — never application code, never the framework payload."
4
4
  model: sonnet
5
5
  color: purple
6
6
  ---
7
7
  > **YOLO MODE**: All agents spawned via the Task tool MUST use `mode: "bypassPermissions"`. No exceptions.
8
8
 
9
- You are the **Skill Improvement Agent**. Your job is to analyze the past week's review
10
- findings and automatically improve the skill/agent instructions to prevent recurring issues.
9
+ You are the **Skill Improvement Agent**. Your job is to analyze the past week's
10
+ routine findings and improve the skill/agent instructions so recurring issues stop
11
+ recurring — via the consumer's **overlay layer**, never by touching the framework
12
+ payload directly.
11
13
 
12
14
  ## Scope (STRICT)
13
15
 
14
16
  **MAY MODIFY:**
15
- - `.claude/skills/**/*.md` — add anti-patterns, tighten checks, improve instructions
16
- - `agents/coding-standards.md` — add new conventions
17
- - `AGENTS.md` add new must-rules for critical patterns
18
- - `docs/reports/skill-improvement-YYYY-MM-DD.md` — output report
17
+ - `.baldart/overlays/<skill>.md` — per-skill extensions (anti-patterns, tightened checks, project rules)
18
+ - `.baldart/overlays/agents/<name>.md` — per-agent extensions (`## [OVERRIDE]` / `## [APPEND]` / `## [PREPEND]` section markers)
19
+ - `.baldart/overlays/AGENTS.md` / `.baldart/overlays/CLAUDE.md` project-wide rule extensions (root primitives are generated files)
20
+ - `docs/reports/{{YYYYMMDD}}-skill-improve.md` — output report
19
21
 
20
22
  **MUST NOT MODIFY:**
23
+ - `.claude/skills/**`, `.claude/agents/**`, `.claude/commands/**` — symlinked/generated framework files; the `framework-edit-gate` hook denies these writes. The overlay IS the write surface.
24
+ - Root `AGENTS.md` / `CLAUDE.md` — generated from versioned skeletons; edit the overlay instead.
25
+ - Anything under `.framework/` — the framework subtree is read-only in consumers.
21
26
  - Any file under `src/` — no application code
22
27
  - `${paths.backlog_dir}/`, `${paths.prd_dir}/`, `${paths.adrs_dir}/` — no product docs
23
28
  - `.claude/settings.json` — no infra config changes
24
29
 
25
30
  ## Weekly Analysis Process
26
31
 
27
- ### Step 1 — Read metrics registry
32
+ ### Step 1 — Read metrics registry (graceful degradation)
28
33
  Read `docs/metrics/skill-runs.jsonl` and filter to the past 7 days.
29
- Compute per-skill aggregates: mean fix_cycles, actionability_rate, qa_pass_first_attempt_rate.
34
+ Compute per-skill aggregates: mean fix_cycles, actionability_rate,
35
+ qa_pass_first_attempt_rate. **If the file is absent, skip this step with a
36
+ one-line note** — do not fail the run.
30
37
 
31
38
  ### Step 2 — Collect findings from reports
32
- Read all files matching:
33
- - `docs/reports/code-review-YYYY-MM-DD.md` from the past 7 days
34
- - `docs/reports/doc-review-YYYY-MM-DD.md` from the past 7 days
35
- - `/qa/*.md` files modified in the past 7 days
39
+ Read ALL routine reports from the past 7 days under `docs/reports/`
40
+ (filename pattern `YYYYMMDD-<type>.md`): `*-code-review.md`, `*-doc-review.md`,
41
+ `*-qa.md`, `*-doc-graph-align.md`, `*-wiki-review.md`, `*-i18n-align.md`,
42
+ `*-design-sync.md`, `*-ds-drift.md`, `*-full-sweep.md` plus the previous
43
+ `*-skill-improve.md` for context (what was already fixed; don't re-fix).
44
+ Types absent this week are simply skipped — analyze what exists.
36
45
 
37
46
  ### Step 3 — Cluster recurring findings
38
- Group findings by category (lint, TypeScript, Security, Performance, Doc, Pattern).
39
- Identify patterns with ≥2 occurrences in the week.
47
+ Group findings by category (lint, TypeScript, Security, Performance, Doc,
48
+ Pattern, Drift). Identify patterns with ≥2 occurrences in the week. A pattern
49
+ already addressed by a prior skill-improve overlay change that KEEPS recurring is
50
+ a signal the overlay fix didn't work — escalate it in the report instead of
51
+ re-applying the same fix.
40
52
 
41
- ### Step 4 — Apply targeted improvements
53
+ ### Step 4 — Apply targeted improvements (overlay layer)
42
54
  For each recurring pattern:
43
- 1. Determine which skill/agent file should mention it
44
- 2. Write a concise addition (1-3 lines) — anti-pattern warning, must-rule, or example
45
- 3. Apply the edit
46
- 4. Commit: `[SKILL-IMPROVE] <category>: <one-line description>`
55
+ 1. Determine which skill/agent owns the gap, and whether the root cause is
56
+ **project-specific** (an opinion, a local convention, a local file) or a
57
+ **base-framework defect** (a vague step, a missing generic rule that would
58
+ recur in any consumer).
59
+ 2. Write a concise addition (1-5 lines) — anti-pattern warning, must-rule, or
60
+ example — into the matching overlay: `.baldart/overlays/<skill>.md` for
61
+ skills, `.baldart/overlays/agents/<name>.md` for agents (use
62
+ `## [APPEND] <topic>` sections; `## [OVERRIDE]` only when replacing a base
63
+ section wholesale). Scaffold missing overlays via
64
+ `npx baldart overlay scaffold` when available.
65
+ 3. Apply the edit.
66
+ 4. Commit: `[SKILL-IMPROVE] <category>: <one-line description>`.
67
+ 5. **If the root cause is a base-framework defect**: STILL apply the overlay fix
68
+ locally (the consumer must not wait for a framework release), AND record the
69
+ defect in the report's `## Upstream Candidates` section — base file path
70
+ (e.g. `framework/.claude/skills/new/references/commit.md`), the defect, the
71
+ proposed base change. The maintainer carries these upstream via `baldart push`.
47
72
 
48
73
  ### Step 5 — Write improvement report
49
- Write `docs/reports/skill-improvement-YYYY-MM-DD.md` with:
50
- - Metrics summary (week vs. previous week)
51
- - Patterns found (≥2 occurrences)
52
- - Changes applied (file, what was added)
74
+ Write `docs/reports/{{YYYYMMDD}}-skill-improve.md` with:
75
+ - Source reports analyzed (table: report, date, type)
76
+ - Metrics summary (week vs. previous week, or "skipped — no metrics file")
77
+ - Patterns found (≥2 occurrences, with evidence + confidence)
78
+ - Changes applied (overlay file, what was added, which findings drove it)
53
79
  - Changes considered but skipped (with reason)
80
+ - `## Upstream Candidates` (base-framework defects flagged this week, or "none")
81
+ - Carry-over open drift not addressable via skill changes (environment gaps,
82
+ blocked-on-implementation items)
54
83
 
55
84
  ## Safety Rules
56
85
 
57
- 1. **Only add, never remove** — do not delete existing rules
86
+ 1. **Only add, never remove** — do not delete existing rules (base or overlay)
58
87
  2. **Minimum 2 occurrences** in the week — no single-occurrence rules
59
88
  3. **One commit per pattern** — small and traceable
60
89
  4. **No speculative rules** — only patterns with concrete evidence from the week's findings
61
- 5. **Max 5 skill edits per week** — avoid bloating skill files
90
+ 5. **Max 5 overlay edits per week** — avoid bloating overlays
91
+ 6. **Never bypass the edit gate** — if a write is denied by the framework-edit-gate, the target was wrong: move the change to the corresponding overlay
@@ -61,6 +61,28 @@ The graph is **never canonical** — proposed pages must still cite repo SSOT an
61
61
  carry `canonicality: derived`. If Graphify is absent, skip this section silently.
62
62
  Provenance: cite the graph node/community id in the candidate payload.
63
63
 
64
+ ## Update Triggers (declarative synthesis freshness)
65
+
66
+ Synthesis pages MAY declare `update_triggers:` in frontmatter — path globs (plain
67
+ strings) and added-line patterns (`content:` prefix) that OBLIGATE an update when
68
+ a diff matches. Semantics SSOT: `agents/llm-wiki-methodology.md § Update triggers`.
69
+
70
+ During a nightly wiki-review, for every page under `${paths.wiki_dir}/syntheses/`
71
+ that declares the field:
72
+
73
+ 1. Compute the commit range since the page's `last_verified_from_code`.
74
+ 2. Match the range's changed file paths against the glob triggers, and its added
75
+ lines against the `content:` triggers.
76
+ 3. On a match where the page itself was NOT updated in that range: **update the
77
+ page yourself** (you are the writer for the wiki layer) — add the missing
78
+ entries, bump `last_verified_from_code`, log to `${paths.wiki_dir}/log.md`.
79
+ If the update needs domain knowledge you lack, flag `WIKI_SYNTH_STALE` with
80
+ the matching commits as a drift finding instead.
81
+
82
+ Pages without the field carry no obligation. When you CREATE a coverage-map
83
+ synthesis (query catalog, schema coverage, endpoint inventory), declare its
84
+ `update_triggers` at creation time — that is what keeps it alive.
85
+
64
86
  ## Frontmatter Discipline
65
87
 
66
88
  All wiki pages MUST have:
@@ -2,6 +2,10 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 1.5.0 — 2026-07-03
6
+
7
+ - **Epic-closure gate (framework v4.99.0)**: `commit.md` step 28 gains sub-step **c-bis** — when the card being marked DONE declares a `parent:` epic, a deterministic count of non-DONE siblings decides whether the PARENT epic's ssot-registry entry (and its own YAML, if present) is flipped to DONE in the same commit. Closes the recurring consumer gap where epics stayed `IN_PROGRESS` after their last child closed (3 occurrences across two audit windows, caught only by the nightly). Mirrored in `new2.js`'s mechanical commit prompt (step 4b).
8
+
5
9
  ## 1.4.0 — 2026-07-02
6
10
 
7
11
  - **Analysis-profile contract (framework v4.94.0)**: `implement.md` Phase 1 step 3 now passes a deterministic `PROFILE=` token to the `codebase-architect` spawn — `ui` when the card has a non-empty `links.design`/`links.design_src` (the same mockup bit as step 6a), else `feature`. Contract SSOT: `framework/agents/analysis-profiles.md`; guarded by the `check-new-parity.mjs` tripwire.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: new
3
3
  effort: medium
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  description: >
6
6
  Orchestrate a team of specialized agents to implement one or more backlog cards
7
7
  end-to-end inside a dedicated worktree, with code review, doc review, QA, and
@@ -33,6 +33,14 @@
33
33
  a. Edit the backlog YAML (`${paths.backlog_dir}/<CARD-ID>.yml`): set `status: DONE`, add `completed_date: <today>`, and add `provenance.implementation_session: <SESSION-ID>` (this run's session UUID — get it with `Bash(echo "${CLAUDE_CODE_SESSION_ID:-}")`; if empty, omit the field). Merge into any existing `provenance:` block written by `/prd` — do NOT overwrite `planning_session`. This makes an implementation bug traceable back to the session that produced it (`~/.claude/projects/*/<id>.jsonl`).
34
34
  b. Add implementation notes summarizing what was built.
35
35
  c. **Update `${paths.references_dir}/ssot-registry.md`** — add/update the entry for this card's feature area. The pre-commit doc-freshness hook BLOCKS commits that touch `${paths.backlog_dir}/` without a corresponding ssot-registry update. Always include ssot-registry.md in the same commit as the backlog YAML.
36
+ c-bis. **Epic-closure gate (deterministic — since v4.99.0)**: if the card YAML declares a parent epic (`parent:` field), check — AFTER step a set this card DONE — whether it was the LAST open child. Deterministic count, no judgement:
37
+ ```bash
38
+ PARENT=$(awk '/^parent:/ {print $2; exit}' ${paths.backlog_dir}/<CARD-ID>.yml)
39
+ if [ -n "$PARENT" ]; then
40
+ PENDING=$(grep -l "^parent: ${PARENT}" ${paths.backlog_dir}/*.yml | xargs grep -L "^status: DONE" | wc -l)
41
+ fi
42
+ ```
43
+ When `PENDING` is `0`: flip the PARENT epic's status in its ssot-registry.md entry to DONE **in the SAME commit**, and if the parent epic has its own backlog YAML, set its `status: DONE` + `completed_date` too. Non-triggers (do nothing, idempotent): the card has no `parent:`; siblings still pending (`PENDING > 0`); the parent entry is already DONE. This closes a recurring consumer gap: step 28c alone updates the CARD's feature-area entry, so epics stayed `IN_PROGRESS` after their last child closed and were only caught by the nightly doc routine (3 confirmed occurrences across two audit windows).
36
44
  d. **Verify the write**: re-read the YAML file and confirm `status: DONE` is present. If not, retry the edit.
37
45
  e. Stage BOTH the updated YAML AND ssot-registry.md, then commit (or as an immediate follow-up commit if the Phase 4 implementation commit already happened). When this produces a SECOND commit for the card, record BOTH hashes in the tracker (`commit: <impl-hash> + <done-hash>`) so traceability/bisect is unambiguous.
38
46
  29. **Update tracker**: move card to `## Completed Cards` with commit hash(es), summary, flags, **and `card_status: DONE (verified)`** — the tracker is the only state surface (§ "State surface — the tracker only"); do not also emit a TaskUpdate or Progress-Bar turn for the transition. If you surface the card completion to the user at all, do it as a short prose line folded into the commit turn, never a dedicated turn.
@@ -876,11 +876,11 @@ async function runCard(cardId, cardPath) {
876
876
  // main repo (so a card is never DONE with a silently-dropped requirement — F-029).
877
877
  const doneStep = deferredOpen
878
878
  ? `(4) DO NOT mark the card DONE: it has an OPEN owner-gated/policy-deferred AC. Keep status IN_PROGRESS and add an implementation_note "deferred — DONE pending follow-up (new2 skill reconciles post-run)". STILL add the ssot-registry row for the committed code.`
879
- : `(4) mark the card DONE in its YAML + add the ssot-registry row.${provLine}`
879
+ : `(4) mark the card DONE in its YAML + add the ssot-registry row.${provLine} (4b) epic-closure gate (deterministic): if the card YAML has a \`parent:\` field, count sibling YAMLs in the backlog dir with that same parent whose status is NOT DONE; when the count is zero, flip the parent epic's ssot-registry entry to DONE (and the parent's own YAML status + completed_date, if one exists) in the SAME commit — these bookkeeping edits are in-scope for staging even if outside MAY-EDIT. Idempotent — skip when no parent, siblings still pending, or the parent entry is already DONE.`
880
880
  let commitRes
881
881
  try {
882
882
  commitRes = await agentSafe(
883
- `Commit card ${cardId} in worktree ${sharedCtx.worktreePath}. MECHANICAL — do NOT re-read reference modules. ROLE BOUNDARY: you NEVER modify file contents except the card YAML status/note fields and the ssot-registry row — source/doc changes are not yours.\n` +
883
+ `Commit card ${cardId} in worktree ${sharedCtx.worktreePath}. MECHANICAL — do NOT re-read reference modules. ROLE BOUNDARY: you NEVER modify file contents except the card YAML status/note fields, the parent-epic YAML status (epic-closure gate only), and the ssot-registry entries — source/doc changes are not yours.\n` +
884
884
  `Steps: (1) \`git status --porcelain\`; (2) stage = MAY-EDIT (${JSON.stringify(mayEdit)}) ∩ dirty — NEVER \`git add -A\`, NEVER \`git stash\`; if dirty has files OUTSIDE MAY-EDIT, do NOT stage them and set reconcileNote; (3) commit message \`[${cardId}] <concise>\`; ${doneStep} (5) 'nothing to commit' = already committed (record HEAD).\n` +
885
885
  `On COMMIT_LOCK: clear stale lock + retry once. Still locked → committed:false.\n\n` +
886
886
  `Return: { committed, commit, filesChanged, reconcileNote }`,
@@ -65,12 +65,47 @@ last_verified_from_code: YYYY-MM-DD
65
65
  canonical_refs: # broader canonicals this page is consistent with
66
66
  - ${paths.references_dir}/ssot-registry.md
67
67
  - ${paths.references_dir}/project-status.md
68
+ update_triggers: # OPTIONAL — diff patterns that OBLIGATE an update (see § Update triggers)
69
+ - "src/lib/server/data/**" # plain string = path glob on changed files
70
+ - "content:'use server'" # content: prefix = pattern on ADDED lines
68
71
  ---
69
72
  ```
70
73
 
71
74
  Run a frontmatter validator (typically `npm run validate:frontmatter` or
72
75
  equivalent) before committing wiki edits.
73
76
 
77
+ ## Update triggers (declarative synthesis freshness)
78
+
79
+ A synthesis page MAY declare `update_triggers:` in its frontmatter — a list of
80
+ diff patterns that **obligate** updating the page whenever a change matches:
81
+
82
+ - a **plain string** is a path glob matched against the changed file paths of a
83
+ diff (e.g. `src/lib/server/data/**` — "any new/changed data-layer function");
84
+ - a **`content:` prefixed entry** is a pattern matched against the ADDED lines
85
+ of the diff (e.g. `content:'use server'` — "any new server action").
86
+
87
+ **Semantics.** When a diff matches at least one trigger of a synthesis page and
88
+ the page itself was not updated in the same change, the page is stale — flag
89
+ `WIKI_SYNTH_STALE`. Three layers consume the field:
90
+
91
+ 1. **Per-task** — the `doc-reviewer` invariant table checks the card diff
92
+ against the declared triggers and updates the matching synthesis in the same
93
+ change (it is the canonical writer).
94
+ 2. **Nightly (curator)** — `wiki-curator` matches the commit range since each
95
+ page's `last_verified_from_code` and updates or flags.
96
+ 3. **Nightly (graph align)** — the `doc-graph-align` routine cross-checks its
97
+ analyzed commit range against declared triggers and emits `WIKI_SYNTH_STALE`
98
+ drift findings (propose, don't author).
99
+
100
+ Pages without the field carry **no obligation** — the mechanism is opt-in and
101
+ additive (no retroactive staleness). Declare triggers when a synthesis is a
102
+ **coverage map** over a code surface (a query catalog, a schema coverage map, an
103
+ endpoint inventory): those are exactly the pages that silently rot when new code
104
+ lands, and a declared trigger turns a hand-written per-project reviewer rule
105
+ into a portable, deterministic check. Keep the trigger list SHORT and precise —
106
+ an over-broad glob (`src/**`) makes every change flag the page and trains
107
+ readers to ignore the signal.
108
+
74
109
  ## Anchor & Cross-Reference Discipline
75
110
 
76
111
  - Markdown slugification: lowercase, spaces → dashes, strip punctuation except
@@ -29,6 +29,12 @@ prompt: |
29
29
  - Registry drift: large graph communities with no
30
30
  `${paths.references_dir}/ssot-registry.md` entry, or registry features whose
31
31
  code cluster is unrecognizable in the graph.
32
+ - Declared-trigger drift: synthesis pages under `${paths.wiki_dir}/syntheses/`
33
+ whose frontmatter `update_triggers` (path globs / `content:` added-line
34
+ patterns — semantics in `agents/llm-wiki-methodology.md § Update triggers`)
35
+ match changes in the analyzed commit range, where the page itself was NOT
36
+ updated in that range → `WIKI_SYNTH_STALE` drift finding for wiki-curator /
37
+ doc-reviewer follow-up. Pages without the field are exempt.
32
38
  4. Emit a consolidated report under
33
39
  `docs/reports/{{YYYYMMDD}}-doc-graph-align.md`.
34
40
 
@@ -13,25 +13,41 @@ agent: skill-improver
13
13
  prompt: |
14
14
  Run the weekly skill / agent improvement pass:
15
15
 
16
- 1. Read the last 7 days of `docs/reports/*-code-review.md` and
17
- `docs/reports/*-doc-review.md` (plus any `docs/reports/*-qa.md` if
18
- present). Identify recurring patterns in findings.
19
- 2. For each recurring pattern, propose a targeted improvement to:
20
- - the relevant `.claude/skills/<name>/SKILL.md` (rule clarification,
21
- new MUST/SHOULD, anti-pattern entry)
22
- - the relevant `.claude/agents/<name>.md` (prompt tightening,
23
- checklist update)
24
- - `AGENTS.md` (new project-wide rule) or
25
- `agents/coding-standards.md` (terminology, naming)
26
- 3. Apply changes inline and commit with prefix `[SKILL-IMPROVE]`. NEVER
27
- modify application code in this routine — only `.claude/`, `agents/`,
28
- `AGENTS.md`, `docs/`.
29
- 4. Emit a consolidated report under
16
+ 1. Read the last 7 days of routine reports under `docs/reports/` — ALL
17
+ types present (`*-code-review.md`, `*-doc-review.md`, `*-qa.md`,
18
+ `*-doc-graph-align.md`, `*-wiki-review.md`, `*-i18n-align.md`,
19
+ `*-design-sync.md`, `*-ds-drift.md`, `*-full-sweep.md`), plus the
20
+ previous `*-skill-improve.md` for context. Identify recurring patterns
21
+ in findings (≥2 occurrences in the window).
22
+ 2. For each recurring pattern, propose a targeted improvement. WRITE
23
+ SURFACE (MANDATORY): consumer overlays, never the framework payload —
24
+ - skill rules `.baldart/overlays/<skill>.md`
25
+ - agent rules → `.baldart/overlays/agents/<name>.md`
26
+ - project-wide rules `.baldart/overlays/AGENTS.md`
27
+ NEVER edit `.claude/skills/**`, `.claude/agents/**`, root `AGENTS.md`,
28
+ or anything under `.framework/` directly — those are symlinked or
29
+ generated framework files and the framework-edit-gate hook denies the
30
+ write.
31
+ 3. Apply changes and commit with prefix `[SKILL-IMPROVE]`. NEVER modify
32
+ application code in this routine — only `.baldart/overlays/` and
33
+ `docs/`.
34
+ 4. UPSTREAM CANDIDATES: when a pattern's root cause lies in the BASE
35
+ framework skill/agent (a vague step, a missing generic rule that would
36
+ recur in ANY consumer — not a project-specific opinion), still fix it
37
+ locally via the overlay, AND record it in a dedicated
38
+ `## Upstream Candidates` section of the report: base file path, the
39
+ defect, the proposed base change. The maintainer carries these
40
+ upstream via `baldart push`.
41
+ 5. Emit a consolidated report under
30
42
  `docs/reports/{{YYYYMMDD}}-skill-improve.md` listing every change with
31
- evidence (which findings drove it) and a confidence score.
43
+ evidence (which findings drove it) and a confidence score, changes
44
+ considered but skipped (with reason), and the Upstream Candidates
45
+ section (or "none").
32
46
 
33
- If no recurring pattern is found, write a short "no changes needed" report
34
- and exit cleanly.
47
+ Graceful degradation: if `docs/metrics/skill-runs.jsonl` is absent, skip
48
+ the metrics summary; if a report type is absent this week, analyze what
49
+ exists. If no recurring pattern is found, write a short "no changes
50
+ needed" report and exit cleanly.
35
51
 
36
52
  output:
37
53
  path: docs/reports/{{YYYYMMDD}}-skill-improve.md
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "4.98.3",
3
+ "version": "4.99.0",
4
4
  "description": "Claude Agent Framework - Reusable framework for coordinating AI agents and humans in software projects",
5
5
  "bin": {
6
6
  "baldart": "./bin/baldart.js"