baldart 4.98.2 → 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 +19 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/doc-reviewer.md +3 -1
- package/framework/.claude/agents/skill-improver.md +56 -26
- package/framework/.claude/agents/wiki-curator.md +22 -0
- package/framework/.claude/skills/new/CHANGELOG.md +4 -0
- package/framework/.claude/skills/new/SKILL.md +1 -1
- package/framework/.claude/skills/new/references/commit.md +8 -0
- package/framework/.claude/workflows/new2.js +2 -2
- package/framework/agents/llm-wiki-methodology.md +35 -0
- package/framework/routines/doc-graph-align.routine.yml +6 -0
- package/framework/routines/skill-improve.routine.yml +33 -17
- package/package.json +1 -1
- package/src/commands/configure.js +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ 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
|
+
|
|
19
|
+
## [4.98.3] - 2026-07-02
|
|
20
|
+
|
|
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.
|
|
22
|
+
|
|
23
|
+
- `src/commands/configure.js`: `detected.features.multi_tenant_theming` default `null → false`. Safe because **every** consumer (`ui-design`, `prd`, `bug`, `code-reviewer`, `/design-review`, …) gates on `features.multi_tenant_theming === true` — so `false` and absent are semantically identical (no skill prompts at use-time when it is absent), and the always-ask contract does not practically apply to this key. Now non-interactive configure WRITES `false` (matching the template), keeping it out of the null-strip, so the detector never re-flags it.
|
|
24
|
+
|
|
25
|
+
**PATCH** — one-line detection-default fix, no behavior change for skills (they check `=== true`), no new surface, no install-layout change. **Codex parity: portable** — `configure.js` is the shared CLI installer that writes `baldart.config.yml` for both runtimes; nothing runtime-specific. **Not a NEW `baldart.config.yml` key** (the key already exists end-to-end) → the schema-change propagation rule does NOT apply.
|
|
26
|
+
|
|
8
27
|
## [4.98.2] - 2026-07-02
|
|
9
28
|
|
|
10
29
|
**Negative guard: the codebase-understanding step is `codebase-architect`, not the generic built-in search agent.** A third live session — a data-wiring task (replace a hardcoded `"unità"` label with the real unit-of-measure in an order-wizard `ProductRow`) — delegated the code-path trace to the built-in `Explore` agent instead of `codebase-architect`, bypassing the profile engine, Reuse Analysis, Canonical Evidence, and the Return Contract. Diagnosed carefully (and deliberately *not* over-fitted): this was **not** a `PROFILE=ui` miss — the task's substance is data/logic wiring (product → UoM → loader → label), whose fitting profile is `feature`, not `ui`; the profile axis was left untouched. The real deviation was on the **agent-selection** axis, and it matches the recurring v4.97.1 shape: a positive mandate ("invoke `codebase-architect`") with no explicit "and NOT the generic explorer" guard (the existing `AGENTS.md` "never auto-route to a generic agent" rule is scoped to the *failure-fallback* case, not the initial choice).
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
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
|
|
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
|
|
10
|
-
findings and
|
|
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
|
-
- `.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- `docs/reports/skill-
|
|
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,
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
-
|
|
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,
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
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
|
|
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.
|
|
@@ -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
|
|
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
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
34
|
-
|
|
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
|
@@ -532,7 +532,15 @@ function detect(cwd = process.cwd()) {
|
|
|
532
532
|
},
|
|
533
533
|
features: {
|
|
534
534
|
has_design_system: hasDesignSystem,
|
|
535
|
-
|
|
535
|
+
// Not autodetectable (no on-disk signal for per-tenant theming), but every
|
|
536
|
+
// consumer gates on `=== true`, so `false` and absent are semantically
|
|
537
|
+
// identical — no skill prompts at use-time when it is absent. Defaulting to
|
|
538
|
+
// `false` (matching the template) instead of `null` keeps it OUT of the
|
|
539
|
+
// non-interactive strip below (which drops null-detected keys), so a
|
|
540
|
+
// `--non-interactive`/`--auto`/CI configure actually WRITES the key. With
|
|
541
|
+
// null it was stripped every time, and `baldart update`'s schema-drift
|
|
542
|
+
// detector then re-flagged it as a "new config key" on every run.
|
|
543
|
+
multi_tenant_theming: false,
|
|
536
544
|
has_api_docs: !!(apiSchemas || openapiSpec || graphqlSchema || apiIndex || apiDocsDirPopulated),
|
|
537
545
|
has_backlog: countMatches('backlog', /\.ya?ml$/) > 0,
|
|
538
546
|
has_adrs: countMatches('docs/decisions', /^ADR-.*\.md$/) > 0,
|