baldart 5.2.1 → 5.3.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 +40 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/CHANGELOG.md +8 -0
- package/framework/.claude/agents/REGISTRY.md +2 -2
- package/framework/.claude/agents/seo-analytics-strategist.md +2 -1
- package/framework/.claude/workflows/new-card-review.js +1 -1
- package/framework/.claude/workflows/new-final-review.js +1 -1
- package/framework/.claude/workflows/new2.js +13 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@ 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
|
+
## [5.3.0] - 2026-07-03
|
|
9
|
+
|
|
10
|
+
**Haiku banned fleet-wide + FEAT-0067 post-mortem fixes.** The FEAT-0067 audit
|
|
11
|
+
(mayo, session `a8b6bc75`) found a haiku `general-purpose` commit agent running
|
|
12
|
+
its first git command with `cd <worktree> &&` and its SECOND without — so the
|
|
13
|
+
card-DONE bookkeeping commit executed in the MAIN checkout and landed on the
|
|
14
|
+
trunk mid-run (`13aa63b62`), forking `ssot-registry.md`, raising a merge
|
|
15
|
+
BLOCKER (a 5.3M-token repair), and blocking epic closure. Second haiku-class
|
|
16
|
+
failure after the v4.42.0 worktree-setup fabrication → the plumbing carve-out
|
|
17
|
+
is revoked.
|
|
18
|
+
|
|
19
|
+
- **Model policy — haiku eliminated, sonnet is the floor** (`REGISTRY.md`
|
|
20
|
+
§ Rules rewritten): no named specialist AND no `general-purpose` plumbing may
|
|
21
|
+
use haiku. Replaced in every spawn site: `new2.js` (`commit:`,
|
|
22
|
+
`integrate:commit`, `rollback:`, `review:*:codex` driver),
|
|
23
|
+
`new-final-review.js` + `new-card-review.js` (`codex-preflight`), and the
|
|
24
|
+
`seo-analytics-strategist` agent (→ sonnet, v1.1.0). Where an op is truly
|
|
25
|
+
deterministic the fix stays a script (`setup-worktree.sh`,
|
|
26
|
+
`revert-files.sh`), not a cheaper model.
|
|
27
|
+
- **`new2.js` commit agents — cwd HARD RULE + placement verify**: every shell
|
|
28
|
+
command must be prefixed `cd <worktree> &&` in the same Bash invocation (the
|
|
29
|
+
cwd resets between calls), and the per-card commit agent now verifies the
|
|
30
|
+
returned sha equals `git -C <worktree> log -1 --format=%H`, reporting
|
|
31
|
+
`committed:false` with the stray sha instead of silently corrupting the
|
|
32
|
+
trunk.
|
|
33
|
+
- **`new2.js` Phase-1 retriever — schema + drift false-positive fix**: the
|
|
34
|
+
prompt now states the exact required StructuredOutput shape (`ok` REQUIRED —
|
|
35
|
+
the FEAT-0067 run burned 5+3 schema-validation retries), and `missingPaths`
|
|
36
|
+
excludes paths the card itself CREATES (new migrations/tests were flagged as
|
|
37
|
+
drift and disproved downstream).
|
|
38
|
+
- **`scripts/new-session-audit.mjs` — workflow-hosted agents counted**: the
|
|
39
|
+
analyzer now traverses `subagents/workflows/<wf>/agent-*.jsonl`; a new2 run
|
|
40
|
+
previously reported the orchestrator alone (FEAT-0067: 3.88M reported vs
|
|
41
|
+
53.89M real — 93% of the run invisible to TOTAL, baselines, and telemetry).
|
|
42
|
+
|
|
43
|
+
Codex parity: portable / N/A — the three workflows are Claude-only by design
|
|
44
|
+
(documented gap with inline fallback); the agent `model:` field is omitted in
|
|
45
|
+
the Codex TOML transpile, so the model-policy change is Claude-side only; the
|
|
46
|
+
audit script is maintainer tooling, not payload.
|
|
47
|
+
|
|
8
48
|
## [5.2.1] - 2026-07-03
|
|
9
49
|
|
|
10
50
|
**`/mw` local-trunk sync robustness.** The worktree merge's local-trunk sync
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.3.0
|
|
@@ -7,6 +7,14 @@ per-item agent merge, the doctor probes, and the discovery hooks — like
|
|
|
7
7
|
|
|
8
8
|
Formato: [Keep a Changelog](https://keepachangelog.com/) · per-agent SemVer.
|
|
9
9
|
|
|
10
|
+
## [seo-analytics-strategist v1.1.0] — 2026-07-03 (framework v5.3.0)
|
|
11
|
+
|
|
12
|
+
- `model: haiku` → `model: sonnet` — haiku is banned fleet-wide (REGISTRY
|
|
13
|
+
§ Rules, v5.3.0): the FEAT-0067 post-mortem showed a haiku plumbing agent
|
|
14
|
+
dropping the `cd <worktree>` invariant between two consecutive git commands
|
|
15
|
+
and committing to the main checkout's trunk. No named agent may run below
|
|
16
|
+
the sonnet floor. `version:` frontmatter added (was pre-v5.0 style).
|
|
17
|
+
|
|
10
18
|
## [ui-expert v2.1.0] — 2026-07-03 (framework v5.2.0)
|
|
11
19
|
|
|
12
20
|
The `/ui-design` v2.0.0 studio refactor. No H2 moved; edits are within
|
|
@@ -210,9 +210,9 @@ Use this table when spawning agents via the `Task` tool. The `model` field in ea
|
|
|
210
210
|
| **hybrid-ml-architect** | opus | — (always opus) | ML architecture is complex by nature |
|
|
211
211
|
| **senior-researcher** | sonnet | opus at orchestrator's discretion for `PROFILE=deep` surveys | Web-native retrieval + synthesis — sonnet is sufficient and fast; depth comes from the profile loop (`DEPTH=`), not the model |
|
|
212
212
|
|
|
213
|
-
**Rules**:
|
|
213
|
+
**Rules**: **Haiku is BANNED fleet-wide** — never for the named specialist agents in the matrix above, and never for `general-purpose` plumbing either (see below). Opus for code writing and creative/complex work. **Sonnet is the floor** for everything else: analysis, review, documentation, AND mechanical plumbing. `qa-sentinel` stays on sonnet even though it is a mechanical gate runner — its failure interpretation and SCOPED-vs-FULL tiering benefit from sonnet.
|
|
214
214
|
|
|
215
|
-
**Plumbing carve-out (
|
|
215
|
+
**Plumbing carve-out ABOLISHED (v5.3.0):** through v5.2.0 mechanical `general-purpose` plumbing MAY have used `model: "haiku"` via override. That carve-out is **revoked** after two independent haiku failures on "trivially mechanical" ops: (1) the worktree-setup fabrication (2/2 `baseline: pass` with nothing on disk — v4.42.0, moved to sonnet); (2) the FEAT-0067 commit corruption — the haiku commit agent ran its first git command with `cd <worktree> &&` and its SECOND without, so a card-DONE bookkeeping commit executed in the MAIN checkout and landed on the trunk mid-run, forking `ssot-registry.md`, triggering a merge BLOCKER, and blocking epic closure. The lesson generalizes: multi-step shell plumbing is a sustained tool-execution chain, and a too-weak model drops invariants (cwd, ROLE BOUNDARY, staging scope) between steps. Where the op is truly deterministic, the fix is a **script, not a cheaper model** (`setup-worktree.sh`, `revert-files.sh`); where a model stays in the loop, the floor is `sonnet`.
|
|
216
216
|
|
|
217
217
|
## Notes
|
|
218
218
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: seo-analytics-strategist
|
|
3
3
|
description: "Use this agent when you need to define SEO strategy, metadata requirements, analytics event plans, or technical SEO specifications for a company website. This agent produces actionable requirements documents that coder agents can implement directly.\n\nExamples:\n\n<example>\nContext: User is building a new company website and needs SEO foundations.\nuser: \"We're launching our company website next month and need to make sure it's discoverable on Google.\"\nassistant: \"I'll use the SEO & Analytics Strategist agent to create a comprehensive SEO and analytics plan for your website launch.\"\n<Task tool invocation to launch seo-analytics-strategist agent>\n</example>\n\n<example>\nContext: User wants to add analytics tracking to existing pages.\nuser: \"We need to track user interactions on our website - button clicks, form submissions, that kind of thing.\"\nassistant: \"Let me invoke the SEO & Analytics Strategist agent to design a complete GA4/GTM event tracking plan with exact specifications for implementation.\"\n<Task tool invocation to launch seo-analytics-strategist agent>\n</example>\n\n<example>\nContext: User mentions search rankings or organic traffic concerns.\nuser: \"Our competitors are ranking higher than us for industry keywords. What should we do?\"\nassistant: \"I'll use the SEO & Analytics Strategist agent to develop a keyword and intent map along with a metadata strategy to improve your search visibility.\"\n<Task tool invocation to launch seo-analytics-strategist agent>\n</example>\n\n<example>\nContext: Developer needs SEO requirements before implementing pages.\nuser: \"I'm about to code the new services pages. What SEO elements do I need to include?\"\nassistant: \"Let me launch the SEO & Analytics Strategist agent to provide you with exact SEO requirements including metadata, schema markup, and internal linking specifications that you can implement directly.\"\n<Task tool invocation to launch seo-analytics-strategist agent>\n</example>"
|
|
4
|
-
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
model: sonnet
|
|
5
6
|
color: pink
|
|
6
7
|
---
|
|
7
8
|
|
|
@@ -321,7 +321,7 @@ if (typeof a.codexScriptPath === 'string' && /codex-companion\.mjs$/.test(a.code
|
|
|
321
321
|
`Resolve the Codex companion script path. Run EXACTLY this one Bash command and nothing else:\n` +
|
|
322
322
|
" ls -d ~/.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/codex-companion.mjs ~/.claude/plugins/cache/openai-codex/codex/*/scripts/codex-companion.mjs 2>/dev/null | sort -V | tail -1\n" +
|
|
323
323
|
`Return codexScriptPath = the trimmed stdout (a single absolute path), or "" if the command printed nothing. Do NOT run Codex, do NOT read any other file, do NOT reason about availability — just report the command's stdout.`,
|
|
324
|
-
{ label: 'codex-preflight', phase: 'Discovery', model: '
|
|
324
|
+
{ label: 'codex-preflight', phase: 'Discovery', model: 'sonnet', schema: PREFLIGHT_SCHEMA }
|
|
325
325
|
)
|
|
326
326
|
codexScriptPath = (pf && typeof pf.codexScriptPath === 'string') ? pf.codexScriptPath.trim() : ''
|
|
327
327
|
} catch (_) { codexScriptPath = '' }
|
|
@@ -302,7 +302,7 @@ if (typeof a.codexScriptPath === 'string' && /codex-companion\.mjs$/.test(a.code
|
|
|
302
302
|
`Resolve the Codex companion script path. Run EXACTLY this one Bash command and nothing else:\n` +
|
|
303
303
|
" ls -d ~/.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/codex-companion.mjs ~/.claude/plugins/cache/openai-codex/codex/*/scripts/codex-companion.mjs 2>/dev/null | sort -V | tail -1\n" +
|
|
304
304
|
`Return codexScriptPath = the trimmed stdout (a single absolute path), or "" if the command printed nothing. Do NOT run Codex, do NOT read any other file, do NOT reason about availability — just report the command's stdout.`,
|
|
305
|
-
{ label: 'codex-preflight', phase: 'Review', model: '
|
|
305
|
+
{ label: 'codex-preflight', phase: 'Review', model: 'sonnet', schema: PREFLIGHT_SCHEMA }
|
|
306
306
|
)
|
|
307
307
|
codexScriptPath = (pf && typeof pf.codexScriptPath === 'string') ? pf.codexScriptPath.trim() : ''
|
|
308
308
|
} catch (_) { codexScriptPath = '' }
|
|
@@ -505,7 +505,7 @@ async function rollbackCard(cardId, mayEdit) {
|
|
|
505
505
|
try {
|
|
506
506
|
const r = await agentSafe(
|
|
507
507
|
`In the worktree ${sharedCtx.worktreePath}, restore the working tree to a CLEAN state for a FAILED card: \`git restore --source=HEAD --worktree --staged -- ${scope}\` then \`git clean -fd ${scope === '.' ? '' : '-- ' + scope}\` (with scope '.' this cleans the whole worktree — safe: all committed work lives in HEAD). Do NOT touch other cards' committed work. Confirm \`git status --porcelain\` is empty for the scope.`,
|
|
508
|
-
{ label: `rollback:${cardId}`, phase: 'Implement', agentType: 'general-purpose', model: '
|
|
508
|
+
{ label: `rollback:${cardId}`, phase: 'Implement', agentType: 'general-purpose', model: 'sonnet',
|
|
509
509
|
schema: { type: 'object', required: ['clean'], additionalProperties: true, properties: { clean: { type: 'boolean' }, note: { type: 'string' } } } }
|
|
510
510
|
)
|
|
511
511
|
return !!(r && r.clean)
|
|
@@ -562,7 +562,8 @@ async function runCard(cardId, cardPath) {
|
|
|
562
562
|
// agents/analysis-profiles.md § 3 caller routing table.
|
|
563
563
|
`PROFILE=${node.hasMockup ? 'ui' : 'feature'} OUTPUT=terse — resolve your analysis profile per agents/analysis-profiles.md (Grep "### PROFILE: ${node.hasMockup ? 'ui' : 'feature'}", Read only that section + its cited shared blocks).\n\n${cardBrief}\n\n` +
|
|
564
564
|
`Explore the codebase exactly as your system prompt + profile mandate for this card's scope (requirements + files_likely_touched: ${JSON.stringify(node.filesLikelyTouched || [])}). Write your COMPLETE untruncated findings (file paths, type signatures, patterns, high-risk paths) to ${baselinePath} — refresh it if a stale copy exists. The owner agent and the per-card reviewers will Read that file; keep your structured return MINIMAL.\n\n` +
|
|
565
|
-
`Also report missingPaths: every path in files_likely_touched that does NOT exist in the worktree (factual ls/test check — no judgement).
|
|
565
|
+
`Also report missingPaths: every path in files_likely_touched that the card expects to ALREADY exist but does NOT exist in the worktree (factual ls/test check — no judgement). EXCLUDE paths the card itself CREATES (NEW files: migrations with placeholder timestamps, new tests, new components declared in scope) — those are not drift (FEAT-0067 false-positive class).\n\n` +
|
|
566
|
+
`Your StructuredOutput MUST be exactly this shape — the boolean property \`ok\` is REQUIRED at the top level (missing it fails schema validation and burns a retry): { "ok": true|false, "missingPaths": ["..."], "note": "..." }. ok:false ONLY if you could not explore the worktree at all.`,
|
|
566
567
|
{ label: `architect:${cardId}`, phase: 'Implement', agentType: 'codebase-architect',
|
|
567
568
|
schema: { type: 'object', required: ['ok'], additionalProperties: true, properties: { ok: { type: 'boolean' }, missingPaths: { type: 'array', items: { type: 'string' } }, note: { type: 'string' } } } }
|
|
568
569
|
)
|
|
@@ -853,11 +854,12 @@ async function runCard(cardId, cardPath) {
|
|
|
853
854
|
`Read the Codex output ONLY through a [codex]-trace-stripping filter. **Fallback**: if it exits non-zero / prints CODEX_NOT_FOUND / stays empty, return note:'codex-unavailable' with EMPTY blocks/scopeExpansion — do NOT review yourself (role boundary); the workflow spawns the real code-reviewer.\n\n` +
|
|
854
855
|
`Map Codex BLOCKER/HIGH findings to blocks:[{gate:'codex-light',domain,evidence}] (each non-empty gate AND evidence — F-014). Map legitimate findings BEYOND this card's AC to scopeExpansion:[{evidence,domain,withinOwnership,newAC}].\n\n` +
|
|
855
856
|
`Return: { blocks:[...], scopeExpansion:[...], note }`,
|
|
856
|
-
//
|
|
857
|
+
// Sonnet, not the inherited opus: this agent is a pure DRIVER — it runs the Codex companion
|
|
857
858
|
// (node + --wait), strips [codex] traces, and maps the companion's findings into the schema.
|
|
858
859
|
// The review INTELLIGENCE is Codex (a different model, run externally); driving it needs no
|
|
859
|
-
// opus reasoning
|
|
860
|
-
|
|
860
|
+
// opus reasoning. Haiku is BANNED fleet-wide since v5.3.0 (FEAT-0067 post-mortem: a haiku
|
|
861
|
+
// plumbing agent dropped the `cd` on its second git command and committed to the MAIN repo).
|
|
862
|
+
{ label: `review:${cardId}:codex`, phase: 'Implement', agentType: 'general-purpose', model: 'sonnet', schema: reviewSchema }
|
|
861
863
|
).catch(onErr)
|
|
862
864
|
}
|
|
863
865
|
return stdReview(ra)
|
|
@@ -929,10 +931,11 @@ async function runCard(cardId, cardPath) {
|
|
|
929
931
|
try {
|
|
930
932
|
commitRes = await agentSafe(
|
|
931
933
|
`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` +
|
|
932
|
-
`
|
|
934
|
+
`HARD RULE — cwd: EVERY shell command MUST begin with \`cd ${sharedCtx.worktreePath} && \` IN THE SAME Bash invocation. The shell cwd RESETS between Bash calls to the MAIN repo: a bare \`git commit\` executes against the main checkout's current branch and corrupts it (observed in FEAT-0067 — a card-DONE commit landed on the trunk mid-run). No exceptions, including 'quick' status/log commands.\n` +
|
|
935
|
+
`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); (6) VERIFY placement: \`cd ${sharedCtx.worktreePath} && git log -1 --format=%H\` MUST equal the sha you return — if it does not, your commit landed outside the worktree: report committed:false with reconcileNote naming the stray sha, do NOT retry blindly.\n` +
|
|
933
936
|
`On COMMIT_LOCK: clear stale lock + retry once. Still locked → committed:false.\n\n` +
|
|
934
937
|
`Return: { committed, commit, filesChanged, reconcileNote }`,
|
|
935
|
-
{ label: `commit:${cardId}`, phase: 'Implement', agentType: 'general-purpose', model: '
|
|
938
|
+
{ label: `commit:${cardId}`, phase: 'Implement', agentType: 'general-purpose', model: 'sonnet',
|
|
936
939
|
schema: { type: 'object', required: ['committed'], additionalProperties: true, properties: { committed: { type: 'boolean' }, commit: { type: 'string' }, filesChanged: { type: 'array', items: { type: 'string' } }, reconcileNote: { type: 'string' } } } }
|
|
937
940
|
)
|
|
938
941
|
} catch (e) {
|
|
@@ -1116,10 +1119,10 @@ async function integrateCrossCard() {
|
|
|
1116
1119
|
// ONE integration commit (the fixes cross card boundaries); mark fully-freed cards DONE in YAML.
|
|
1117
1120
|
try {
|
|
1118
1121
|
await agentSafe(
|
|
1119
|
-
`Commit the cross-card integration fixes in worktree ${sharedCtx.worktreePath}. MECHANICAL — do NOT modify source beyond what is already changed on disk. Steps:\n` +
|
|
1122
|
+
`Commit the cross-card integration fixes in worktree ${sharedCtx.worktreePath}. MECHANICAL — do NOT modify source beyond what is already changed on disk. HARD RULE — cwd: EVERY shell command MUST begin with \`cd ${sharedCtx.worktreePath} && \` in the SAME Bash invocation (the shell cwd resets to the MAIN repo between calls; a bare git command corrupts the main checkout). Steps:\n` +
|
|
1120
1123
|
`(1) \`git status --porcelain\`; (2) stage ONLY dirty files within the batch union ${JSON.stringify(batchUnion)} — NEVER \`git add -A\`, NEVER \`git stash\`; (3) for each fully-freed card YAML [${fullyFreed.join(', ') || '(none)'}] set status to DONE and add implementation_note "cross-card integration: deferred AC resolved with batch-union ownership (new2 v4.30.0)"${SESSION_ID ? ' and set provenance.implementation_session: "' + SESSION_ID + '" (do NOT touch planning_session)' : ''}; (4) commit message \`[integrate] cross-card residual fixes${fullyFreed.length ? ' (' + fullyFreed.join(', ') + ')' : ''}\`; (5) 'nothing to commit' = the resolve already committed (record HEAD).\n` +
|
|
1121
1124
|
`Return: { committed, commit, filesChanged }`,
|
|
1122
|
-
{ label: 'integrate:commit', phase: 'Integrate', agentType: 'general-purpose', model: '
|
|
1125
|
+
{ label: 'integrate:commit', phase: 'Integrate', agentType: 'general-purpose', model: 'sonnet',
|
|
1123
1126
|
schema: { type: 'object', required: ['committed'], additionalProperties: true, properties: { committed: { type: 'boolean' }, commit: { type: 'string' }, filesChanged: { type: 'array', items: { type: 'string' } } } } }
|
|
1124
1127
|
)
|
|
1125
1128
|
} catch (e) { if (e && e.transientExhausted) noteDegraded('outage') }
|
|
@@ -1259,7 +1262,7 @@ if (!committed.length) {
|
|
|
1259
1262
|
// YAML status reconciliation + grep-based epic closure + leave-and-report hygiene gates), and
|
|
1260
1263
|
// the correctness-critical checks (F-029 forcedDone guard, F-040 deferred guard) are enforced
|
|
1261
1264
|
// in JS AFTER it returns — they do NOT depend on the agent's reasoning. Opus here is pure cost;
|
|
1262
|
-
//
|
|
1265
|
+
// sonnet is also the fleet-wide plumbing floor (haiku banned since v5.3.0).
|
|
1263
1266
|
{ label: 'merge', phase: 'Merge', agentType: 'general-purpose', model: 'sonnet', schema: MERGE_SCHEMA }
|
|
1264
1267
|
)
|
|
1265
1268
|
} catch (e) { if (e && e.transientExhausted) noteDegraded('outage'); mergeResult = null }
|