claude-alfred 0.3.19 → 0.3.21
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/README.ja.md +27 -1
- package/README.md +27 -1
- package/content/hooks/hooks.json +0 -5
- package/dist/cli.mjs +2 -2
- package/dist/{directives-BtMZZnDe.mjs → directives-DfzKzUAL.mjs} +1 -1
- package/dist/{dispatcher-Bl7px8hy.mjs → dispatcher-BDl_Flyx.mjs} +6 -6
- package/dist/{post-tool-BRoelm73.mjs → post-tool-BawR4gHR.mjs} +5 -5
- package/dist/{post-tool-BL5YKl-j.mjs → post-tool-DpBkq5ik.mjs} +4 -4
- package/dist/{pre-compact-DEqTQ_7v.mjs → pre-compact-Cncx9q7L.mjs} +1 -1
- package/dist/{pre-tool-YJGmHuiU.mjs → pre-tool-Dyp4S8cV.mjs} +43 -6
- package/dist/{review-gate-0cGEW7jx.mjs → review-gate-7Pfe_A-8.mjs} +1 -1
- package/dist/{server-DaiRsZ3w.mjs → server-D3b54XYU.mjs} +74 -30
- package/dist/{session-start-CrZszyvc.mjs → session-start-CU4-KivX.mjs} +3 -3
- package/dist/{state-XSGGyez_.mjs → state-Cih-8_Zc.mjs} +1 -1
- package/dist/{stop-gh3SchT6.mjs → stop-CGv96IQd.mjs} +2 -2
- package/dist/{user-prompt-la6CpECb.mjs → user-prompt-BPAOU8f-.mjs} +3 -3
- package/package.json +1 -1
- package/web/dist/assets/activity-BMH0Gseq.js +3 -0
- package/web/dist/assets/{alert-dialog-DOk2vAC0.js → alert-dialog-Df-NKKik.js} +1 -1
- package/web/dist/assets/button-BC81_2hy.js +1 -0
- package/web/dist/assets/dist-CCslGrjS.js +1 -0
- package/web/dist/assets/es2015-C0wv2Iox.js +41 -0
- package/web/dist/assets/index-BedjjxO2.css +1 -0
- package/web/dist/assets/index-ClD5S_3_.js +138 -0
- package/web/dist/assets/{knowledge-BVNS0rvw.js → knowledge-Cf76s4T9.js} +8 -8
- package/web/dist/assets/routes-DZR7VbL6.js +1 -0
- package/web/dist/assets/{stagger-container-Cw2dfuIA.js → stagger-container-ClpnejW9.js} +1 -1
- package/web/dist/assets/{tasks-6gs3T7RP.js → tasks-Byg4aFbV.js} +1 -1
- package/web/dist/assets/{tasks._slug-D_xK_slB.js → tasks._slug-jxqMGzVd.js} +10 -10
- package/web/dist/index.html +4 -4
- package/web/dist/assets/activity-CRNPQErc.js +0 -3
- package/web/dist/assets/button-DHDUbkWK.js +0 -1
- package/web/dist/assets/dist-Dkaca6_h.js +0 -1
- package/web/dist/assets/index-R19UEUEr.js +0 -178
- package/web/dist/assets/index-r1JIc2ya.css +0 -1
- package/web/dist/assets/routes-BVHQFTM8.js +0 -1
- package/web/dist/assets/tooltip-z-i3XAtt.js +0 -1
- /package/web/dist/assets/{dist-CzjiYFd3.js → dist-CbLvV7YE.js} +0 -0
package/README.ja.md
CHANGED
|
@@ -56,6 +56,32 @@ Claude Code で:
|
|
|
56
56
|
|
|
57
57
|
**ダッシュボードが使える。** `alfred dashboard` で `localhost:7575` が開く。タスク進捗、行レベルコメント付きレビュー、ファイル単位の承認、ナレッジの健全性、操作履歴。日英ワンクリック切替。
|
|
58
58
|
|
|
59
|
+
## 2026年に alfred が必要な理由
|
|
60
|
+
|
|
61
|
+
Claude Code は強力だが、構造なき AI コーディングには既知の問題がある:
|
|
62
|
+
|
|
63
|
+
- **初回成功率 ~30%** — spec による文脈がないと、Claude は完了を偽装し、エッジケースを飛ばし、「終わった」と言い張る。alfred の3層ゲート(spec → review → approval)がコードベースに到達する前にキャッチする。
|
|
64
|
+
- **セッション間のコンテキスト喪失** — 1M context(Opus 4.6)でも compact は発火する。alfred は決定・パターン・進捗を構造化 JSON で永続化。compact、セッション境界、モデル切替を超えて生存する。
|
|
65
|
+
- **無限リファクタリングループ** — bounded iteration がないと Claude は同じコードを何時間も書き直す。alfred の Wave ベース実装が commit → review → advance を強制。Wave あたり最大2回の fix ラウンド、超えたらエスカレート。
|
|
66
|
+
- **セキュリティ盲点** — AI 生成コードの45%に脆弱性(業界調査)。alfred は Wave 境界ごとに並列コードレビューエージェントを起動、セキュリティは専用のレビュー視点。
|
|
67
|
+
- **仕様と実装のドリフト** — 実装が始まった瞬間に仕様は古くなる。alfred の Living Spec が毎コミットで変更ファイルを design.md に自動追記。仕様が自動で正直になる。
|
|
68
|
+
|
|
69
|
+
### SDD と IDD の融合
|
|
70
|
+
|
|
71
|
+
業界は **Spec-Driven Development**(構造化仕様)と **Intent-Driven Development**(Why と What だけ、How は AI 任せ)の2つに収束しつつある。alfred は両方を橋渡し:
|
|
72
|
+
|
|
73
|
+
- **フル SDD** — M/L/XL 機能向け。要件、設計、タスク、テスト、トレーサビリティ、レビューゲート
|
|
74
|
+
- **軽量 IDD** — S/D 変更向け。要件 + 判断記録のみ、設計のオーバーヘッドなし
|
|
75
|
+
- **不変の判断記録** — `ledger save` で ADR ライクな意思決定を保存。プロジェクト・セッションを超えてセマンティック検索可能
|
|
76
|
+
|
|
77
|
+
### 1M context 時代の設計
|
|
78
|
+
|
|
79
|
+
Opus 4.6 の 1M context で compact は稀になったが、発火時の破壊力は5倍。alfred はこの現実に対応:
|
|
80
|
+
|
|
81
|
+
- **PreCompact hook** が構造化チャプターメモリ(ゴール、判断、サマリー)をコンテキスト消失前にキャプチャ
|
|
82
|
+
- **Knowledge 永続化**(`.alfred/knowledge/`)が compact、セッション再起動、モデル切替を確実に生き延びるデータ層
|
|
83
|
+
- **適応的注入** — 新プロジェクトにはフルコンテキスト、成熟プロジェクトには現タスクのみ。コンテキスト肥大化なし
|
|
84
|
+
|
|
59
85
|
## スキル
|
|
60
86
|
|
|
61
87
|
| スキル | ひとこと |
|
|
@@ -114,7 +140,7 @@ JSON ファイルとして Git にコミットし、PR でレビューし、チ
|
|
|
114
140
|
rules/ # 「常に X する。優先度: P0。根拠: Y」
|
|
115
141
|
```
|
|
116
142
|
|
|
117
|
-
|
|
143
|
+
15回以上検索ヒットしたパターンはルールに自動昇格。矛盾は自動検出。
|
|
118
144
|
|
|
119
145
|
検索パイプライン: Voyage AI ベクトル + リランキング > FTS5 ファジーマッチ > キーワードフォールバック。「auth」で「authentication」「login」「認証」もヒット。
|
|
120
146
|
|
package/README.md
CHANGED
|
@@ -56,6 +56,32 @@ Most spec tools give you slash commands that say "you should write a spec first.
|
|
|
56
56
|
|
|
57
57
|
**A dashboard that's actually useful.** `alfred dashboard` opens `localhost:7575` with live task progress, spec review with line-level comments, file-by-file approval, knowledge health, and activity timeline. English/Japanese toggle.
|
|
58
58
|
|
|
59
|
+
## Why alfred in 2026
|
|
60
|
+
|
|
61
|
+
Claude Code is powerful, but unstructured AI coding has well-documented failure modes:
|
|
62
|
+
|
|
63
|
+
- **~30% first-attempt success rate** — without spec grounding, Claude hallucinates completions, skips edge cases, and claims "done" when it isn't. alfred's 3-layer gate system (spec → review → approval) catches these before they reach your codebase.
|
|
64
|
+
- **Context loss across sessions** — even with 1M context (Opus 4.6), compaction eventually fires and wipes your working state. alfred persists decisions, patterns, and progress as structured JSON files that survive any compaction, any session boundary, any model swap.
|
|
65
|
+
- **Infinite refactoring loops** — without bounded iteration, Claude can spend hours rewriting the same code. alfred's wave-based implementation enforces commit → review → advance. Max 2 fix rounds per wave, then escalate.
|
|
66
|
+
- **Security blind spots** — 45% of AI-generated code contains vulnerabilities (per industry research). alfred spawns parallel code-review agents at every wave boundary, with security as a dedicated review perspective.
|
|
67
|
+
- **Spec-implementation drift** — specs go stale the moment coding starts. alfred's living spec auto-appends changed files to design.md on every commit. Your spec stays honest automatically.
|
|
68
|
+
|
|
69
|
+
### SDD meets IDD
|
|
70
|
+
|
|
71
|
+
The industry is converging on two complementary paradigms: **Spec-Driven Development** (structured specs as source of truth) and **Intent-Driven Development** (capture *why* and *what*, let AI handle *how*). alfred bridges both:
|
|
72
|
+
|
|
73
|
+
- **Full SDD** for M/L/XL features — requirements, design, tasks, tests, with traceability and review gates
|
|
74
|
+
- **Lightweight IDD** for S/D changes — just requirements + decisions, no design overhead
|
|
75
|
+
- **Immutable decisions** via `ledger save` — like ADRs, but semantically searchable across projects and sessions
|
|
76
|
+
|
|
77
|
+
### Built for 1M context
|
|
78
|
+
|
|
79
|
+
With Opus 4.6's 1M context window, compaction is rarer but more destructive when it hits. alfred is designed for this reality:
|
|
80
|
+
|
|
81
|
+
- **PreCompact hook** captures structured chapter memory (goal, decisions, summary) before context is lost
|
|
82
|
+
- **Knowledge persistence** (`.alfred/knowledge/`) is the only data that guaranteed survives compaction, session restarts, and model changes
|
|
83
|
+
- **Adaptive injection** — new projects get full context on session start; mature projects get just the current task. No context bloat.
|
|
84
|
+
|
|
59
85
|
## Skills
|
|
60
86
|
|
|
61
87
|
| Skill | One-liner |
|
|
@@ -114,7 +140,7 @@ Knowledge lives as JSON files you can commit, review in PRs, and share with your
|
|
|
114
140
|
rules/ # "Always do X. Priority: P0. Because: Y."
|
|
115
141
|
```
|
|
116
142
|
|
|
117
|
-
|
|
143
|
+
Patterns auto-promote to rules after 15+ search hits. Contradictions detected automatically.
|
|
118
144
|
|
|
119
145
|
Search pipeline: Voyage AI vectors with reranking > FTS5 with fuzzy matching > keyword fallback. "auth" finds "authentication", "login", and more.
|
|
120
146
|
|
package/content/hooks/hooks.json
CHANGED
|
@@ -58,11 +58,6 @@
|
|
|
58
58
|
"statusMessage": "alfred: checking spec approval...",
|
|
59
59
|
"timeout": 5,
|
|
60
60
|
"type": "command"
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"type": "prompt",
|
|
64
|
-
"prompt": "You are a spec-driven development gatekeeper. An Edit/Write tool is about to execute. The command handler already passed deterministic checks (review-gate, approval-gate).\n\nCheck the conversation context:\n1. If an active spec ALREADY EXISTS (dossier init was called, or spec context is visible in the conversation), respond {\"ok\": true} — the spec requirement is satisfied.\n2. If NO spec exists and this is a TRIVIAL change (typo fix, documentation update, config tweak, comment edit, style fix, renaming, version bump), respond {\"ok\": true} — no spec needed.\n3. If NO spec exists and this is SUBSTANTIAL work (new feature, bug fix requiring investigation, refactoring, architecture change), respond {\"ok\": false, \"reason\": \"This change requires a spec. Create one with: dossier action=init (use size=S for small changes, size=D for delta changes)\"}.\n\nWhen in doubt, allow it — false blocks are worse than missing specs.",
|
|
65
|
-
"timeout": 10
|
|
66
61
|
}
|
|
67
62
|
]
|
|
68
63
|
}
|
package/dist/cli.mjs
CHANGED
|
@@ -371,7 +371,7 @@ const main = defineCommand({
|
|
|
371
371
|
async run() {
|
|
372
372
|
const { Store } = await import("./store-BffM-bi-.mjs").then((n) => (n.t(), n.r));
|
|
373
373
|
const { Embedder } = await import("./embedder-D3hJoryD.mjs");
|
|
374
|
-
const { serveMCP } = await import("./server-
|
|
374
|
+
const { serveMCP } = await import("./server-D3b54XYU.mjs");
|
|
375
375
|
const store = Store.openDefault();
|
|
376
376
|
let emb = null;
|
|
377
377
|
try {
|
|
@@ -422,7 +422,7 @@ const main = defineCommand({
|
|
|
422
422
|
description: "Event name"
|
|
423
423
|
} },
|
|
424
424
|
async run({ args }) {
|
|
425
|
-
const { runHook } = await import("./dispatcher-
|
|
425
|
+
const { runHook } = await import("./dispatcher-BDl_Flyx.mjs").then((n) => (n.i(), n.t));
|
|
426
426
|
await runHook(args.event);
|
|
427
427
|
}
|
|
428
428
|
}),
|
|
@@ -3,7 +3,7 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
|
|
|
3
3
|
import { c as incrementHitCount, f as searchKnowledgeKeyword, i as getKnowledgeByIDs, l as init_knowledge } from "./knowledge-C7rEfFSX.mjs";
|
|
4
4
|
import { r as vectorSearchKnowledge, t as init_vectors } from "./vectors-DHZGQ096.mjs";
|
|
5
5
|
import { a as subTypeBoost, i as searchKnowledgeFTS, o as subTypeHalfLife, r as init_fts } from "./fts-DICqcpG_.mjs";
|
|
6
|
-
import { i as init_dispatcher, n as emitAdditionalContext } from "./dispatcher-
|
|
6
|
+
import { i as init_dispatcher, n as emitAdditionalContext } from "./dispatcher-BDl_Flyx.mjs";
|
|
7
7
|
//#region src/mcp/helpers.ts
|
|
8
8
|
function truncate(s, maxLen) {
|
|
9
9
|
const runes = [...s];
|
|
@@ -89,27 +89,27 @@ async function runHook(event) {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
async function handleSessionStart(ev, signal) {
|
|
92
|
-
const { sessionStart } = await import("./session-start-
|
|
92
|
+
const { sessionStart } = await import("./session-start-CU4-KivX.mjs");
|
|
93
93
|
await sessionStart(ev, signal);
|
|
94
94
|
}
|
|
95
95
|
async function handlePreCompact(ev, signal) {
|
|
96
|
-
const { preCompact } = await import("./pre-compact-
|
|
96
|
+
const { preCompact } = await import("./pre-compact-Cncx9q7L.mjs");
|
|
97
97
|
await preCompact(ev, signal);
|
|
98
98
|
}
|
|
99
99
|
async function handleUserPromptSubmit(ev, signal) {
|
|
100
|
-
const { userPromptSubmit } = await import("./user-prompt-
|
|
100
|
+
const { userPromptSubmit } = await import("./user-prompt-BPAOU8f-.mjs");
|
|
101
101
|
await userPromptSubmit(ev, signal);
|
|
102
102
|
}
|
|
103
103
|
async function handlePostToolUse(ev, signal) {
|
|
104
|
-
const { postToolUse } = await import("./post-tool-
|
|
104
|
+
const { postToolUse } = await import("./post-tool-BawR4gHR.mjs");
|
|
105
105
|
await postToolUse(ev, signal);
|
|
106
106
|
}
|
|
107
107
|
async function handlePreToolUse(ev, _signal) {
|
|
108
|
-
const { preToolUse } = await import("./pre-tool-
|
|
108
|
+
const { preToolUse } = await import("./pre-tool-Dyp4S8cV.mjs");
|
|
109
109
|
await preToolUse(ev);
|
|
110
110
|
}
|
|
111
111
|
async function handleStop(ev, _signal) {
|
|
112
|
-
const { stop } = await import("./stop-
|
|
112
|
+
const { stop } = await import("./stop-CGv96IQd.mjs");
|
|
113
113
|
await stop(ev);
|
|
114
114
|
}
|
|
115
115
|
var init_dispatcher = __esmMin((() => {}));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./types-K2jxpWyU.mjs";
|
|
3
3
|
import "./audit-e13xK9Fr.mjs";
|
|
4
|
-
import "./dispatcher-
|
|
5
|
-
import "./directives-
|
|
6
|
-
import { a as postToolUse, n as init_post_tool } from "./post-tool-
|
|
4
|
+
import "./dispatcher-BDl_Flyx.mjs";
|
|
5
|
+
import "./directives-DfzKzUAL.mjs";
|
|
6
|
+
import { a as postToolUse, n as init_post_tool } from "./post-tool-DpBkq5ik.mjs";
|
|
7
7
|
import "./store-BffM-bi-.mjs";
|
|
8
|
-
import "./review-gate-
|
|
9
|
-
import "./state-
|
|
8
|
+
import "./review-gate-7Pfe_A-8.mjs";
|
|
9
|
+
import "./state-Cih-8_Zc.mjs";
|
|
10
10
|
init_post_tool();
|
|
11
11
|
export { postToolUse };
|
|
@@ -5,11 +5,11 @@ import { n as init_audit, t as appendAudit } from "./audit-e13xK9Fr.mjs";
|
|
|
5
5
|
import { a as getKnowledgeStats, d as promoteSubType, l as init_knowledge, m as upsertKnowledge, o as getPromotionCandidates, r as getKnowledgeByID } from "./knowledge-C7rEfFSX.mjs";
|
|
6
6
|
import { i as searchKnowledgeFTS, r as init_fts, t as detectKnowledgeConflicts } from "./fts-DICqcpG_.mjs";
|
|
7
7
|
import { n as init_project, t as detectProject } from "./project-DCKke4_Q.mjs";
|
|
8
|
-
import { a as notifyUser, i as init_dispatcher } from "./dispatcher-
|
|
9
|
-
import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-
|
|
8
|
+
import { a as notifyUser, i as init_dispatcher } from "./dispatcher-BDl_Flyx.mjs";
|
|
9
|
+
import { a as trackHitCounts, i as searchPipeline, n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-DfzKzUAL.mjs";
|
|
10
10
|
import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
|
|
11
|
-
import { a as writeReviewGate, d as init_spec_guard, n as init_review_gate, p as isSpecFilePath } from "./review-gate-
|
|
12
|
-
import {
|
|
11
|
+
import { a as writeReviewGate, d as init_spec_guard, n as init_review_gate, p as isSpecFilePath } from "./review-gate-7Pfe_A-8.mjs";
|
|
12
|
+
import { f as writeStateText, i as parseWaveProgress, o as readStateText, p as writeWaveProgress, r as init_state, s as readWaveProgress, t as addWorkedSlug } from "./state-Cih-8_Zc.mjs";
|
|
13
13
|
import { mkdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
@@ -5,7 +5,7 @@ import { r as init_epic, s as syncTaskStatus } from "./epic-CfxJ13zy.mjs";
|
|
|
5
5
|
import { n as init_audit, t as appendAudit } from "./audit-e13xK9Fr.mjs";
|
|
6
6
|
import { l as init_knowledge, m as upsertKnowledge } from "./knowledge-C7rEfFSX.mjs";
|
|
7
7
|
import { n as init_project, t as detectProject } from "./project-DCKke4_Q.mjs";
|
|
8
|
-
import { a as notifyUser, i as init_dispatcher } from "./dispatcher-
|
|
8
|
+
import { a as notifyUser, i as init_dispatcher } from "./dispatcher-BDl_Flyx.mjs";
|
|
9
9
|
import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
|
|
10
10
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { join } from "node:path";
|
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
|
|
3
3
|
import { a as effectiveStatus, s as init_types } from "./types-K2jxpWyU.mjs";
|
|
4
|
-
import { d as init_spec_guard, f as isActiveSpecMalformed, l as denyTool, m as tryReadActiveSpec, n as init_review_gate, o as allowTool, p as isSpecFilePath, r as isGateActive } from "./review-gate-
|
|
5
|
-
import "./state-
|
|
4
|
+
import { d as init_spec_guard, f as isActiveSpecMalformed, l as denyTool, m as tryReadActiveSpec, n as init_review_gate, o as allowTool, p as isSpecFilePath, r as isGateActive } from "./review-gate-7Pfe_A-8.mjs";
|
|
5
|
+
import { a as readStateJSON, r as init_state } from "./state-Cih-8_Zc.mjs";
|
|
6
|
+
import { resolve } from "node:path";
|
|
6
7
|
//#region src/hooks/pre-tool.ts
|
|
7
8
|
/**
|
|
9
|
+
* Check if a file path is outside the project directory or in a known non-code
|
|
10
|
+
* location. These files should never be blocked by review/approval gates.
|
|
11
|
+
* (#16: gate scope was too broad, blocking memory/docs/CLAUDE.md edits)
|
|
12
|
+
*/
|
|
13
|
+
function isGateExemptPath(cwd, filePath) {
|
|
14
|
+
if (!cwd || !filePath) return false;
|
|
15
|
+
const resolved = resolve(cwd, filePath);
|
|
16
|
+
const cwdPrefix = cwd.endsWith("/") ? cwd : `${cwd}/`;
|
|
17
|
+
if (!resolved.startsWith(cwdPrefix) && resolved !== cwd) return true;
|
|
18
|
+
const rel = resolved.slice(cwdPrefix.length);
|
|
19
|
+
if (rel.startsWith("docs/")) return true;
|
|
20
|
+
if (!rel.includes("/") && rel.endsWith(".md")) return true;
|
|
21
|
+
if (rel.startsWith(".claude/")) return true;
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
8
25
|
* PreToolUse handler: block Edit/Write on review-gate or unapproved spec.
|
|
9
26
|
* Enforcement order: .alfred/ exempt → malformed check → review-gate → approval gate.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
27
|
+
* Uses allowTool() for: .alfred/ files, deferred/cancelled specs, and active specs with cleared gates.
|
|
28
|
+
* Only falls through to prompt hook (LLM judge) when NO active spec exists.
|
|
12
29
|
*/
|
|
13
30
|
async function preToolUse(ev) {
|
|
14
31
|
const toolName = ev.tool_name ?? "";
|
|
@@ -31,16 +48,34 @@ async function preToolUse(ev) {
|
|
|
31
48
|
return;
|
|
32
49
|
}
|
|
33
50
|
}
|
|
51
|
+
if (filePath && isGateExemptPath(ev.cwd, filePath)) {
|
|
52
|
+
allowTool("Gate-exempt path (non-code file)");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
34
55
|
const gate = isGateActive(ev.cwd);
|
|
35
56
|
if (gate) {
|
|
57
|
+
if (gate.fix_mode) {
|
|
58
|
+
allowTool(`Fix mode active for '${gate.slug}' — editing allowed, re-review required before clear`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
36
61
|
denyTool([
|
|
37
62
|
`${gate.gate === "wave-review" ? `Wave ${gate.wave ?? "?"} review` : "Spec self-review"} required for spec '${gate.slug}'. Complete review, then run: dossier action=gate sub_action=clear reason="<review summary>"`,
|
|
38
63
|
`- Gate reason: ${gate.reason}`,
|
|
39
|
-
"- \"I already reviewed mentally\" → Run actual review (3-agent or /alfred:inspect), then clear the gate"
|
|
64
|
+
"- \"I already reviewed mentally\" → Run actual review (3-agent or /alfred:inspect), then clear the gate",
|
|
65
|
+
`- Need to apply fixes first? Run: dossier action=gate sub_action=fix reason="fixing Critical findings"`
|
|
40
66
|
].join("\n"));
|
|
41
67
|
return;
|
|
42
68
|
}
|
|
43
|
-
if (!spec)
|
|
69
|
+
if (!spec) {
|
|
70
|
+
const polish = readStateJSON(ev.cwd, "polish.json", {});
|
|
71
|
+
if (polish.slug) {
|
|
72
|
+
allowTool(`Polish mode (post-complete '${polish.slug}')`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
process.stderr.write("[alfred] No active spec. Consider creating one: dossier action=init\n");
|
|
76
|
+
allowTool("No active spec (advisory warning emitted)");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
44
79
|
if ([
|
|
45
80
|
"M",
|
|
46
81
|
"L",
|
|
@@ -53,6 +88,7 @@ async function preToolUse(ev) {
|
|
|
53
88
|
].join("\n"));
|
|
54
89
|
return;
|
|
55
90
|
}
|
|
91
|
+
allowTool(`Active spec '${spec.slug}' (${spec.size}), gates clear`);
|
|
56
92
|
}
|
|
57
93
|
var BLOCKABLE_TOOLS;
|
|
58
94
|
//#endregion
|
|
@@ -60,6 +96,7 @@ __esmMin((() => {
|
|
|
60
96
|
init_types();
|
|
61
97
|
init_review_gate();
|
|
62
98
|
init_spec_guard();
|
|
99
|
+
init_state();
|
|
63
100
|
BLOCKABLE_TOOLS = new Set(["Edit", "Write"]);
|
|
64
101
|
}))();
|
|
65
102
|
export { preToolUse };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
|
|
3
3
|
import { l as readActiveState, s as init_types } from "./types-K2jxpWyU.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { a as readStateJSON, d as writeStateJSON, r as init_state } from "./state-Cih-8_Zc.mjs";
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
6
|
import { join, resolve } from "node:path";
|
|
7
7
|
//#region src/hooks/spec-guard.ts
|
|
@@ -6,13 +6,13 @@ import { n as init_audit, t as appendAudit } from "./audit-e13xK9Fr.mjs";
|
|
|
6
6
|
import { i as getKnowledgeByIDs, l as init_knowledge } from "./knowledge-C7rEfFSX.mjs";
|
|
7
7
|
import { r as vectorSearchKnowledge, t as init_vectors } from "./vectors-DHZGQ096.mjs";
|
|
8
8
|
import { a as subTypeBoost, i as searchKnowledgeFTS, r as init_fts } from "./fts-DICqcpG_.mjs";
|
|
9
|
-
import "./dispatcher-
|
|
10
|
-
import { o as truncate, r as init_helpers } from "./directives-
|
|
11
|
-
import { c as updateTaskStatus, l as handleLedger, n as init_post_tool, o as post_tool_exports, s as init_status, u as init_ledger } from "./post-tool-
|
|
9
|
+
import "./dispatcher-BDl_Flyx.mjs";
|
|
10
|
+
import { o as truncate, r as init_helpers } from "./directives-DfzKzUAL.mjs";
|
|
11
|
+
import { c as updateTaskStatus, l as handleLedger, n as init_post_tool, o as post_tool_exports, s as init_status, u as init_ledger } from "./post-tool-DpBkq5ik.mjs";
|
|
12
12
|
import "./store-BffM-bi-.mjs";
|
|
13
|
-
import { a as writeReviewGate, i as readReviewGate, n as init_review_gate, t as clearReviewGate } from "./review-gate-
|
|
14
|
-
import { d as
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { a as writeReviewGate, i as readReviewGate, n as init_review_gate, t as clearReviewGate } from "./review-gate-7Pfe_A-8.mjs";
|
|
14
|
+
import { d as writeStateJSON, n as ensureStateDir, p as writeWaveProgress, r as init_state, s as readWaveProgress, u as stateDir } from "./state-Cih-8_Zc.mjs";
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { join, resolve } from "node:path";
|
|
17
17
|
import process$1 from "node:process";
|
|
18
18
|
//#region node_modules/zod/v3/helpers/util.js
|
|
@@ -18808,46 +18808,46 @@ function dossierValidate(projectPath, params) {
|
|
|
18808
18808
|
}
|
|
18809
18809
|
//#endregion
|
|
18810
18810
|
//#region src/spec/templates/en/requirements.tmpl
|
|
18811
|
-
var requirements_default$1 = "# Requirements: {{taskSlug}}\n\n> {{description}}\n\n## Goal\n\n<!--
|
|
18811
|
+
var requirements_default$1 = "# Requirements: {{taskSlug}}\n\n> {{description}}\n\n## Goal\n\n<!-- 1-2 sentences. What this change achieves. -->\n\n## User Stories\n\n<!-- US-N: As a user, I want to... -->\n\n## Functional Requirements\n\n<!--\nUse EARS notation (keywords stay in English — parser validates WHEN/SHALL):\n- Ubiquitous: The system SHALL {response}.\n- Event-Driven: WHEN {trigger}, the system SHALL {response}.\n- State-Driven: WHILE {state}, the system SHALL {response}.\n- Optional: WHERE {feature}, the system SHALL {response}.\n- Unwanted: IF {condition}, THEN the system SHALL {response}.\n\nEach FR MUST include confidence + source annotation:\n <!-- confidence: N | source: user/code/inference/assumption | grounding: verified/reviewed/inferred/speculative -->\n-->\n\n### FR-1: [Requirement Title]\n\n<!-- confidence: 5 | source: inference | grounding: inferred -->\n\n## Acceptance Criteria\n\n<!--\nAt least 1 per FR. These become the basis for test specs. Vague ACs produce vague tests.\n-->\n\nAC-1.1: Given [specific precondition], When [specific action], Then [verifiable outcome]\n\n## Error Scenarios\n\n<!-- AI implements happy-path only by default.\n Errors NOT listed here will NOT be handled. -->\n\n| Scenario | Input/State | Expected Handling |\n|----------|------------|-------------------|\n| | | |\n\n## Non-Functional Requirements\n\n<!-- NFR-N: Include measurable targets.\n Examples: \"within 3 seconds\" \"below 5%\" \"up to 1000 entries\"\n Include measurement method: \"average\" \"p95\" \"over 60 seconds\" -->\n\n## Security Requirements\n\n<!-- Keep only applicable items:\n- [ ] Input validation (SQL injection, XSS, path traversal)\n- [ ] Authentication / authorization checks\n- [ ] Data sensitivity (PII, API keys)\n- [ ] Dependency vulnerability check\n- [ ] Not applicable (reason: )\n-->\n\n## Out of Scope\n\n<!-- If implementor starts building out-of-scope features, refer here to stop.\n Explicit \"won't build\" prevents AI scope creep. -->\n\n-\n";
|
|
18812
18812
|
//#endregion
|
|
18813
18813
|
//#region src/spec/templates/en/bugfix.tmpl
|
|
18814
|
-
var bugfix_default$1 = "# Bugfix: {{taskSlug}}\n\n> {{description}}\n\n## Bug Summary\n\n## Severity & Impact\n\n
|
|
18814
|
+
var bugfix_default$1 = "# Bugfix: {{taskSlug}}\n\n> {{description}}\n\n## Bug Summary\n\n<!-- 1-2 sentences. What happens vs. what should happen. -->\n\n## Severity & Impact\n\n| Field | Value |\n|-------|-------|\n| Severity | P0 (service down) / P1 (major feature broken) / P2 (workaround exists) / P3 (minor) |\n| Impact | |\n| Frequency | Always / under specific conditions / rare |\n| Workaround | Yes (describe) / None |\n\n## Reproduction Steps\n\n1.\n2.\n3.\n\n## Root Cause Analysis\n\n### 5 Whys\n\n1. Why? →\n2. Why? →\n3. Why? →\n4. Why? →\n5. Why (root cause)? →\n\n### Code Trace\n\n<!-- Exact paths and line numbers so implementor can locate the cause immediately. -->\n\n- **Symptom location**: `src/path/to/file.ts:line` — what happens\n- **Root cause location**: `src/path/to/file.ts:line` — why it happens\n- **Data flow**: input → processing → point of failure\n\n## Fix Strategy\n\n- **Target file**: `src/path/to/file.ts` — concrete change description\n- **Rejected alternatives**: other approaches and why dismissed\n- **Side-effect risk**: potential impact on other functionality\n\n## Unchanged Behavior\n\n<!-- What MUST NOT break. Implementor checks these BEFORE applying fix. -->\n\n- [ ] All existing tests pass\n- [ ]\n\n## Regression Prevention Test\n\n<!-- Test to detect recurrence. Also add to test-specs.md.\n Test MUST describe external-observable behavior only (no internal implementation references). -->\n\n```gherkin\nScenario: [Bug does not recur]\n Given [precondition that triggered the bug]\n When [action that caused the bug]\n Then [correct behavior]\n```\n";
|
|
18815
18815
|
//#endregion
|
|
18816
18816
|
//#region src/spec/templates/en/delta.tmpl
|
|
18817
|
-
var delta_default$1 = "# Delta: {{taskSlug}}\n\n> {{description}}\n\n## Change Summary\n\n## Files Affected\n\n### CHG-1: [Change description]\n\n- File
|
|
18817
|
+
var delta_default$1 = "# Delta: {{taskSlug}}\n\n> {{description}}\n\n## Change Summary\n\n<!-- 1-2 sentences. What changes and why. -->\n\n## Files Affected\n\n### CHG-1: [Change description]\n\n- File: `src/path/to/file.ts`\n- Before: [current code or behavior]\n- After: [changed code or behavior]\n\n## Rationale\n\n<!-- Why this change is necessary. If alternatives exist, list them with rejection reasons.\n Important decisions MUST be persisted via `ledger save sub_type=decision`. -->\n\n## Impact Scope\n\n<!-- What else this change affects. If nothing, explicitly state \"no impact\". -->\n\n- **API compatibility**: Changed / Unchanged\n- **UI**: Changed / Unchanged\n- **Tests**: Modification needed / Not needed\n- **Performance**: Impacted / Not impacted\n\n## Unchanged Behavior\n\n<!-- What MUST NOT break. -->\n\n- [ ] All existing tests pass\n- [ ]\n\n## Test Plan\n\n<!-- How to verify the change is correct. Concrete commands or steps. -->\n\n## Rollback Strategy\n\n<!-- Recovery steps if problems occur. Is `git revert` sufficient, or is data migration needed? -->\n";
|
|
18818
18818
|
//#endregion
|
|
18819
18819
|
//#region src/spec/templates/en/design.tmpl
|
|
18820
|
-
var design_default$1 = "# Design: {{taskSlug}}\n\n##
|
|
18820
|
+
var design_default$1 = "# Design: {{taskSlug}}\n\n## Architecture Overview\n\n<!-- ASCII diagram showing component structure and data flow.\n Implementor MUST create/modify files according to this diagram. -->\n\n## Component Design\n\n<!-- For each component: write Why and What. Minimize How — implementor decides. -->\n\n### [Component Name] (`src/path/to/file.ts`)\n\n- **Responsibility**: One sentence.\n- **Interface**:\n```typescript\n// Public function signatures and types. Implementor MUST follow this contract.\n```\n- **Dependencies**: Existing modules used\n- **Error handling**: Errors this component throws/returns\n\n## Data Models\n\n<!-- New/changed tables, type definitions. Write both SQL DDL and TypeScript types.\n Implementor uses these definitions directly in code. -->\n\n## API Contracts\n\n<!-- New/changed endpoints.\n Implementor MUST follow this contract exactly. No ad-hoc field additions. -->\n\n| Method | Path | Request | Response | Error |\n|--------|------|---------|----------|-------|\n| | | | | |\n\n## Error Scenarios\n\n<!-- List errors that CAN happen and HOW to handle them.\n AI tends to implement happy-path only. Errors not listed here will NOT be handled. -->\n\n| Scenario | Input/State | Expected Handling | HTTP/Exit |\n|----------|------------|-------------------|-----------|\n| | | | |\n\n## Boundary Conditions\n\n<!-- Typical edge cases AI misses. Implementation MUST cover these. -->\n\n- [ ] Empty input (null, undefined, \"\", [], {})\n- [ ] Maximum values (MAX_INT, very long strings, 1000+ records)\n- [ ] Concurrent access (simultaneous writes, race conditions)\n- [ ] Unicode / CJK / special characters\n- [ ] Unauthorized / expired auth\n- [ ] Network error / timeout\n- [ ] Remove non-applicable items\n\n## Design Decisions\n\n<!-- Important decisions MUST be persisted via `ledger save sub_type=decision`. -->\n\n| Decision | Choice | Rationale | Alternatives |\n|----------|--------|-----------|--------------|\n| | | | |\n\n## Non-Goals\n\n<!-- Align with Out of Scope in requirements.md.\n If implementor starts building out-of-scope features, refer here to stop. -->\n\n-\n\n## Traceability Matrix\n\n<!-- Every FR must map to component → task → test. No orphans allowed. -->\n\n| Req ID | Component | Task ID | Test ID |\n|--------|-----------|---------|---------|\n| FR-1 | | T-1.1 | TS-1.1 |\n";
|
|
18821
18821
|
//#endregion
|
|
18822
18822
|
//#region src/spec/templates/en/tasks.tmpl
|
|
18823
|
-
var tasks_default$1 = "# Tasks: {{taskSlug}}\n\n## Wave 1:
|
|
18823
|
+
var tasks_default$1 = "# Tasks: {{taskSlug}}\n\n## Summary\n\n<!--\n- Total: N tasks across M waves (+ Closing Wave)\n- Size: NS, NM, NL\n- Parallel-safe: T-X.Y / T-X.Z (tasks in same wave that can run in parallel)\n-->\n\n## Wave 1: [Wave Name]\n\n<!-- Order waves by build sequence: Foundation → Core → Integration → Polish -->\n\n- [ ] T-1.1 [S/M/L] [Task Title]\n _Requirements: FR-1 | Depends: — | Files: src/path/to/file.ts_\n - [Implementation detail 1]\n - [Implementation detail 2]\n - Verify: [Done condition — tests pass, curl check, etc.]\n\n<!--\nTask definition rules:\n- Each task MUST have Requirements (linked FR), Depends (dependency), Files (targets)\n- Verify must be a concrete command: \"task test passes\" \"curl localhost:7575/api/X returns 200\" etc.\n- S: ~30min, 1 file | M: ~1-2h, multi-file | L: ~2-4h, complex logic\n- (P) suffix marks parallel-safe tasks\n\nTask decomposition principles:\n- 1 task = 1 responsibility. \"Create A, wire B, test C\" = 3 separate tasks\n- Max 3-4 changed files per task. Split if more\n- DB schema changes and logic using them = separate tasks (migration first)\n- Tests go WITH the implementation task (not separate). Verify confirms tests pass\n- If frontend and backend are independent, make them parallel tasks (P)\n\nBad examples:\n T-1.1 [L] Build API + DB + frontend all at once → too large, unreviewable\n T-1.1 [S] Write code / T-1.2 [S] Write tests → tests belong with implementation\n\nGood examples:\n T-1.1 [M] DB schema + migration + tests\n T-1.2 [M] API endpoint + tests (Depends: T-1.1)\n T-1.3 [M] (P) Frontend UI (Depends: T-1.2 types only)\n-->\n\n### T-1.R: Wave 1 Review\n- [ ] Commit changes (include wave number in message)\n- [ ] Self-review (delegate to `alfred:code-reviewer` agent, run in foreground)\n- [ ] Critical/High → `dossier gate fix` → apply fixes → re-review → confirm 0 findings\n- [ ] Save learnings to knowledge (`ledger save`)\n- [ ] `dossier gate clear reason=\"Wave 1 review: [summary]\"`\n\n## Wave: Closing\n\n- [ ] T-C.1 Final self-review from multiple perspectives\n- [ ] T-C.2 Update CLAUDE.md / README if needed\n- [ ] T-C.3 Verify tests pass (`task test`)\n- [ ] T-C.4 Save key learnings to knowledge via `ledger save`\n\n## Dependency Graph\n\n```\nT-1.1 ──→ T-1.2\n```\n\nWhen all items checked → `dossier action=complete` to close the spec.\n";
|
|
18824
18824
|
//#endregion
|
|
18825
18825
|
//#region src/spec/templates/en/test-specs.tmpl
|
|
18826
|
-
var test_specs_default$1 = "# Test Specs: {{taskSlug}}\n\n## TS-1.1: [Test Title]\n
|
|
18826
|
+
var test_specs_default$1 = "# Test Specs: {{taskSlug}}\n\n## Coverage Matrix\n\n<!-- Every FR must have a test. An FR without a test is a coverage gap. -->\n\n| Req ID | Test IDs | Type | Priority | Status |\n|--------|----------|------|----------|--------|\n| FR-1 | TS-1.1 | unit | P0 | planned |\n\n## Test Cases\n\n<!--\nGherkin format. Each test MUST have source annotation:\n <!-- source: FR-N -->\n\nEARS → Gherkin mapping:\n WHILE → Given / WHEN → When / SHALL → Then\n\nDescribe ONLY external-observable behavior:\n ✓ \"Given no users are registered\"\n ✗ \"Given the UserService has an empty userRepository\"\nDo NOT reference internal implementation (class names, DB tables, framework terms) in tests.\n-->\n\n### TS-1.1: [Test Title]\n<!-- source: FR-1 -->\n\n```gherkin\nScenario: [Scenario name]\n Given [precondition]\n When [action]\n Then [expected result]\n```\n\n## Error Path Tests\n\n<!-- AI tends to test happy-path only.\n Every error scenario from design.md MUST have a test. -->\n\n### TS-E.1: [Error Scenario Name]\n<!-- source: FR-N, Error Scenario -->\n\n```gherkin\nScenario: [Behavior on error]\n Given [precondition that causes error]\n When [action that triggers error]\n Then [expected error handling]\n```\n\n## Edge Case Matrix\n\n<!-- Corresponds to boundary condition checklist in design.md. -->\n\n| Scenario | Input | Expected | Req |\n|----------|-------|----------|-----|\n| Empty input | | | |\n| Max values | | | |\n| Concurrent | | | |\n\n## Test Data\n\n<!-- Mock strategy:\n - External APIs → mock (Voyage, git subprocess, etc.)\n - DB → real DB (tmpdir test DB, follow existing patterns)\n - Filesystem → tmpdir (mkdtempSync pattern)\n-->\n\n## Unchanged Behavior\n\n<!-- Existing tests/behavior that MUST NOT break.\n `task test` all passing is the minimum bar. -->\n\n- [ ] All existing tests pass\n- [ ]\n";
|
|
18827
18827
|
//#endregion
|
|
18828
18828
|
//#region src/spec/templates/en/research.tmpl
|
|
18829
|
-
var research_default$1 = "# Research: {{taskSlug}}\n\n##
|
|
18829
|
+
var research_default$1 = "# Research: {{taskSlug}}\n\n## Existing Code Analysis\n\n<!-- List files that MUST be read before implementation. Exact paths and line numbers.\n Patterns found here MUST be reused during implementation. -->\n\n| File | Line | What's There | Reusable? |\n|------|------|-------------|-----------|\n| | | | |\n\n## Patterns to Follow\n\n<!-- Patterns already established in this codebase.\n Implementation MUST follow these. Do NOT invent new patterns. -->\n\n- **Naming**:\n- **Error handling**:\n- **Testing**:\n- **Type definitions**:\n\n## Gap Analysis\n\n| Current State | Required | Gap | Target File | Difficulty |\n|---------------|----------|-----|-------------|-----------|\n| | | | | S/M/L |\n\n## Implementation Options\n\n### Option A: [Recommended]\n\n- **Concrete changes**: which file, which function, how\n- **Pros**:\n- **Cons**:\n- **Risk**:\n\n### Option B: [Alternative]\n\n- **Concrete changes**:\n- **Pros**:\n- **Cons**:\n- **Rejection reason**:\n\n## Dependency Verification\n\n<!-- Verify all libraries/APIs actually exist. AI hallucinates versions and APIs.\n Confirm via grep/Read, not assumption. -->\n\n| Dependency | Verification Method | Confirmed |\n|-----------|-------------------|-----------|\n| | | ✓ / ✗ |\n\n## Risks & Unknowns\n\n<!-- confidence: N | source: code/inference/assumption -->\n\n1.\n2.\n\n## Done Criteria\n\n- [ ] All relevant code read, paths and line numbers recorded\n- [ ] Reusable patterns identified\n- [ ] Dependency existence confirmed (no hallucinations)\n- [ ] At least 2 options compared, recommendation selected\n";
|
|
18830
18830
|
//#endregion
|
|
18831
18831
|
//#region src/spec/templates/ja/requirements.tmpl
|
|
18832
|
-
var requirements_default = "# 要件定義: {{taskSlug}}\n\n> {{description}}\n\n## ゴール\n\n<!--
|
|
18832
|
+
var requirements_default = "# 要件定義: {{taskSlug}}\n\n> {{description}}\n\n## ゴール\n\n<!-- 1-2 文。この変更で何が達成されるか。 -->\n\n## ユーザーストーリー\n\n<!-- US-N: ユーザーとして、〜したい -->\n\n## 機能要件\n\n<!--\nEARS 記法で記述(キーワードは英語のまま — パーサーが WHEN/SHALL を検証するため):\n- Ubiquitous: The system SHALL {response}.\n- Event-Driven: WHEN {trigger}, the system SHALL {response}.\n- State-Driven: WHILE {state}, the system SHALL {response}.\n- Optional: WHERE {feature}, the system SHALL {response}.\n- Unwanted: IF {condition}, THEN the system SHALL {response}.\n\n各 FR に confidence + source アノテーション必須:\n <!-- confidence: N | source: user/code/inference/assumption | grounding: verified/reviewed/inferred/speculative -->\n-->\n\n### FR-1: [要件タイトル]\n\n<!-- confidence: 5 | source: inference | grounding: inferred -->\n\n## 受入条件\n\n<!--\n各 FR に最低 1 つ。これがテスト仕様の元になる。曖昧な AC は曖昧なテストを生む。\n-->\n\nAC-1.1: Given [具体的な前提条件], When [具体的な操作], Then [検証可能な結果]\n\n## エラーシナリオ\n\n<!-- AI は正常系しか実装しない傾向がある。\n ここに書かないエラーは処理されない。 -->\n\n| シナリオ | 入力/状態 | 期待する処理 |\n|----------|----------|-------------|\n| | | |\n\n## 非機能要件\n\n<!-- NFR-N: 測定可能な目標値を含めること。\n 例: \"3秒以内\" \"5%以下\" \"1000件以下\"\n 測定方法も書く: \"平均\" \"p95\" \"60秒間\" -->\n\n## セキュリティ要件\n\n<!-- 該当する項目のみ残す:\n- [ ] 入力バリデーション(SQL injection, XSS, path traversal)\n- [ ] 認証/認可チェック\n- [ ] データの機密性(個人情報、API キー)\n- [ ] 依存パッケージの脆弱性確認\n- [ ] 該当なし(理由: )\n-->\n\n## スコープ外\n\n<!-- 実装者がスコープ外の機能を作り始めたらここを参照して止める。\n 「作らないもの」を明示することで AI のスコープ逸脱を防止。 -->\n\n-\n";
|
|
18833
18833
|
//#endregion
|
|
18834
18834
|
//#region src/spec/templates/ja/bugfix.tmpl
|
|
18835
|
-
var bugfix_default = "# バグ修正: {{taskSlug}}\n\n> {{description}}\n\n## バグ概要\n\n## 重要度と影響範囲\n\n
|
|
18835
|
+
var bugfix_default = "# バグ修正: {{taskSlug}}\n\n> {{description}}\n\n## バグ概要\n\n<!-- 1-2 文。何が起きるか vs 何が正しい動作か。 -->\n\n## 重要度と影響範囲\n\n| 項目 | 内容 |\n|------|------|\n| 重要度 | P0 (サービス停止) / P1 (主要機能障害) / P2 (回避策あり) / P3 (軽微) |\n| 影響範囲 | |\n| 頻度 | 常に / 特定条件下 / 稀 |\n| 回避策 | あり (内容) / なし |\n\n## 再現手順\n\n1.\n2.\n3.\n\n## 原因分析\n\n### 5 Whys\n\n1. なぜ?→\n2. なぜ?→\n3. なぜ?→\n4. なぜ?→\n5. なぜ(根本原因)?→\n\n### コードトレース\n\n<!-- 実装者が原因箇所を即座に特定できるよう、正確なパスと行番号を書く。 -->\n\n- **発症箇所**: `src/path/to/file.ts:line` — 何が起きるか\n- **原因箇所**: `src/path/to/file.ts:line` — なぜ起きるか\n- **データフロー**: 入力 → 処理 → 問題が生じるポイント\n\n## 修正方針\n\n- **変更対象**: `src/path/to/file.ts` — 具体的にどう変えるか\n- **選択しなかった方法**: 代替案と却下理由\n- **副作用リスク**: 修正が他に影響する可能性\n\n## 変更不可の動作\n\n<!-- 修正で壊してはいけないもの。実装者はここを確認してから修正すること。 -->\n\n- [ ] 既存テスト全件パス\n- [ ]\n\n## リグレッション防止テスト\n\n<!-- このバグの再発を検知するテスト。test-specs.md にも追加すること。\n テストは外部観測可能な振る舞いのみ(内部実装を参照しない)。 -->\n\n```gherkin\nScenario: [バグの再発防止]\n Given [バグ発生の前提条件]\n When [バグを引き起こす操作]\n Then [正常な動作]\n```\n";
|
|
18836
18836
|
//#endregion
|
|
18837
18837
|
//#region src/spec/templates/ja/delta.tmpl
|
|
18838
|
-
var delta_default = "# 差分変更: {{taskSlug}}\n\n> {{description}}\n\n## 変更概要\n\n## 影響ファイル\n\n### CHG-1: [変更内容]\n\n- File
|
|
18838
|
+
var delta_default = "# 差分変更: {{taskSlug}}\n\n> {{description}}\n\n## 変更概要\n\n<!-- 1-2 文。何を変えるか、なぜ変えるか。 -->\n\n## 影響ファイル\n\n### CHG-1: [変更内容]\n\n- File: `src/path/to/file.ts`\n- Before: [現在のコードまたは動作]\n- After: [変更後のコードまたは動作]\n\n## 変更理由\n\n<!-- なぜこの変更が必要か。代替案があれば記載し却下理由も書く。\n 重要な判断は `ledger save sub_type=decision` で永続化。 -->\n\n## 影響範囲\n\n<!-- この変更が影響する他の機能/コンポーネント。\n 影響なしの場合も「影響なし」と明記する。 -->\n\n- **API 互換性**: 変更あり / なし\n- **UI**: 変更あり / なし\n- **テスト**: 修正必要 / 不要\n- **パフォーマンス**: 影響あり / なし\n\n## 変更不可の動作\n\n<!-- この変更で壊してはいけないもの。 -->\n\n- [ ] 既存テスト全件パス\n- [ ]\n\n## テスト計画\n\n<!-- 変更の正しさをどう確認するか。具体的なコマンドまたは手順。 -->\n\n## ロールバック手順\n\n<!-- 問題が起きた場合の復旧手順。`git revert` で十分か、データ migration が必要か。 -->\n";
|
|
18839
18839
|
//#endregion
|
|
18840
18840
|
//#region src/spec/templates/ja/design.tmpl
|
|
18841
|
-
var design_default = "# 設計: {{taskSlug}}\n\n##
|
|
18841
|
+
var design_default = "# 設計: {{taskSlug}}\n\n## アーキテクチャ概要\n\n<!-- ASCII ダイアグラムでコンポーネント構成とデータフローを示す。\n 実装者はこの図に従ってファイルを作成/変更すること。 -->\n\n## コンポーネント設計\n\n<!-- 各コンポーネントに以下を記載。Why と What を書く。How は最小限 — 実装者が判断する。 -->\n\n### [コンポーネント名] (`src/path/to/file.ts`)\n\n- **責務**: 1文で。\n- **インターフェース**:\n```typescript\n// 公開する関数シグネチャと型を書く。実装者はこの契約に従う。\n```\n- **依存**: 使用する既存モジュール\n- **エラー処理**: このコンポーネントが throw/return するエラー\n\n## データモデル\n\n<!-- 新規/変更テーブル、型定義。SQL DDL + TypeScript 型を両方書く。\n 実装者はここの定義をそのままコードに使う。 -->\n\n## API 契約\n\n<!-- 新規/変更エンドポイント。\n 実装者はこの契約に正確に従うこと。勝手なフィールド追加禁止。 -->\n\n| Method | Path | Request | Response | Error |\n|--------|------|---------|----------|-------|\n| | | | | |\n\n## エラーシナリオ\n\n<!-- 正常系だけでなく、発生しうるエラーとその処理方法を列挙する。\n AI は happy-path のみ実装する傾向がある。ここで明示しないエラーは処理されない。 -->\n\n| シナリオ | 入力/状態 | 期待する処理 | HTTP/Exit |\n|----------|----------|-------------|-----------|\n| | | | |\n\n## 境界条件\n\n<!-- AI が見落とす典型的なエッジケース。実装時に必ずカバーすること。 -->\n\n- [ ] 空入力 (null, undefined, \"\", [], {})\n- [ ] 最大値 (MAX_INT, 長大文字列, 1000+ レコード)\n- [ ] 並行アクセス (同時書き込み, レース条件)\n- [ ] Unicode / 日本語 / 特殊文字\n- [ ] 権限なし / 認証切れ\n- [ ] ネットワークエラー / タイムアウト\n- [ ] 該当なし項目は削除すること\n\n## 設計判断\n\n<!-- 重要な判断は `ledger save sub_type=decision` で永続化すること。 -->\n\n| 判断 | 選択 | 理由 | 代替案 |\n|------|------|------|--------|\n| | | | |\n\n## やらないこと\n\n<!-- requirements.md の Out of Scope と整合。\n 実装者がスコープ外の機能を作り始めたらここを参照して止める。 -->\n\n-\n\n## トレーサビリティマトリクス\n\n<!-- 全 FR がコンポーネント → タスク → テストに紐づくこと。孤立禁止。 -->\n\n| Req ID | Component | Task ID | Test ID |\n|--------|-----------|---------|---------|\n| FR-1 | | T-1.1 | TS-1.1 |\n";
|
|
18842
18842
|
//#endregion
|
|
18843
18843
|
//#region src/spec/templates/ja/tasks.tmpl
|
|
18844
|
-
var tasks_default = "# タスク: {{taskSlug}}\n\n## Wave 1:
|
|
18844
|
+
var tasks_default = "# タスク: {{taskSlug}}\n\n## サマリー\n\n<!--\n- Total: N tasks across M waves (+ Closing Wave)\n- Size: NS, NM, NL\n- Parallel-safe: T-X.Y / T-X.Z (同 Wave 内で並列実行可能なタスク)\n-->\n\n## Wave 1: [Wave 名]\n\n<!-- Wave はビルド順に並べる: Foundation → Core → Integration → Polish -->\n\n- [ ] T-1.1 [S/M/L] [タスクタイトル]\n _Requirements: FR-1 | Depends: — | Files: src/path/to/file.ts_\n - [実装内容 1]\n - [実装内容 2]\n - Verify: [完了条件 — テスト通過、動作確認等]\n\n<!--\nタスク定義ルール:\n- 各タスクに Requirements (紐づく FR), Depends (依存タスク), Files (変更対象) を書く\n- Verify は具体的なコマンド: \"task test パス\" \"curl localhost:7575/api/X で 200\" 等\n- S: ~30min, 1 ファイル | M: ~1-2h, 複数ファイル | L: ~2-4h, 複雑なロジック\n- (P) をタイトルに付けると並列実行可能マーク\n\nタスク分割の原則:\n- 1 タスク = 1 責務。「A を作って B に繋いで C をテスト」は 3 タスクに分ける\n- 1 タスクの変更ファイルは最大 3-4 個。超えたら分割する\n- DB スキーマ変更と、それを使うロジックは別タスクにする(migration を先に)\n- テストは実装タスクに含める(別タスクにしない)。Verify でテスト通過を確認\n- フロントエンドとバックエンドが独立なら並列タスク (P) にする\n\n悪い例:\n T-1.1 [L] API + DB + フロント全部やる → 大きすぎ、レビュー不能\n T-1.1 [S] コード書く / T-1.2 [S] テスト書く → テストは実装と一緒にやる\n\n良い例:\n T-1.1 [M] DB スキーマ + migration + テスト\n T-1.2 [M] API エンドポイント + テスト (Depends: T-1.1)\n T-1.3 [M] (P) フロントエンド UI (Depends: T-1.2 の型のみ)\n-->\n\n### T-1.R: Wave 1 レビュー\n- [ ] 変更をコミット(Wave 番号をメッセージに含める)\n- [ ] セルフレビュー(`alfred:code-reviewer` エージェントに委譲。foreground で実行)\n- [ ] Critical/High → `dossier gate fix` → 修正 → 再レビュー → 0 件確認\n- [ ] 学びをナレッジに保存(`ledger save`)\n- [ ] `dossier gate clear reason=\"Wave 1 review: [summary]\"`\n\n## Wave: Closing\n\n- [ ] T-C.1 最終セルフレビュー(多角的に)\n- [ ] T-C.2 必要に応じて CLAUDE.md / README を更新\n- [ ] T-C.3 テスト通過を確認(`task test`)\n- [ ] T-C.4 重要な学びをナレッジに保存(`ledger save`)\n\n## 依存関係グラフ\n\n```\nT-1.1 ──→ T-1.2\n```\n\n全項目チェック後 → `dossier action=complete` でスペックをクローズ。\n";
|
|
18845
18845
|
//#endregion
|
|
18846
18846
|
//#region src/spec/templates/ja/test-specs.tmpl
|
|
18847
|
-
var test_specs_default = "# テスト仕様: {{taskSlug}}\n\n## TS-1.1:
|
|
18847
|
+
var test_specs_default = "# テスト仕様: {{taskSlug}}\n\n## カバレッジマトリクス\n\n<!-- 全 FR にテストが紐づくこと。紐づかない FR はテスト漏れ。 -->\n\n| Req ID | Test IDs | Type | Priority | Status |\n|--------|----------|------|----------|--------|\n| FR-1 | TS-1.1 | unit | P0 | planned |\n\n## テストケース\n\n<!--\nGherkin 形式。各テストに source アノテーション必須:\n <!-- source: FR-N -->\n\nEARS → Gherkin マッピング:\n WHILE → Given / WHEN → When / SHALL → Then\n\n外部観測可能な振る舞いのみ記述すること:\n ✓ \"Given ユーザーが登録されていない\"\n ✗ \"Given UserService の userRepository が空\"\n内部実装(クラス名、DB テーブル名、フレームワーク用語)をテストに書かない。\n-->\n\n### TS-1.1: [テストタイトル]\n<!-- source: FR-1 -->\n\n```gherkin\nScenario: [シナリオ名]\n Given [前提条件]\n When [操作]\n Then [期待結果]\n```\n\n## エラーパステスト\n\n<!-- AI は happy-path しかテストしない傾向がある。\n design.md のエラーシナリオを全てテストすること。 -->\n\n### TS-E.1: [エラーシナリオ名]\n<!-- source: FR-N, Error Scenario -->\n\n```gherkin\nScenario: [エラー発生時の振る舞い]\n Given [エラーが起きる前提条件]\n When [エラーを引き起こす操作]\n Then [エラー処理の期待結果]\n```\n\n## エッジケースマトリクス\n\n<!-- design.md の境界条件チェックリストに対応するテスト。 -->\n\n| シナリオ | 入力 | 期待結果 | Req |\n|----------|------|----------|-----|\n| 空入力 | | | |\n| 最大値 | | | |\n| 並行 | | | |\n\n## テストデータ\n\n<!-- モック戦略:\n - 外部 API → モック(Voyage, git subprocess 等)\n - DB → 実 DB(tmpdir でテスト用 DB 作成、既存パターンに従う)\n - ファイルシステム → tmpdir(mkdtempSync パターン)\n-->\n\n## 変更不可の動作\n\n<!-- 今回の変更で壊してはいけない既存テスト/動作を列挙。\n `task test` 全件パスは最低条件。 -->\n\n- [ ] 既存テスト全件パス\n- [ ]\n";
|
|
18848
18848
|
//#endregion
|
|
18849
18849
|
//#region src/spec/templates/ja/research.tmpl
|
|
18850
|
-
var research_default = "# リサーチ: {{taskSlug}}\n\n##
|
|
18850
|
+
var research_default = "# リサーチ: {{taskSlug}}\n\n## 既存コード分析\n\n<!-- 実装前に必ず読むべきファイルをリストする。パスと行番号は正確に。\n ここで挙げたパターンを実装時に再利用すること。 -->\n\n| ファイル | 行 | 何があるか | 再利用可能か |\n|----------|-----|-----------|-------------|\n| | | | |\n\n## 従うべき既存パターン\n\n<!-- このプロジェクトで既に使われているパターンを列挙。\n 実装時はこれらに従うこと。独自パターンの導入は禁止。 -->\n\n- **命名**:\n- **エラー処理**:\n- **テスト**:\n- **型定義**:\n\n## ギャップ分析\n\n| 現状 | 必要 | ギャップ | 対象ファイル | 難易度 |\n|------|------|---------|-------------|--------|\n| | | | | S/M/L |\n\n## 実装オプション\n\n### Option A: [推奨]\n\n- **具体的な変更**: どのファイルのどの関数をどう変えるか\n- **メリット**:\n- **デメリット**:\n- **リスク**:\n\n### Option B: [代替案]\n\n- **具体的な変更**:\n- **メリット**:\n- **デメリット**:\n- **却下理由**:\n\n## 依存関係の確認\n\n<!-- 使用するライブラリ/API が実際に存在するか検証済みか。\n AI はバージョンやAPIを幻覚する。grep/Read で確認すること。 -->\n\n| 依存 | 確認方法 | 存在確認 |\n|------|---------|---------|\n| | | ✓ / ✗ |\n\n## リスク & 未知数\n\n<!-- confidence: N | source: code/inference/assumption -->\n\n1.\n2.\n\n## 完了基準\n\n- [ ] 関連コードをすべて読み、パスと行番号を記録した\n- [ ] 再利用すべきパターンを特定した\n- [ ] 依存関係の存在を確認した(幻覚なし)\n- [ ] 最低 2 オプションを比較し推奨を選定した\n";
|
|
18851
18851
|
//#endregion
|
|
18852
18852
|
//#region src/spec/templates.ts
|
|
18853
18853
|
init_types();
|
|
@@ -18970,6 +18970,9 @@ async function dossierInit(projectPath, store, emb, params) {
|
|
|
18970
18970
|
detail: params.description,
|
|
18971
18971
|
user: "mcp"
|
|
18972
18972
|
});
|
|
18973
|
+
try {
|
|
18974
|
+
unlinkSync(join(stateDir(projectPath), "polish.json"));
|
|
18975
|
+
} catch {}
|
|
18973
18976
|
const result = {
|
|
18974
18977
|
task_slug: params.task_slug,
|
|
18975
18978
|
spec_dir: initResult.specDir.dir(),
|
|
@@ -19046,10 +19049,18 @@ async function searchRelatedKnowledge(store, emb, description, limit) {
|
|
|
19046
19049
|
//#region src/mcp/dossier/lifecycle.ts
|
|
19047
19050
|
init_epic();
|
|
19048
19051
|
init_review_gate();
|
|
19052
|
+
init_state();
|
|
19049
19053
|
init_audit();
|
|
19050
19054
|
init_status();
|
|
19051
19055
|
init_types();
|
|
19052
19056
|
init_helpers();
|
|
19057
|
+
function ensurePolishState(projectPath, slug) {
|
|
19058
|
+
ensureStateDir(projectPath);
|
|
19059
|
+
writeStateJSON(projectPath, "polish.json", {
|
|
19060
|
+
slug,
|
|
19061
|
+
completed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
19062
|
+
});
|
|
19063
|
+
}
|
|
19053
19064
|
function dossierComplete(projectPath, store, params) {
|
|
19054
19065
|
let taskSlug = params.task_slug;
|
|
19055
19066
|
if (!taskSlug) try {
|
|
@@ -19098,6 +19109,9 @@ function dossierComplete(projectPath, store, params) {
|
|
|
19098
19109
|
detail: `${currentStatus} → done (dossier:complete)`
|
|
19099
19110
|
});
|
|
19100
19111
|
syncTaskStatus(projectPath, taskSlug, "done");
|
|
19112
|
+
try {
|
|
19113
|
+
ensurePolishState(projectPath, taskSlug);
|
|
19114
|
+
} catch {}
|
|
19101
19115
|
const result = {
|
|
19102
19116
|
task_slug: taskSlug,
|
|
19103
19117
|
completed: true,
|
|
@@ -19189,12 +19203,41 @@ function dossierGate(projectPath, params) {
|
|
|
19189
19203
|
reason
|
|
19190
19204
|
});
|
|
19191
19205
|
}
|
|
19206
|
+
case "fix": {
|
|
19207
|
+
const gate = readReviewGate(projectPath);
|
|
19208
|
+
if (!gate) return jsonResult$1({
|
|
19209
|
+
fix_mode: false,
|
|
19210
|
+
reason: "no active review gate"
|
|
19211
|
+
});
|
|
19212
|
+
if (gate.fix_mode) return jsonResult$1({
|
|
19213
|
+
fix_mode: true,
|
|
19214
|
+
reason: "already in fix mode"
|
|
19215
|
+
});
|
|
19216
|
+
const fixReason = params.reason ? truncate(params.reason, 500) : "Applying review fixes";
|
|
19217
|
+
writeReviewGate(projectPath, {
|
|
19218
|
+
...gate,
|
|
19219
|
+
fix_mode: true,
|
|
19220
|
+
reason: `[fix_mode] ${fixReason} (original: ${gate.reason})`
|
|
19221
|
+
});
|
|
19222
|
+
appendAudit(projectPath, {
|
|
19223
|
+
action: "gate.fix",
|
|
19224
|
+
target: gate.slug,
|
|
19225
|
+
detail: fixReason,
|
|
19226
|
+
user: "mcp"
|
|
19227
|
+
});
|
|
19228
|
+
return jsonResult$1({
|
|
19229
|
+
fix_mode: true,
|
|
19230
|
+
slug: gate.slug,
|
|
19231
|
+
reason: fixReason,
|
|
19232
|
+
hint: "Edit/Write now allowed. After fixes, re-run review then `dossier gate clear reason=\"re-review: 0 Critical\"` to fully clear."
|
|
19233
|
+
});
|
|
19234
|
+
}
|
|
19192
19235
|
case "status": {
|
|
19193
19236
|
const gate = readReviewGate(projectPath);
|
|
19194
19237
|
if (!gate) return jsonResult$1({ gate: null });
|
|
19195
19238
|
return jsonResult$1(gate);
|
|
19196
19239
|
}
|
|
19197
|
-
default: return errorResult$1(`unknown gate sub_action: ${subAction} (valid: set/clear/status)`);
|
|
19240
|
+
default: return errorResult$1(`unknown gate sub_action: ${subAction} (valid: set/clear/fix/status)`);
|
|
19198
19241
|
}
|
|
19199
19242
|
}
|
|
19200
19243
|
function dossierCheck(projectPath, params) {
|
|
@@ -19604,6 +19647,7 @@ Size-based scaling: init accepts size (S/M/L/XL) and spec_type (feature/bugfix).
|
|
|
19604
19647
|
sub_action: enumType([
|
|
19605
19648
|
"set",
|
|
19606
19649
|
"clear",
|
|
19650
|
+
"fix",
|
|
19607
19651
|
"status"
|
|
19608
19652
|
]).optional().describe("Gate sub-action (for gate action)"),
|
|
19609
19653
|
gate_type: enumType(["spec-review", "wave-review"]).optional().describe("Gate type (for gate set)"),
|
|
@@ -19656,7 +19700,7 @@ Actions:
|
|
|
19656
19700
|
]).describe("Action to perform"),
|
|
19657
19701
|
id: numberType().optional().describe("Record ID (required for promote)"),
|
|
19658
19702
|
query: stringType().optional().describe("Search query"),
|
|
19659
|
-
label: stringType().optional().describe("Short label for saved entry"),
|
|
19703
|
+
label: stringType().optional().describe("Short label for saved entry (REQUIRED for save)"),
|
|
19660
19704
|
limit: numberType().optional().describe("Maximum search results (default: 10)"),
|
|
19661
19705
|
detail: enumType([
|
|
19662
19706
|
"compact",
|
|
@@ -19667,22 +19711,22 @@ Actions:
|
|
|
19667
19711
|
"decision",
|
|
19668
19712
|
"pattern",
|
|
19669
19713
|
"rule"
|
|
19670
|
-
]).optional().describe("Knowledge type (
|
|
19671
|
-
title: stringType().optional().describe("Entry title"),
|
|
19672
|
-
decision: stringType().optional().describe("Decision: what was decided"),
|
|
19673
|
-
reasoning: stringType().optional().describe("Decision: why this choice"),
|
|
19714
|
+
]).optional().describe("Knowledge type (REQUIRED for save)"),
|
|
19715
|
+
title: stringType().optional().describe("Entry title (REQUIRED for save)"),
|
|
19716
|
+
decision: stringType().optional().describe("Decision: what was decided (REQUIRED for decision)"),
|
|
19717
|
+
reasoning: stringType().optional().describe("Decision: why this choice (REQUIRED for decision)"),
|
|
19674
19718
|
alternatives: stringType().optional().describe("Decision: newline-separated rejected alternatives with reasons"),
|
|
19675
19719
|
context_text: stringType().optional().describe("Decision/Pattern: context or background"),
|
|
19676
19720
|
pattern_type: enumType([
|
|
19677
19721
|
"good",
|
|
19678
19722
|
"bad",
|
|
19679
19723
|
"error-solution"
|
|
19680
|
-
]).optional().describe("Pattern: type"),
|
|
19681
|
-
pattern: stringType().optional().describe("Pattern: concrete steps"),
|
|
19724
|
+
]).optional().describe("Pattern: type (REQUIRED for pattern)"),
|
|
19725
|
+
pattern: stringType().optional().describe("Pattern: concrete steps (REQUIRED for pattern)"),
|
|
19682
19726
|
application_conditions: stringType().optional().describe("Pattern: when to apply"),
|
|
19683
19727
|
expected_outcomes: stringType().optional().describe("Pattern: expected results"),
|
|
19684
|
-
key: stringType().optional().describe("Rule: machine-readable key"),
|
|
19685
|
-
text: stringType().optional().describe("Rule: imperative text"),
|
|
19728
|
+
key: stringType().optional().describe("Rule: machine-readable key (REQUIRED for rule)"),
|
|
19729
|
+
text: stringType().optional().describe("Rule: imperative text (REQUIRED for rule)"),
|
|
19686
19730
|
category: stringType().optional().describe("Rule: category"),
|
|
19687
19731
|
priority: enumType([
|
|
19688
19732
|
"p0",
|
|
@@ -3,10 +3,10 @@ import { n as __esmMin } from "./chunk-CAm0Jl7e.mjs";
|
|
|
3
3
|
import { c as readActive, l as readActiveState, s as init_types, t as SpecDir } from "./types-K2jxpWyU.mjs";
|
|
4
4
|
import { l as init_knowledge, m as upsertKnowledge, n as deleteOrphanKnowledge, s as getRecentDecisions, t as countKnowledge } from "./knowledge-C7rEfFSX.mjs";
|
|
5
5
|
import { n as init_project, t as detectProject } from "./project-DCKke4_Q.mjs";
|
|
6
|
-
import { a as notifyUser, i as init_dispatcher, r as extractSection } from "./dispatcher-
|
|
7
|
-
import { n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-
|
|
6
|
+
import { a as notifyUser, i as init_dispatcher, r as extractSection } from "./dispatcher-BDl_Flyx.mjs";
|
|
7
|
+
import { n as init_directives, o as truncate, r as init_helpers, t as emitDirectives } from "./directives-DfzKzUAL.mjs";
|
|
8
8
|
import { n as openDefaultCached, t as init_store } from "./store-BffM-bi-.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { l as resetWorkedSlugs, r as init_state } from "./state-Cih-8_Zc.mjs";
|
|
10
10
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
//#region src/hooks/session-start.ts
|
|
@@ -128,4 +128,4 @@ var init_state = __esmMin((() => {
|
|
|
128
128
|
WAVE_PROGRESS_FILE = "wave-progress.json";
|
|
129
129
|
}));
|
|
130
130
|
//#endregion
|
|
131
|
-
export {
|
|
131
|
+
export { readStateJSON as a, readWorkedSlugs as c, writeStateJSON as d, writeStateText as f, parseWaveProgress as i, resetWorkedSlugs as l, ensureStateDir as n, readStateText as o, writeWaveProgress as p, init_state as r, readWaveProgress as s, addWorkedSlug as t, stateDir as u };
|