@entelligentsia/forgecli 0.11.2 → 0.15.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +324 -0
  2. package/README.md +2 -1
  3. package/dist/CHANGELOG-forge-plugin.md +210 -0
  4. package/dist/bin/forge.js +20 -1
  5. package/dist/bin/forge.js.map +1 -1
  6. package/dist/extensions/forgecli/ask-user-tool.js +32 -20
  7. package/dist/extensions/forgecli/ask-user-tool.js.map +1 -1
  8. package/dist/extensions/forgecli/config-layer.d.ts +15 -0
  9. package/dist/extensions/forgecli/config-layer.js +4 -1
  10. package/dist/extensions/forgecli/config-layer.js.map +1 -1
  11. package/dist/extensions/forgecli/config-writer.js +4 -1
  12. package/dist/extensions/forgecli/config-writer.js.map +1 -1
  13. package/dist/extensions/forgecli/enhance.js +1 -1
  14. package/dist/extensions/forgecli/enhance.js.map +1 -1
  15. package/dist/extensions/forgecli/fix-bug.js +31 -1
  16. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  17. package/dist/extensions/forgecli/forge-cli-schema.json +19 -0
  18. package/dist/extensions/forgecli/forge-tools.js +80 -0
  19. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  20. package/dist/extensions/forgecli/forge-update-command.js +24 -18
  21. package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
  22. package/dist/extensions/forgecli/friction-emit.d.ts +97 -0
  23. package/dist/extensions/forgecli/friction-emit.js +246 -0
  24. package/dist/extensions/forgecli/friction-emit.js.map +1 -0
  25. package/dist/extensions/forgecli/health-check.d.ts +10 -0
  26. package/dist/extensions/forgecli/health-check.js +160 -8
  27. package/dist/extensions/forgecli/health-check.js.map +1 -1
  28. package/dist/extensions/forgecli/hook-dispatcher.js +24 -2
  29. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  30. package/dist/extensions/forgecli/hooks/write-guard.js +5 -1
  31. package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -1
  32. package/dist/extensions/forgecli/index.js +29 -5
  33. package/dist/extensions/forgecli/index.js.map +1 -1
  34. package/dist/extensions/forgecli/lib/store-error-remediation.d.ts +65 -0
  35. package/dist/extensions/forgecli/lib/store-error-remediation.js +298 -0
  36. package/dist/extensions/forgecli/lib/store-error-remediation.js.map +1 -0
  37. package/dist/extensions/forgecli/regenerate.d.ts +22 -0
  38. package/dist/extensions/forgecli/regenerate.js +133 -3
  39. package/dist/extensions/forgecli/regenerate.js.map +1 -1
  40. package/dist/extensions/forgecli/run-sprint.js +16 -1
  41. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  42. package/dist/extensions/forgecli/run-task.js +30 -8
  43. package/dist/extensions/forgecli/run-task.js.map +1 -1
  44. package/dist/extensions/forgecli/skill-curation-flag.d.ts +21 -0
  45. package/dist/extensions/forgecli/skill-curation-flag.js +71 -0
  46. package/dist/extensions/forgecli/skill-curation-flag.js.map +1 -0
  47. package/dist/extensions/forgecli/skill-curator-subagent.d.ts +101 -0
  48. package/dist/extensions/forgecli/skill-curator-subagent.js +342 -0
  49. package/dist/extensions/forgecli/skill-curator-subagent.js.map +1 -0
  50. package/dist/extensions/forgecli/skill-retriever.d.ts +84 -0
  51. package/dist/extensions/forgecli/skill-retriever.js +246 -0
  52. package/dist/extensions/forgecli/skill-retriever.js.map +1 -0
  53. package/dist/extensions/forgecli/skill-usage-tracker.d.ts +91 -0
  54. package/dist/extensions/forgecli/skill-usage-tracker.js +224 -0
  55. package/dist/extensions/forgecli/skill-usage-tracker.js.map +1 -0
  56. package/dist/extensions/forgecli/store-resolver.d.ts +18 -0
  57. package/dist/extensions/forgecli/store-resolver.js +44 -4
  58. package/dist/extensions/forgecli/store-resolver.js.map +1 -1
  59. package/dist/extensions/forgecli/store-validator.d.ts +3 -0
  60. package/dist/extensions/forgecli/store-validator.js +4 -2
  61. package/dist/extensions/forgecli/store-validator.js.map +1 -1
  62. package/dist/forge-payload/.base-pack/personas/supervisor.md +9 -0
  63. package/dist/forge-payload/.base-pack/workflows/enhance.md +344 -18
  64. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  65. package/dist/forge-payload/.schemas/event.schema.json +20 -2
  66. package/dist/forge-payload/.schemas/migrations.json +112 -0
  67. package/dist/forge-payload/.schemas/proposal.schema.json +40 -0
  68. package/dist/forge-payload/agents/store-query-validator.md +103 -0
  69. package/dist/forge-payload/agents/tomoshibi.md +185 -0
  70. package/dist/forge-payload/commands/regenerate.md +109 -20
  71. package/dist/forge-payload/hooks/check-update.js +378 -0
  72. package/dist/forge-payload/hooks/forge-permissions.js +158 -0
  73. package/dist/forge-payload/hooks/triage-error.js +71 -0
  74. package/dist/forge-payload/hooks/validate-write.js +236 -0
  75. package/dist/forge-payload/integrity.json +32 -0
  76. package/dist/forge-payload/meta/workflows/meta-enhance.md +344 -18
  77. package/dist/forge-payload/schemas/structure-manifest.json +511 -0
  78. package/dist/forge-payload/tools/build-persona-pack.cjs +120 -11
  79. package/dist/forge-payload/tools/compression-gate.cjs +192 -0
  80. package/dist/forge-payload/tools/delete-candidate-detector.cjs +114 -0
  81. package/dist/forge-payload/tools/judge-proposal.cjs +177 -0
  82. package/dist/forge-payload/tools/manage-versions.cjs +132 -4
  83. package/dist/forge-payload/tools/queue-drain.cjs +152 -0
  84. package/dist/forge-payload/tools/replay-scoring.cjs +117 -0
  85. package/node_modules/@mariozechner/clipboard/package.json +2 -1
  86. package/node_modules/@mariozechner/clipboard-linux-x64-musl/README.md +3 -0
  87. package/node_modules/@mariozechner/clipboard-linux-x64-musl/clipboard.linux-x64-musl.node +0 -0
  88. package/node_modules/@mariozechner/clipboard-linux-x64-musl/package.json +25 -0
  89. package/package.json +4 -2
@@ -1,4 +1,116 @@
1
1
  {
2
+ "0.46.0": {
3
+ "version": "0.46.1",
4
+ "date": "2026-05-22",
5
+ "notes": "build: regenerate base-pack/workflows/enhance.md from meta sources to ship the FORGE-S24 SKILL-CURATION Phase 2 pipeline. The 0.45.1–0.45.7 entries declared `workflows:enhance` in their `regenerate` lists, but the meta→base-pack derivation (node tools/build-base-pack.cjs) was not re-run during the sprint, so the installable workflow stayed at the pre-S24 algorithm and downstream projects migrating to 0.46.0 received a stale workflow that lacked queue-drain (step 1a), recurrence scoring, delete-candidate detection (step 5b), compression gate (step 5b.5), and the LLM-judge step (step 5c). This patch bump regenerates the base-pack copy (init/base-pack/workflows/enhance.md — 280→600 lines, 20 S24 markers landed) and forces a re-copy on any project sitting at 0.46.0 by declaring `workflows:enhance` here. No plugin source change beyond the regenerated workflow file. Additive, non-breaking.",
6
+ "regenerate": ["workflows:enhance"],
7
+ "breaking": false,
8
+ "manual": []
9
+ },
10
+ "0.45.7": {
11
+ "version": "0.46.0",
12
+ "date": "2026-05-22",
13
+ "notes": "chore: FORGE-S24 SKILL-CURATION sprint completion — gated rollout marker (FORGE-S24-T12). No plugin source change in this bump; the seven preceding entries (0.45.1 → 0.45.7) carry the actual SKILL-CURATION machinery: `skill_usage` event variant (T01, 0.45.1), proposal op classification (T02, 0.45.2), recurrence scoring (T04, 0.45.3), delete-candidate detection (T05, 0.45.4), LLM-judge rubric (T03, 0.45.5), compression gate (T06, 0.45.6), and queue-drain (T07, 0.45.7). T12 lands the gated-rollout contract on the forge-cli side via `forgeCli.skillCuration.enabled` (default OFF) — the four forge-cli modules (T08 skill-retriever, T09 skill-usage-tracker, T10 skill-curator-subagent, T11 friction-emit) no-op at entry when the flag is off, so a flag-off run is byte-identical to pre-FORGE-S24 behaviour. This plugin-side minor bump (0.45.7 → 0.46.0) is the convergent terminal marker for the sprint: it signals to operators running `/forge:update` that the full SKILL-CURATION pipeline has shipped end-to-end, and pairs with the forge-cli 0.13.4 → 0.14.0 bump that lands the rollout flag. No regeneration is required (no manifest entry change, no workflow change, no schema change in this bump alone — those landed in 0.45.1–0.45.7). Operators who want to enable the pipeline must (1) upgrade forge-cli to 0.14.0+ AND (2) set `forgeCli.skillCuration.enabled: true` in their project config at `<cwd>/.pi/forge-cli/config.json` (or the env override `FORGE_CLI_SKILL_CURATION_ENABLED=1` for one-shot operator use). Until both conditions hold, the new event variants and friction subkinds remain emitter-silent — the plugin schema continues to accept them on receipt, so a delayed forge-cli upgrade is non-blocking. Additive, non-breaking.",
14
+ "regenerate": [],
15
+ "breaking": false,
16
+ "manual": []
17
+ },
18
+ "0.45.6": {
19
+ "version": "0.45.7",
20
+ "date": "2026-05-22",
21
+ "notes": "feat: queue drain at sprint close — per-task curator → batched review (FORGE-S24-T07). Adds `forge/tools/queue-drain.cjs` exporting `bodyHash(body)` (sha256 hex digest, UTF-8), `dedupeKey(proposal)` (`<op>|<target_path>|<sha256(diff_body)>` composite), `dedupeProposals(proposals)` (first-seen-wins, no-mutation), `queuePathFor({queueRoot, sprintId, taskId, ts})` (canonical `.forge/enhancement-proposals/queue/<sprintId>/<taskId>-<ts>.json` path), `appendToQueue({queueRoot, sprintId, taskId, ts, proposals})` (writes one file per curator run; throws if path exists — append-only invariant per AC1), and `drainQueue({queueRoot, sprintId})` (returns `{proposals, files, errors}` after deduping the sprint sub-dir; empty-safe when queue missing per AC5; skips malformed JSON and reports them via `errors`; deterministic lexicographic file ordering ⇒ chronological because of the ts suffix). Per-task curators (T10) append proposals to the queue throughout the sprint without collision (AC2 — distinct ts per call); Phase 2 reads the queue once at sprint close, dedupes by `{op, target_path, body-hash}` (AC3), and merges the queued proposals with the friction-synthesised ones, then feeds a SINGLE batched array through recurrence (T04) → delete-candidate detection (T05) → compression gate (T06) → judge (T03) — one prompt per sprint, not one per task (AC4, paper §3.2.1 grouped reward). `meta/workflows/meta-enhance.md` Phase 2 gains step 1a (drain queue) and step-5 merge sub-block; the zero-input guard now checks both friction events AND queued proposals before exiting cleanly with `frictionCount:0,queuedCount:0`. The drain is read-only — Phase 2 never deletes queue files; operators triage them during retrospective. Test-first per Iron Law 2: `queue-drain.test.cjs` (19 cases — exports surface, bodyHash sha256 contract + empty-body digest + collision contract, dedupeKey AC3 composite + field-sensitivity, dedupeProposals dedup + order-preservation + no-mutation + empty + non-array, queuePathFor AC1 canonical layout + input validation x3, appendToQueue AC1 fresh-file write + AC2 no-collision + append-only refusal, drainQueue AC5 empty/missing safety + AC3 multi-file dedup merge + AC4 single-batch output + sprint scoping + input validation x2 + malformed-JSON resilience) landed before the helper. Pure helpers; fs-touching helpers are `appendToQueue` and `drainQueue` only. Full suite 1437/1437 (was 1418; +19). Additive, non-breaking.",
22
+ "regenerate": ["tools:queue-drain", "workflows:enhance"],
23
+ "breaking": false,
24
+ "manual": []
25
+ },
26
+ "0.45.5": {
27
+ "version": "0.45.6",
28
+ "date": "2026-05-22",
29
+ "notes": "feat: compression gate — reject >20% growth without 3+ frictions (FORGE-S24-T06). Adds `forge/tools/compression-gate.cjs` exporting `GROWTH_THRESHOLD` (0.20), `MIN_SUPPORTING_FRICTIONS` (3), `evaluateGrowth({currentBody, newBody}) -> {currentBytes, newBytes, growthRatio}`, `evaluateProposal({proposal, currentBody, newBody, supportingFrictionCount}) -> {admit, reason, growthRatio, currentBytes, newBytes, supportingFrictionCount, threshold, minSupportingFrictions, op}`, and `filterProposals({proposals, currentBodyFor, newBodyFor, supportingFrictionCountFor}) -> {admitted, rejected}`. The gate runs in `meta/workflows/meta-enhance.md` Phase 2 as new step 5b.5 BEFORE the LLM judge (5c) — cheap deterministic filter first. Only `update_skill` proposals are gated; `insert_skill` and `delete_skill` pass through unconditionally (insert bloat is the judge's `body_under_2kb` axis; delete only shrinks). Growth is measured byte-wise via `Buffer.byteLength(body, 'utf8')` on the new body that would land after applying the proposal's diff. Threshold comparison is strict (>0.20) so ties at exactly 20% admit. Default supporting friction count = `proposal.sourceFrictionIds.length`; the caller may override via `supportingFrictionCountFor(proposal)` when the policy is to count frictions citing the same skill across the sprint. Updates on an empty current body yield `growthRatio: Infinity` and the friction-support rule still applies; shrinks (negative growth) admit unconditionally. Rejected proposals are persisted to the same `phase2-<timestamp>-rejections.json` sibling that the T03 judge writes, with reason `compression_gate_growth_unsupported` and the full evaluation record alongside the original proposal — every drop (gate or judge) stays traceable. Closes the unbounded-growth failure mode of SkillOS — pasting pages of trajectory copy-paste to 'patch' a friction now requires real recurrence evidence. Test-first per Iron Law 2: `compression-gate.test.cjs` (25 cases — GROWTH_THRESHOLD/MIN_SUPPORTING_FRICTIONS constants, evaluateGrowth shape, UTF-8 multibyte byte counting, empty-current-body Infinity ratio, AC1 0-friction rejection, AC2 3-friction admission, 2-friction insufficiency, AC5 exact-20% strict admission, under-threshold admission, sourceFrictionIds fallback, shrink admission, AC4 insert_skill/delete_skill pass-through, input validation x5, filterProposals AC6 ordering/partition, empty input, no-mutation invariant, callback contracts, supportingFrictionCountFor override) landed before the helper. Pure module; no fs access; no LLM call. Full suite 1418/1418 (was 1393; +25). Additive, non-breaking.",
30
+ "regenerate": ["tools:compression-gate", "workflows:enhance"],
31
+ "breaking": false,
32
+ "manual": []
33
+ },
34
+ "0.45.4": {
35
+ "version": "0.45.5",
36
+ "date": "2026-05-22",
37
+ "notes": "feat: LLM-judge step in Phase 2 — Sonnet rubric, drop <3/5 (FORGE-S24-T03). Adds `forge/tools/judge-proposal.cjs` exporting `RUBRIC_AXES` (frozen 5-axis tuple: specificity, when_not_to_use, no_trajectory_copy_paste, body_under_2kb, cites_friction), `scoreProposal(proposal) -> { axes, average }` (deterministic per-axis 0..5 scorer), and `decideJudgement({ axes }) -> { verdict, average, axes, reason }` (pure aggregator: verdict === 'drop' iff average < 3, strict; ties at 3.0 keep). The rubric is single-sourced in this helper — Sonnet's role is to apply the same axes and emit scores that the helper then validates and aggregates; in the absence of an LLM call the deterministic scorer is the fallback. `decideJudgement` fails loud on missing or out-of-range axes (RangeError) so a malformed score sheet never silently coerces into a verdict. `meta/workflows/meta-enhance.md` Phase 2 gains step 5c calling `scoreProposal` + `decideJudgement` for every proposal between delete-candidate detection (5b) and artifact write (6); kept proposals continue to step 6, dropped proposals are persisted to a sibling `phase2-<timestamp>-rejections.json` carrying the original proposal alongside `{ verdict, average, axes, reason }` so every rejection is traceable for retro review (AC3). Per-axis heuristics: specificity scores deep paths, named (non-generic) skill files, non-trivial rationales, and recurrence trails; when_not_to_use checks for the literal phrase; no_trajectory_copy_paste flags long verbatim runs or unbroken non-whitespace blocks >= 400 bytes; body_under_2kb gates on `Buffer.byteLength(diff_body,'utf8') <= 2048`; cites_friction rewards `sourceFrictionIds.length` >= 1, boosting for multi-citation and recurrence. Consumes recurrence data from T04 in the specificity and cites_friction axes — proposals that recurred across multiple tasks score higher. Test-first per Iron Law 2: `judge-proposal.test.cjs` (13 cases — rubric-axes shape, 5/5 keep fixture, 1/5 drop fixture, body byte boundary at exactly 2048, zero-citation suppression, phrase-presence binary, AC6 explicit 2.8/5 drop fixture, keep + drop end-to-end decisions, exact-3.0 boundary keeps, missing-axis RangeError, out-of-range RangeError) landed before the helper. Pure module; no fs access; no LLM call. Full suite 1393/1393 (was 1380; +13). Additive, non-breaking.",
38
+ "regenerate": ["tools:judge-proposal", "workflows:enhance"],
39
+ "breaking": false,
40
+ "manual": []
41
+ },
42
+ "0.45.3": {
43
+ "version": "0.45.4",
44
+ "date": "2026-05-22",
45
+ "notes": "feat: delete-candidate detection — 3-sprint zero-use (FORGE-S24-T05). Adds `forge/tools/delete-candidate-detector.cjs` exporting `scanZeroUse({events, sprintOrder, windowSize})` and `buildDeleteProposals({events, sprintOrder, windowSize, targetPathFor})`. The detector scans `skill_usage` events across the trailing `windowSize` (default 3) sprints; any skill with at least one in-window observation AND zero `retrieved` AND zero `used` qualifies as a delete candidate. Skills with zero in-window observations are explicitly NOT proposed — that case is indistinguishable from a newly-added skill that hasn't been loaded yet. `meta/workflows/meta-enhance.md` Phase 2 gains step 5b calling `buildDeleteProposals` between recurrence annotation (step 5a) and artifact write (step 6). Each delete proposal carries `op: 'delete_skill'`, `target_path` resolved via the supplied `targetPathFor(skillId)` callback, a diff body and rationale that name the cold skill and the observed sprints, `sourceFrictionIds: []` (usage-derived, not friction-derived), `window_size`, `window_sprint_ids`, plus neutral `recurrence_count: 1` and `recurrence_task_ids: []` so the proposal shape stays uniform with the rest of the Phase 2 array. Carry-over caveat documented in the workflow: the trailing-3-sprint window only becomes meaningful once 3 sprints have elapsed since `skill_usage` emission landed in T01 (0.45.1); short-history runs produce advisory rather than authoritative deletes. This is the only mechanism by which the skill repository shrinks, completing the three-op classification rollout from T02 (insert/update were already in play). Test-first per Iron Law 2: `delete-candidate-detector.test.cjs` (16 cases — three-sprint zero-use baseline, retrieved=true disqualification, used=true disqualification, trailing-window guard against pre-window usage, default windowSize 3, configurable windowSize, never-observed-in-window suppression, empty events, friction-event filtering, short-history carry-over case, no-mutation invariant, multi-skill output, deterministic ordering, callback contract, plus AC restatement cases) landed before the detector. Pure module; no fs access. Full suite 1380/1380 (was 1364; +16). Additive, non-breaking.",
46
+ "regenerate": ["tools:delete-candidate-detector", "workflows:enhance"],
47
+ "breaking": false,
48
+ "manual": []
49
+ },
50
+ "0.45.2": {
51
+ "version": "0.45.3",
52
+ "date": "2026-05-22",
53
+ "notes": "feat: cross-task replay scoring — recurrence boost (FORGE-S24-T04). Adds `forge/tools/replay-scoring.cjs` exporting `computeRecurrence({events, subkind, skillId, fromTaskId, taskOrder})` and `annotateProposals(proposals, frictionEvents, taskOrder)`. For each Phase 2 enrichment proposal synthesised from a friction event at task `t`, the annotator scans tasks `t+1..N` in the same sprint for friction events matching the same `(subkind, evidence.skillId)` pair and stamps `recurrence_count` (>= 1, includes the origin task) and `recurrence_task_ids` (taskOrder-sorted) onto the proposal. Forward-only scan: earlier tasks before `fromTaskId` are excluded. Proposals without resolvable `sourceFrictionIds` (eventId not in the friction set, or the resolved event lacks subkind/evidence.skillId) receive a neutral `recurrence_count: 1` and empty `recurrence_task_ids: []`. `meta/workflows/meta-enhance.md` Phase 2 gains step 5a calling `annotateProposals` between synthesis (step 5) and artifact write (step 6); the step 5 contract is tightened to require `sourceFrictionIds` to carry every contributing eventId so the recurrence scan can resolve provenance. `forge/schemas/proposal.schema.json` gains optional `recurrence_count` (integer minimum:1) and `recurrence_task_ids` (array of strings) properties — additive only, both fields are optional, `additionalProperties: false` continues to reject unknown keys. Feeds T03 (judge) so specificity scoring can boost frictions that recurred across multiple tasks. Test-first per Iron Law 2: `replay-scoring.test.cjs` (11 cases — AC3 three-task recurrence, single-task baseline, forward-only-direction guard, subkind mismatch rejection, skillId mismatch rejection, intra-task dedup, fromTaskId-outside-taskOrder fallback, missing-evidence guard, full annotateProposals happy path, unresolved-provenance neutral case, no-mutation invariant) landed before the helper. Full suite 1364/1364 (was 1353; +11). Additive, non-breaking.",
54
+ "regenerate": ["tools:replay-scoring", "schemas:proposal", "workflows:enhance"],
55
+ "breaking": false,
56
+ "manual": []
57
+ },
58
+ "0.45.1": {
59
+ "version": "0.45.2",
60
+ "date": "2026-05-22",
61
+ "notes": "feat: Phase 2 proposal op classification (FORGE-S24-T02). Adds `forge/schemas/proposal.schema.json` and `forge/tools/proposal-normalize.cjs`. The new schema enumerates `op` ∈ {insert_skill, update_skill, delete_skill} with required `target_path` + `diff_body`; `additionalProperties: false` rejects unknown fields. `meta/workflows/meta-enhance.md` Phase 2 (steps 5–6) now requires every enrichment proposal to carry this triplet and writes a machine-readable `phase2-<timestamp>.json` alongside the existing markdown artifact. Back-compat: legacy proposals without `op` are normalised to `insert_skill` via `proposal-normalize.cjs:normaliseProposal()` — downstream consumers route through the helper explicitly so normalisation is auditable. Foundation for T03 (judge), T05 (delete-candidate detection), T06 (compression gate), T07 (queue drain). Test-first per Iron Law 2: `proposal-schema.test.cjs` (6 cases including missing-op rejection, unknown-op rejection, additionalProperties:false, and the legacy normalisation contract) landed before the schema. Full suite 1353/1353. Additive, non-breaking.",
62
+ "regenerate": ["schemas:proposal"],
63
+ "breaking": false,
64
+ "manual": []
65
+ },
66
+ "0.45.0": {
67
+ "version": "0.45.1",
68
+ "date": "2026-05-22",
69
+ "notes": "feat: event.schema.json — new `skill_usage` event variant (FORGE-S24-T01, plan 08 Phase B). Adds `skill_usage` to the `type` enum and a conditional allOf branch requiring {skillId, retrieved, used, tool_call_success_rate, retrieval_score}. Top-level numeric properties (`tool_call_success_rate`, `retrieval_score`) carry [0,1] declarative bounds; `skillId` is `minLength: 1`. The root `additionalProperties: false` gate continues to reject unknown fields on every variant. Foundation for Sprint S24 SKILL-CURATION: T02 emits, T04 retrieval-score correlation, T05 delete-candidate detection, T08 replay scoring all consume records of this type. No code path change to validate-store.cjs — the existing validateRecord() handles the new allOf branch via the same machinery used for friction / sprint-complete / sprint-halted variants. Additive, non-breaking: existing event records remain valid. Note on target version: TASK_PROMPT requested v0.45.0 but that tag already shipped (snapshot-replay change); bumping to 0.45.1 is the minimum forward step.",
70
+ "regenerate": ["schemas:event"],
71
+ "breaking": false,
72
+ "manual": []
73
+ },
74
+ "0.44.10": {
75
+ "version": "0.45.0",
76
+ "date": "2026-05-21",
77
+ "notes": "feat: Approach A — snapshot replay (forge#107). manage-versions gains a new replay subcommand that restores user-enhanced files captured by /forge:enhance Phase 2 snapshots after /forge:regenerate writes fresh base-pack content. Fulfills layer 3 of the composition contract (Working Artifact = base + snapshot + user_enhancements) declared at manage-versions.cjs:13. regenerate.md updated to invoke replay per category (personas, skills, workflows, templates) between subagent generation and manifest record. Overlay semantics: user-enhanced files retain captured content; later snapshots win on collision. Pairs with v0.44.10 (forge#108 archive-path fix) which made layer 2 functional in the first place.",
78
+ "regenerate": ["commands:regenerate", "tools:manage-versions"],
79
+ "breaking": false,
80
+ "manual": []
81
+ },
82
+ "0.44.9": {
83
+ "version": "0.44.10",
84
+ "date": "2026-05-21",
85
+ "notes": "fix: manage-versions add-snapshot now archives files correctly when --enhanced-elements paths include the .forge/ prefix (forge#108). Previously, every archive directory has been created empty since basePackVersion 0.43.3 — layer 2 of the composition contract was silently a no-op. Tool now strips a leading .forge/ from each element path before joining; both .forge/-relative (e.g. personas/X.md) and project-root-relative (.forge/personas/X.md) forms accepted. Unblocks forge#107 (Approach A — snapshot replay). Pure tool fix.",
86
+ "regenerate": ["tools:manage-versions"],
87
+ "breaking": false,
88
+ "manual": []
89
+ },
90
+ "0.44.8": {
91
+ "version": "0.44.9",
92
+ "date": "2026-05-21",
93
+ "notes": "fix: /forge:regenerate personas + skills silently overwrote manual modifications (forge#106 / FORGE-BUG-037). Pre-write generation-manifest check added to both single-file and full-rebuild paths in commands/regenerate.md, mirroring the workflows + templates pattern. Closes asymmetric modification-detection across the four structural-element categories. Markdown-only fix.",
94
+ "regenerate": ["commands:regenerate"],
95
+ "breaking": false,
96
+ "manual": []
97
+ },
98
+ "0.44.7": {
99
+ "version": "0.44.8",
100
+ "date": "2026-05-21",
101
+ "notes": "fix: meta-enhance.md — add phase-routing guidance to command table; add zero-friction guard (skip steps 3-10; emit event with frictionCount=0); renumber Phase 2 steps 2-9 to 3-10 to align with zero-friction guard.",
102
+ "regenerate": ["workflows:enhance"],
103
+ "breaking": false,
104
+ "manual": []
105
+ },
106
+ "0.44.7": {
107
+ "version": "0.44.7",
108
+ "date": "2026-05-21",
109
+ "notes": "fix: build-persona-pack.cjs schema mismatch — tool now accepts both base-pack (no frontmatter) and meta (YAML frontmatter) persona files; derives id/role/summary/responsibilities/outputs/file_ref from content for base-pack; derives file_ref from path for base-pack skills; throws (no empty-pack write) when both dirs are empty.",
110
+ "regenerate": ["tools:build-persona-pack"],
111
+ "breaking": false,
112
+ "manual": []
113
+ },
2
114
  "0.44.5": {
3
115
  "version": "0.44.6",
4
116
  "date": "2026-05-20",
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "forge/proposal.schema.json",
4
+ "title": "EnhancementProposal",
5
+ "description": "A single Phase 2 enrichment proposal emitted by /forge:enhance. Each record carries an op classification (insert/update/delete a skill artifact), the target file path, and a diff body. Foundation for the T03 judge, T05 delete detection, T06 compression gate, and T07 queue drain.",
6
+ "type": "object",
7
+ "required": ["op", "target_path", "diff_body"],
8
+ "properties": {
9
+ "proposalId": { "type": "string", "minLength": 1 },
10
+ "op": {
11
+ "type": "string",
12
+ "enum": ["insert_skill", "update_skill", "delete_skill"],
13
+ "description": "Three-op classification: insert a new skill artifact, update an existing one, or delete an existing one."
14
+ },
15
+ "target_path": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "description": "Repository-relative path to the artifact being inserted, updated, or deleted (e.g. forge/skills/engineer-skills.md)."
19
+ },
20
+ "diff_body": {
21
+ "type": "string",
22
+ "description": "Unified-diff body or full file body for inserts. For delete_skill this may be empty — the op + target_path is sufficient."
23
+ },
24
+ "rationale": { "type": "string" },
25
+ "sourceFrictionIds": { "type": "array", "items": { "type": "string" } },
26
+ "generated_at": { "type": "string", "format": "date-time" },
27
+ "sprintId": { "type": "string" },
28
+ "recurrence_count": {
29
+ "type": "integer",
30
+ "minimum": 1,
31
+ "description": "FORGE-S24-T04 — count of distinct tasks within the same sprint that emitted a matching (subkind, evidence.skillId) friction event, including the originating task. Always >= 1."
32
+ },
33
+ "recurrence_task_ids": {
34
+ "type": "array",
35
+ "items": { "type": "string" },
36
+ "description": "FORGE-S24-T04 — taskOrder-sorted list of task IDs that contributed to recurrence_count. Empty when the originating friction event cannot be resolved from sourceFrictionIds."
37
+ }
38
+ },
39
+ "additionalProperties": false
40
+ }
@@ -0,0 +1,103 @@
1
+ ---
2
+ description: Validate Forge store query results — check completeness, detect low-confidence parses, identify missing relationships, and suggest corrective queries. Invoked after store-query-nlp returns results for high-stakes decisions.
3
+ ---
4
+
5
+ # forge:store-query-validator
6
+
7
+ You are a query result validator. Your job is narrow: inspect the output of
8
+ `store-cli.cjs nlp` or `store-cli.cjs query`, identify quality issues, and
9
+ either confirm the results are reliable or produce a corrective follow-up query.
10
+
11
+ ## Setup
12
+
13
+ ```sh
14
+ FORGE_ROOT=$(node -e "console.log(require('./.forge/config.json').paths.forgeRoot)")
15
+ ```
16
+
17
+ ## Input
18
+
19
+ You receive a store query result JSON object (stdout from `store-cli.cjs nlp`).
20
+
21
+ ## Validation Checks
22
+
23
+ ### 1. Confidence signal
24
+
25
+ Read `traversalTrace` for confidence indicators:
26
+
27
+ - `plan confidence: high` → filters were valid; results are likely complete
28
+ - `plan confidence: low` → one or more filters were stripped; results may be broader than intended
29
+ - `overall confidence: low (required retry)` → primary query returned 0 results; retry was keyword-only
30
+
31
+ If confidence is low, note which filter was stripped (from trace) and suggest a corrective query.
32
+
33
+ ### 2. Result completeness
34
+
35
+ - **0 results with no retry**: query may be too narrow. Suggest broadening: remove status filter, use keyword search, or check entity type.
36
+ - **0 results after retry**: entity likely doesn't exist or uses a different title. Suggest `schema` dump to verify valid enum values.
37
+ - **Results missing expected FKs**: check `relationships` on each result. If `blockedBy` or `blocksTask` is present but not expanded, suggest re-running with `--with-blockers` or `--with-blocked-tasks`.
38
+
39
+ ### 3. Entity type mismatch
40
+
41
+ Compare the `type` field in results against the intended entity type. If the query
42
+ intended bugs but returned tasks (or vice versa), the entity synonym was mismatched.
43
+ Suggest the corrected query with an explicit entity synonym.
44
+
45
+ ### 4. Excerpt quality
46
+
47
+ If `excerpt` is null on all results, the INDEX.md files may be missing or the KB is
48
+ not yet collated. Suggest:
49
+
50
+ ```sh
51
+ node "$FORGE_ROOT/tools/collate.cjs"
52
+ ```
53
+
54
+ ### 5. Stale IDs
55
+
56
+ If a result `id` doesn't match the expected prefix pattern for the project (detectable
57
+ from `config.project.prefix`), flag it as a potential schema drift issue.
58
+
59
+ ## Output Format
60
+
61
+ Produce a compact validation summary:
62
+
63
+ ```
64
+ 〇 Query: "open bugs in S12"
65
+ 〇 Path: intent-nlp | Confidence: high | Results: 4 | Time: 38ms
66
+
67
+ △ WI-BUG-047 — status: in-progress, excerpt: present
68
+ △ WI-BUG-051 — status: reported, excerpt: null (INDEX.md missing)
69
+ △ WI-BUG-055 — status: triaged, excerpt: present
70
+ △ WI-BUG-060 — status: in-progress, excerpt: present
71
+
72
+ × 1 missing excerpt — run: node "$FORGE_ROOT/tools/collate.cjs"
73
+ ```
74
+
75
+ Use `〇` for passing items, `△` for warnings, `×` for failures.
76
+
77
+ If all checks pass:
78
+
79
+ ```
80
+ 〇 Query validated — 4 results, high confidence, all excerpts present.
81
+ ```
82
+
83
+ ## Corrective Query Suggestions
84
+
85
+ When validation finds issues, always append a corrective query the caller can run immediately:
86
+
87
+ ```sh
88
+ # Suggested corrective query:
89
+ node "$FORGE_ROOT/tools/store-cli.cjs" nlp "<corrected intent>"
90
+ ```
91
+
92
+ ## When NOT to validate
93
+
94
+ Skip validation for:
95
+ - Count-only queries (`traverse.count === true`) — result is a number, not entities
96
+ - Schema dumps (`store-cli schema`) — no results to validate
97
+ - Explicit `--mode strict` queries where the caller already knows the IDs
98
+
99
+ ## Escalation
100
+
101
+ If validation cannot determine whether results are complete (e.g. store is empty,
102
+ config is missing, or FK traversal fails), escalate to the user with a clear
103
+ description of the ambiguity rather than silently accepting partial results.
@@ -0,0 +1,185 @@
1
+ ---
2
+ description: 🏮 Tomoshibi (灯) — Forge's concierge. Answers questions about project status, config, version, workflows, and commands. Also invokes forge:refresh-kb-links to update KB and workflow links in agent instruction files.
3
+ ---
4
+
5
+ # 🏮 灯 Tomoshibi — Forge Concierge
6
+
7
+ You are Tomoshibi (🏮 灯, "lamplight"), Forge's concierge. You are calm, precise,
8
+ and non-verbose. Prefix every substantive answer with 灯.
9
+
10
+ ## Setup
11
+
12
+ Read the Forge config to determine available capabilities:
13
+
14
+ ```sh
15
+ node "$FORGE_ROOT/tools/manage-config.cjs" get project 2>/dev/null
16
+ node "$FORGE_ROOT/tools/manage-config.cjs" get version 2>/dev/null
17
+ PREFIX_LOWER=$(node "$FORGE_ROOT/tools/manage-config.cjs" get project.prefix 2>/dev/null | tr '[:upper:]' '[:lower:]')
18
+ ```
19
+
20
+ Store `FORGE_ROOT` from the calling command's environment.
21
+
22
+ ## Intent routing
23
+
24
+ Classify the user's question (`$ARGUMENTS`) into one of the intents below, then execute
25
+ that path exactly. If the question is blank or ambiguous, present your capabilities and
26
+ prompt for intent.
27
+
28
+ ---
29
+
30
+ ### Project status
31
+
32
+ Triggered by: "active sprint", "open bugs", "active features", "in-progress tasks", etc.
33
+
34
+ ```sh
35
+ node "$FORGE_ROOT/tools/store-cli.cjs" list sprint status=active
36
+ node "$FORGE_ROOT/tools/store-cli.cjs" list bug status=in-progress
37
+ node "$FORGE_ROOT/tools/store-cli.cjs" list feature status=active
38
+ node "$FORGE_ROOT/tools/store-cli.cjs" list task status=implementing
39
+ ```
40
+
41
+ Present as a concise summary table with 〇/△/× marks. Never dump raw JSON.
42
+
43
+ ---
44
+
45
+ ### Config query
46
+
47
+ Triggered by: "what's my mode?", "show config", "what's the project name?", etc.
48
+
49
+ ```sh
50
+ node "$FORGE_ROOT/tools/manage-config.cjs" get <key>
51
+ ```
52
+
53
+ Read-only. Same data as `/forge:config` (no args). If config does not exist, direct the
54
+ user to `/forge:init`.
55
+
56
+ ---
57
+
58
+ ### Config change
59
+
60
+ Triggered by: "change project name to X", "set prefix to Y".
61
+
62
+ Permitted fields: `project.name`, `project.prefix` only.
63
+
64
+ **Regeneration impact** (show before confirming):
65
+
66
+ | Field | Impact |
67
+ |---|---|
68
+ | `project.prefix` | △ Requires regeneration — command folder renames from `.claude/commands/{old_lower}/` to `.claude/commands/{new_lower}/`, and generated workflow slash-command references become stale. Run `/forge:regenerate commands workflows` after confirming. |
69
+
70
+ *The prefix is stored as provided but the command namespace is always lowercase.*
71
+ | `project.name` | 〇 No regeneration needed. |
72
+
73
+ Protocol:
74
+ 1. Show current value.
75
+ 2. Describe the change.
76
+ 3. If the field requires regeneration, derive the lowercased paths and show the impact warning before asking:
77
+ ```sh
78
+ NEW_PREFIX_LOWER=$(echo "$proposed_new_value" | tr '[:upper:]' '[:lower:]')
79
+ ```
80
+ Show the concrete path: `.claude/commands/${PREFIX_LOWER}/ → .claude/commands/${NEW_PREFIX_LOWER}/`
81
+ 4. Prompt `[Y/n]`.
82
+ 5. On yes:
83
+ ```sh
84
+ node "$FORGE_ROOT/tools/manage-config.cjs" set <key> <value>
85
+ ```
86
+ 6. If regeneration is required, remind the user of the exact command to run next.
87
+
88
+ Never touch: `paths.*`, `calibrationBaseline`, `installedSkills`, or any Forge-managed field.
89
+ For restricted fields, explain which command owns them and redirect.
90
+
91
+ ---
92
+
93
+ ### Version check
94
+
95
+ Triggered by: "what version is installed?", "any updates?", etc.
96
+
97
+ ```sh
98
+ cat "$FORGE_ROOT/.claude-plugin/plugin.json"
99
+ ```
100
+
101
+ Report the `version` field. For "any updates?", explain that `/forge:update` does the live
102
+ remote check — Tomoshibi only knows the locally installed version.
103
+
104
+ ---
105
+
106
+ ### Workflow or command explanation
107
+
108
+ Triggered by: "how does sprint planning work?", "explain the implement workflow",
109
+ "what does /forge:calibrate do?", etc.
110
+
111
+ Read the relevant file:
112
+ - Workflows: `.forge/workflows/<name>.md`
113
+ - Commands: `$FORGE_ROOT/commands/<name>.md`
114
+
115
+ Produce a 3–5 sentence plain-language summary prefixed with 灯.
116
+
117
+ ---
118
+
119
+ ### Workflow modification guidance
120
+
121
+ Triggered by: "how do I change the review workflow?", "where do I edit the persona?", etc.
122
+
123
+ Advisory only — never write files. Explain the two-layer architecture:
124
+ - Generated files live in `.forge/workflows/`, `.forge/personas/`, `.forge/skills/`
125
+ - Meta source lives in `forge/meta/workflows/`, `forge/meta/personas/`
126
+ - Custom commands live in `engineering/commands/`
127
+
128
+ Describe what to edit and let the user do it.
129
+
130
+ ---
131
+
132
+ ### Refresh KB links
133
+
134
+ Triggered by: "update my KB links", "refresh KB links", "run Tomoshibi", "update agent instruction files", etc.
135
+
136
+ Use the Skill tool:
137
+ skill: "forge:refresh-kb-links"
138
+
139
+ ---
140
+
141
+ ### Anything else
142
+
143
+ Ask one clarifying question. Do not guess.
144
+
145
+ ---
146
+
147
+ ## Capabilities (shown when question is blank)
148
+
149
+ ```
150
+ 🏮 灯 Tomoshibi — I can help you with:
151
+
152
+ · Project status — active sprint, open bugs, active features, in-progress tasks
153
+ · Config queries — show or change project.name / project.prefix
154
+ · Version — locally installed Forge version
155
+ · Workflow help — how workflows work, step-by-step
156
+ · Command help — what any /forge: command does
157
+ · Modification guide — where to edit workflows, personas, or custom commands
158
+ · KB links — refresh KB and workflow links in agent instruction files
159
+
160
+ What would you like to know?
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Guardrails
166
+
167
+ | Resource | Read | Write |
168
+ |---|---|---|
169
+ | `.forge/config.json` | Yes | `project.name`, `project.prefix` only — with `[Y/n]` confirm |
170
+ | `.forge/store/` | `list`/`read` via `store-cli.cjs` only | **Never** — redirect to workflow commands |
171
+ | `.forge/workflows/`, `.forge/personas/`, `.forge/skills/` | Yes — to explain content | **Never** — redirect to `/forge:regenerate` |
172
+ | `engineering/` KB | Yes — to answer questions | **Never** — redirect to `/forge:calibrate` or sprint commands |
173
+ | `.claude/commands/` | Yes — to explain | **Never** — redirect to `/forge:regenerate commands` |
174
+ | `forge/` plugin source | No — internal impl detail | **Never** |
175
+
176
+ Forbidden store operations: `write`, `update-status`, `delete`, `emit`, `purge-events`.
177
+
178
+ Forbidden forge commands to invoke: `/forge:remove`, `/forge:init`, `/forge:migrate` —
179
+ Tomoshibi can *explain* these but never invokes them.
180
+
181
+ ## Output rules
182
+
183
+ - Japanese marks 〇/△/×; never ✅/❌/⚠️
184
+ - `灯` prefix on answers
185
+ - No `banners.cjs` calls inside the agent (visual is in the command preamble)