@wazir-dev/cli 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -2
- package/README.md +6 -6
- package/docs/concepts/architecture.md +1 -1
- package/docs/concepts/roles-and-workflows.md +2 -0
- package/docs/concepts/why-wazir.md +59 -0
- package/docs/decisions/2026-03-19-deferred-items.md +564 -0
- package/docs/decisions/2026-03-19-enhancement-decisions.md +300 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +1 -1
- package/docs/readmes/INDEX.md +21 -5
- package/docs/readmes/features/expertise/README.md +2 -2
- package/docs/readmes/features/exports/README.md +2 -2
- package/docs/readmes/features/schemas/README.md +3 -0
- package/docs/readmes/features/skills/README.md +17 -0
- package/docs/readmes/features/skills/clarifier.md +5 -0
- package/docs/readmes/features/skills/claude-cli.md +5 -0
- package/docs/readmes/features/skills/codex-cli.md +5 -0
- package/docs/readmes/features/skills/dispatching-parallel-agents.md +5 -0
- package/docs/readmes/features/skills/executing-plans.md +5 -0
- package/docs/readmes/features/skills/executor.md +5 -0
- package/docs/readmes/features/skills/finishing-a-development-branch.md +5 -0
- package/docs/readmes/features/skills/gemini-cli.md +5 -0
- package/docs/readmes/features/skills/humanize.md +5 -0
- package/docs/readmes/features/skills/init-pipeline.md +5 -0
- package/docs/readmes/features/skills/receiving-code-review.md +5 -0
- package/docs/readmes/features/skills/requesting-code-review.md +5 -0
- package/docs/readmes/features/skills/reviewer.md +5 -0
- package/docs/readmes/features/skills/subagent-driven-development.md +5 -0
- package/docs/readmes/features/skills/using-git-worktrees.md +5 -0
- package/docs/readmes/features/skills/wazir.md +5 -0
- package/docs/readmes/features/skills/writing-skills.md +5 -0
- package/docs/readmes/features/workflows/prepare-next.md +1 -1
- package/docs/reference/configuration-reference.md +47 -6
- package/docs/reference/launch-checklist.md +4 -4
- package/docs/reference/review-loop-pattern.md +538 -0
- package/docs/reference/roles-reference.md +1 -0
- package/docs/reference/skill-tiers.md +147 -0
- package/docs/reference/tooling-cli.md +5 -1
- package/docs/truth-claims.yaml +18 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +97 -1
- package/exports/hosts/claude/.claude/agents/clarifier.md +3 -0
- package/exports/hosts/claude/.claude/agents/designer.md +3 -0
- package/exports/hosts/claude/.claude/agents/executor.md +2 -0
- package/exports/hosts/claude/.claude/agents/planner.md +3 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +2 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +5 -1
- package/exports/hosts/claude/.claude/agents/specifier.md +3 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +4 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +4 -0
- package/exports/hosts/claude/.claude/commands/design.md +4 -0
- package/exports/hosts/claude/.claude/commands/discover.md +4 -0
- package/exports/hosts/claude/.claude/commands/execute.md +4 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +4 -0
- package/exports/hosts/claude/.claude/commands/plan.md +4 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +4 -0
- package/exports/hosts/claude/.claude/commands/specify.md +4 -0
- package/exports/hosts/claude/.claude/commands/verify.md +4 -0
- package/exports/hosts/claude/.claude/settings.json +9 -0
- package/exports/hosts/claude/CLAUDE.md +1 -1
- package/exports/hosts/claude/export.manifest.json +22 -20
- package/exports/hosts/claude/host-package.json +3 -1
- package/exports/hosts/codex/AGENTS.md +1 -1
- package/exports/hosts/codex/export.manifest.json +22 -20
- package/exports/hosts/codex/host-package.json +3 -1
- package/exports/hosts/cursor/.cursor/hooks.json +4 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +1 -1
- package/exports/hosts/cursor/export.manifest.json +22 -20
- package/exports/hosts/cursor/host-package.json +3 -1
- package/exports/hosts/gemini/GEMINI.md +1 -1
- package/exports/hosts/gemini/export.manifest.json +22 -20
- package/exports/hosts/gemini/host-package.json +3 -1
- package/hooks/context-mode-router +191 -0
- package/hooks/definitions/context_mode_router.yaml +19 -0
- package/hooks/definitions/loop_cap_guard.yaml +1 -1
- package/hooks/hooks.json +43 -0
- package/hooks/protected-path-write-guard +8 -0
- package/hooks/routing-matrix.json +45 -0
- package/hooks/session-start +62 -1
- package/llms-full.txt +905 -132
- package/package.json +3 -3
- package/roles/clarifier.md +3 -0
- package/roles/designer.md +3 -0
- package/roles/executor.md +2 -0
- package/roles/planner.md +3 -0
- package/roles/researcher.md +2 -0
- package/roles/reviewer.md +5 -1
- package/roles/specifier.md +3 -0
- package/schemas/hook.schema.json +2 -1
- package/schemas/phase-report.schema.json +80 -0
- package/schemas/usage.schema.json +25 -1
- package/schemas/wazir-manifest.schema.json +19 -0
- package/skills/brainstorming/SKILL.md +20 -56
- package/skills/clarifier/SKILL.md +243 -0
- package/skills/claude-cli/SKILL.md +320 -0
- package/skills/codex-cli/SKILL.md +260 -0
- package/skills/debugging/SKILL.md +24 -1
- package/skills/design/SKILL.md +13 -0
- package/skills/dispatching-parallel-agents/SKILL.md +13 -0
- package/skills/executing-plans/SKILL.md +28 -2
- package/skills/executor/SKILL.md +129 -0
- package/skills/finishing-a-development-branch/SKILL.md +13 -0
- package/skills/gemini-cli/SKILL.md +260 -0
- package/skills/humanize/SKILL.md +13 -0
- package/skills/init-pipeline/SKILL.md +76 -78
- package/skills/prepare-next/SKILL.md +81 -10
- package/skills/receiving-code-review/SKILL.md +21 -0
- package/skills/requesting-code-review/SKILL.md +38 -5
- package/skills/reviewer/SKILL.md +423 -0
- package/skills/run-audit/SKILL.md +13 -0
- package/skills/scan-project/SKILL.md +13 -0
- package/skills/self-audit/SKILL.md +197 -16
- package/skills/subagent-driven-development/SKILL.md +38 -2
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +2 -0
- package/skills/subagent-driven-development/implementer-prompt.md +8 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +7 -0
- package/skills/tdd/SKILL.md +21 -0
- package/skills/using-git-worktrees/SKILL.md +13 -0
- package/skills/using-skills/SKILL.md +13 -0
- package/skills/verification/SKILL.md +13 -0
- package/skills/wazir/SKILL.md +286 -262
- package/skills/writing-plans/SKILL.md +44 -4
- package/skills/writing-skills/SKILL.md +13 -0
- package/templates/artifacts/implementation-plan.md +3 -0
- package/templates/artifacts/tasks-template.md +133 -0
- package/templates/examples/phase-report.example.json +48 -0
- package/templates/examples/wazir-manifest.example.yaml +1 -1
- package/tooling/src/adapters/composition-engine.js +256 -0
- package/tooling/src/adapters/model-router.js +84 -0
- package/tooling/src/capture/command.js +111 -2
- package/tooling/src/capture/run-config.js +23 -0
- package/tooling/src/capture/store.js +24 -0
- package/tooling/src/capture/usage.js +106 -0
- package/tooling/src/checks/ac-matrix.js +256 -0
- package/tooling/src/checks/brand-truth.js +3 -6
- package/tooling/src/checks/command-registry.js +13 -0
- package/tooling/src/checks/docs-truth.js +1 -1
- package/tooling/src/checks/runtime-surface.js +3 -7
- package/tooling/src/checks/skills.js +111 -0
- package/tooling/src/cli.js +17 -3
- package/tooling/src/commands/stats.js +161 -0
- package/tooling/src/commands/validate.js +5 -1
- package/tooling/src/export/compiler.js +33 -37
- package/tooling/src/gating/agent.js +145 -0
- package/tooling/src/guards/phase-prerequisite-guard.js +127 -0
- package/tooling/src/hooks/routing-logic.js +69 -0
- package/tooling/src/init/auto-detect.js +260 -0
- package/tooling/src/init/command.js +161 -0
- package/tooling/src/input/scanner.js +46 -0
- package/tooling/src/reports/command.js +103 -0
- package/tooling/src/reports/phase-report.js +323 -0
- package/tooling/src/state/command.js +160 -0
- package/tooling/src/state/db.js +287 -0
- package/tooling/src/status/command.js +53 -1
- package/wazir.manifest.yaml +26 -17
- package/workflows/clarify.md +4 -0
- package/workflows/design-review.md +4 -0
- package/workflows/design.md +4 -0
- package/workflows/discover.md +4 -0
- package/workflows/execute.md +4 -0
- package/workflows/plan-review.md +4 -0
- package/workflows/plan.md +4 -0
- package/workflows/spec-challenge.md +4 -0
- package/workflows/specify.md +4 -0
- package/workflows/verify.md +4 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
5
|
+
|
|
6
|
+
function getStateDatabasePath(stateRoot) {
|
|
7
|
+
return path.join(stateRoot, 'state', 'state.sqlite');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function hashDescription(description) {
|
|
11
|
+
return crypto.createHash('sha256').update(description).digest('hex');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function ensureStateSchema(db) {
|
|
15
|
+
db.exec(`
|
|
16
|
+
CREATE TABLE IF NOT EXISTS learnings (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
source_run TEXT NOT NULL,
|
|
19
|
+
category TEXT NOT NULL,
|
|
20
|
+
scope_roles TEXT DEFAULT '',
|
|
21
|
+
scope_stacks TEXT DEFAULT '',
|
|
22
|
+
scope_concerns TEXT DEFAULT '',
|
|
23
|
+
confidence TEXT DEFAULT 'medium' CHECK(confidence IN ('low','medium','high')),
|
|
24
|
+
recurrence_count INTEGER DEFAULT 1,
|
|
25
|
+
content TEXT NOT NULL,
|
|
26
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
27
|
+
last_applied TEXT,
|
|
28
|
+
expires_at TEXT
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS findings (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
run_id TEXT NOT NULL,
|
|
34
|
+
phase TEXT NOT NULL,
|
|
35
|
+
source TEXT NOT NULL CHECK(source IN ('internal','codex','self-audit','gemini')),
|
|
36
|
+
severity TEXT NOT NULL CHECK(severity IN ('critical','high','medium','low')),
|
|
37
|
+
description TEXT NOT NULL,
|
|
38
|
+
resolved INTEGER DEFAULT 0,
|
|
39
|
+
finding_hash TEXT NOT NULL,
|
|
40
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
CREATE TABLE IF NOT EXISTS audit_history (
|
|
44
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
+
run_id TEXT NOT NULL,
|
|
46
|
+
date TEXT NOT NULL DEFAULT (date('now')),
|
|
47
|
+
finding_count INTEGER DEFAULT 0,
|
|
48
|
+
fix_count INTEGER DEFAULT 0,
|
|
49
|
+
manual_count INTEGER DEFAULT 0,
|
|
50
|
+
quality_score_before REAL,
|
|
51
|
+
quality_score_after REAL
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
CREATE TABLE IF NOT EXISTS usage_aggregate (
|
|
55
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
56
|
+
run_id TEXT NOT NULL,
|
|
57
|
+
date TEXT NOT NULL DEFAULT (date('now')),
|
|
58
|
+
tokens_saved INTEGER DEFAULT 0,
|
|
59
|
+
bytes_avoided INTEGER DEFAULT 0,
|
|
60
|
+
savings_ratio REAL DEFAULT 0.0,
|
|
61
|
+
index_queries INTEGER DEFAULT 0,
|
|
62
|
+
routing_decisions INTEGER DEFAULT 0
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_category ON learnings(category);
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_findings_run_id ON findings(run_id);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_findings_finding_hash ON findings(finding_hash);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_audit_history_run_id ON audit_history(run_id);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_usage_aggregate_run_id ON usage_aggregate(run_id);
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Database lifecycle
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
export function openStateDb(stateRoot) {
|
|
78
|
+
const databasePath = getStateDatabasePath(stateRoot);
|
|
79
|
+
fs.mkdirSync(path.dirname(databasePath), { recursive: true });
|
|
80
|
+
const db = new DatabaseSync(databasePath, { timeout: 5000 });
|
|
81
|
+
ensureStateSchema(db);
|
|
82
|
+
return db;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function closeStateDb(db) {
|
|
86
|
+
db.close();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Learnings CRUD
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
export function insertLearning(db, record) {
|
|
94
|
+
const id = crypto.randomUUID();
|
|
95
|
+
const createdAt = new Date().toISOString();
|
|
96
|
+
|
|
97
|
+
db.prepare(`
|
|
98
|
+
INSERT INTO learnings (id, source_run, category, scope_roles, scope_stacks, scope_concerns, confidence, content, created_at)
|
|
99
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
100
|
+
`).run(
|
|
101
|
+
id,
|
|
102
|
+
record.source_run,
|
|
103
|
+
record.category,
|
|
104
|
+
record.scope_roles ?? '',
|
|
105
|
+
record.scope_stacks ?? '',
|
|
106
|
+
record.scope_concerns ?? '',
|
|
107
|
+
record.confidence ?? 'medium',
|
|
108
|
+
record.content,
|
|
109
|
+
createdAt,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
return id;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function getLearningsByScope(db, filters = {}) {
|
|
116
|
+
const conditions = [];
|
|
117
|
+
const params = [];
|
|
118
|
+
|
|
119
|
+
if (filters.roles) {
|
|
120
|
+
conditions.push("scope_roles LIKE ?");
|
|
121
|
+
params.push(`%${filters.roles}%`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (filters.stacks) {
|
|
125
|
+
conditions.push("scope_stacks LIKE ?");
|
|
126
|
+
params.push(`%${filters.stacks}%`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (filters.concerns) {
|
|
130
|
+
conditions.push("scope_concerns LIKE ?");
|
|
131
|
+
params.push(`%${filters.concerns}%`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (filters.confidence) {
|
|
135
|
+
conditions.push("confidence = ?");
|
|
136
|
+
params.push(filters.confidence);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
140
|
+
const limit = filters.limit ? `LIMIT ${Number(filters.limit)}` : '';
|
|
141
|
+
|
|
142
|
+
return db.prepare(`
|
|
143
|
+
SELECT * FROM learnings ${where} ORDER BY created_at DESC ${limit}
|
|
144
|
+
`).all(...params);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function updateLearningRecurrence(db, id) {
|
|
148
|
+
const now = new Date().toISOString();
|
|
149
|
+
|
|
150
|
+
db.prepare(`
|
|
151
|
+
UPDATE learnings
|
|
152
|
+
SET recurrence_count = recurrence_count + 1,
|
|
153
|
+
last_applied = ?
|
|
154
|
+
WHERE id = ?
|
|
155
|
+
`).run(now, id);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function getRecurringLearnings(db, minCount) {
|
|
159
|
+
return db.prepare(`
|
|
160
|
+
SELECT * FROM learnings
|
|
161
|
+
WHERE recurrence_count >= ?
|
|
162
|
+
ORDER BY recurrence_count DESC
|
|
163
|
+
`).all(minCount);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Findings CRUD
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
export function insertFinding(db, record) {
|
|
171
|
+
const id = crypto.randomUUID();
|
|
172
|
+
const findingHash = record.finding_hash ?? hashDescription(record.description);
|
|
173
|
+
const createdAt = new Date().toISOString();
|
|
174
|
+
|
|
175
|
+
db.prepare(`
|
|
176
|
+
INSERT INTO findings (id, run_id, phase, source, severity, description, finding_hash, created_at)
|
|
177
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
178
|
+
`).run(
|
|
179
|
+
id,
|
|
180
|
+
record.run_id,
|
|
181
|
+
record.phase,
|
|
182
|
+
record.source,
|
|
183
|
+
record.severity,
|
|
184
|
+
record.description,
|
|
185
|
+
findingHash,
|
|
186
|
+
createdAt,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
return id;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function getFindingsByRun(db, runId) {
|
|
193
|
+
return db.prepare(`
|
|
194
|
+
SELECT * FROM findings
|
|
195
|
+
WHERE run_id = ?
|
|
196
|
+
ORDER BY created_at ASC
|
|
197
|
+
`).all(runId);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function getRecurringFindingHashes(db, minOccurrences) {
|
|
201
|
+
return db.prepare(`
|
|
202
|
+
SELECT finding_hash, COUNT(*) AS count
|
|
203
|
+
FROM findings
|
|
204
|
+
GROUP BY finding_hash
|
|
205
|
+
HAVING COUNT(*) >= ?
|
|
206
|
+
ORDER BY count DESC
|
|
207
|
+
`).all(minOccurrences);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function resolveFinding(db, id) {
|
|
211
|
+
db.prepare(`
|
|
212
|
+
UPDATE findings SET resolved = 1 WHERE id = ?
|
|
213
|
+
`).run(id);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
// Audit history
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
export function insertAuditRecord(db, record) {
|
|
221
|
+
db.prepare(`
|
|
222
|
+
INSERT INTO audit_history (run_id, finding_count, fix_count, manual_count, quality_score_before, quality_score_after)
|
|
223
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
224
|
+
`).run(
|
|
225
|
+
record.run_id,
|
|
226
|
+
record.finding_count ?? 0,
|
|
227
|
+
record.fix_count ?? 0,
|
|
228
|
+
record.manual_count ?? 0,
|
|
229
|
+
record.quality_score_before ?? null,
|
|
230
|
+
record.quality_score_after ?? null,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function getAuditTrend(db, limit) {
|
|
235
|
+
const limitClause = limit ? `LIMIT ${Number(limit)}` : '';
|
|
236
|
+
|
|
237
|
+
return db.prepare(`
|
|
238
|
+
SELECT * FROM audit_history
|
|
239
|
+
ORDER BY date DESC, id DESC
|
|
240
|
+
${limitClause}
|
|
241
|
+
`).all();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
// Usage
|
|
246
|
+
// ---------------------------------------------------------------------------
|
|
247
|
+
|
|
248
|
+
export function insertUsageRecord(db, record) {
|
|
249
|
+
db.prepare(`
|
|
250
|
+
INSERT INTO usage_aggregate (run_id, tokens_saved, bytes_avoided, savings_ratio, index_queries, routing_decisions)
|
|
251
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
252
|
+
`).run(
|
|
253
|
+
record.run_id,
|
|
254
|
+
record.tokens_saved ?? 0,
|
|
255
|
+
record.bytes_avoided ?? 0,
|
|
256
|
+
record.savings_ratio ?? 0.0,
|
|
257
|
+
record.index_queries ?? 0,
|
|
258
|
+
record.routing_decisions ?? 0,
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function getUsageSummary(db) {
|
|
263
|
+
const row = db.prepare(`
|
|
264
|
+
SELECT
|
|
265
|
+
COALESCE(SUM(tokens_saved), 0) AS total_tokens_saved,
|
|
266
|
+
COALESCE(SUM(bytes_avoided), 0) AS total_bytes_avoided,
|
|
267
|
+
CASE WHEN COUNT(*) > 0 THEN AVG(savings_ratio) ELSE 0.0 END AS avg_savings_ratio,
|
|
268
|
+
COALESCE(SUM(index_queries), 0) AS total_index_queries,
|
|
269
|
+
COUNT(*) AS run_count
|
|
270
|
+
FROM usage_aggregate
|
|
271
|
+
`).get();
|
|
272
|
+
|
|
273
|
+
return row;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Stats (for CLI)
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
export function getStateCounts(db) {
|
|
281
|
+
return {
|
|
282
|
+
learning_count: db.prepare('SELECT COUNT(*) AS count FROM learnings').get().count,
|
|
283
|
+
finding_count: db.prepare('SELECT COUNT(*) AS count FROM findings').get().count,
|
|
284
|
+
audit_count: db.prepare('SELECT COUNT(*) AS count FROM audit_history').get().count,
|
|
285
|
+
usage_count: db.prepare('SELECT COUNT(*) AS count FROM usage_aggregate').get().count,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
@@ -5,6 +5,46 @@ import { parseCommandOptions } from '../command-options.js';
|
|
|
5
5
|
import { readYamlFile } from '../loaders.js';
|
|
6
6
|
import { findProjectRoot } from '../project-root.js';
|
|
7
7
|
import { resolveStateRoot } from '../state-root.js';
|
|
8
|
+
import { estimateTokens } from '../capture/usage.js';
|
|
9
|
+
|
|
10
|
+
function readUsageSavingsSummary(stateRoot, runId) {
|
|
11
|
+
const usagePath = path.join(stateRoot, 'runs', runId, 'usage.json');
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(usagePath)) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const usage = JSON.parse(fs.readFileSync(usagePath, 'utf8'));
|
|
19
|
+
const cr = usage.savings?.capture_routing ?? {};
|
|
20
|
+
const cm = usage.savings?.context_mode ?? {};
|
|
21
|
+
const co = usage.savings?.compaction ?? {};
|
|
22
|
+
const iq = usage.savings?.index_queries ?? {};
|
|
23
|
+
|
|
24
|
+
const crTokensSaved = cr.estimated_tokens_avoided ?? 0;
|
|
25
|
+
const cmRawTokens = estimateTokens(Math.round((cm.raw_kb ?? 0) * 1024));
|
|
26
|
+
const cmAfterTokens = estimateTokens(Math.round((cm.context_kb ?? 0) * 1024));
|
|
27
|
+
const cmTokensSaved = cmRawTokens - cmAfterTokens;
|
|
28
|
+
const coTokensSaved = (co.pre_compaction_tokens_est ?? 0) - (co.post_compaction_tokens_est ?? 0);
|
|
29
|
+
const iqTokensSaved = iq.estimated_tokens_saved ?? 0;
|
|
30
|
+
|
|
31
|
+
const totalSaved = crTokensSaved + cmTokensSaved + coTokensSaved + iqTokensSaved;
|
|
32
|
+
|
|
33
|
+
if (totalSaved === 0) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const crRawTokens = crTokensSaved + estimateTokens(cr.summary_bytes ?? 0);
|
|
38
|
+
const withoutSavings = crRawTokens + cmRawTokens + (co.pre_compaction_tokens_est ?? 0);
|
|
39
|
+
const pct = withoutSavings > 0
|
|
40
|
+
? `${((totalSaved / withoutSavings) * 100).toFixed(0)}%`
|
|
41
|
+
: '0%';
|
|
42
|
+
|
|
43
|
+
return `Context savings: ~${totalSaved.toLocaleString('en-US')} tokens saved (${pct} reduction)`;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
8
48
|
|
|
9
49
|
function success(payload, options = {}) {
|
|
10
50
|
if (options.json) {
|
|
@@ -14,9 +54,15 @@ function success(payload, options = {}) {
|
|
|
14
54
|
};
|
|
15
55
|
}
|
|
16
56
|
|
|
57
|
+
let output = `${payload.run_id} ${payload.phase} ${payload.status}\n`;
|
|
58
|
+
|
|
59
|
+
if (payload.savings_summary) {
|
|
60
|
+
output += `${payload.savings_summary}\n`;
|
|
61
|
+
}
|
|
62
|
+
|
|
17
63
|
return {
|
|
18
64
|
exitCode: 0,
|
|
19
|
-
stdout:
|
|
65
|
+
stdout: output,
|
|
20
66
|
};
|
|
21
67
|
}
|
|
22
68
|
|
|
@@ -61,6 +107,12 @@ export function runStatusCommand(parsed, context = {}) {
|
|
|
61
107
|
status_path: statusPath,
|
|
62
108
|
};
|
|
63
109
|
|
|
110
|
+
const savingsSummary = readUsageSavingsSummary(stateRoot, options.run);
|
|
111
|
+
|
|
112
|
+
if (savingsSummary) {
|
|
113
|
+
payload.savings_summary = savingsSummary;
|
|
114
|
+
}
|
|
115
|
+
|
|
64
116
|
return success(payload, { json: options.json });
|
|
65
117
|
} catch (error) {
|
|
66
118
|
return {
|
package/wazir.manifest.yaml
CHANGED
|
@@ -47,20 +47,31 @@ workflows:
|
|
|
47
47
|
- prepare_next
|
|
48
48
|
- run_audit
|
|
49
49
|
phases:
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
- init
|
|
51
|
+
- clarifier
|
|
52
|
+
- executor
|
|
53
|
+
- final_review
|
|
54
|
+
phase_prerequisites:
|
|
55
|
+
init: {}
|
|
56
|
+
clarifier: {}
|
|
57
|
+
executor:
|
|
58
|
+
required_artifacts:
|
|
59
|
+
- clarified/clarification.md
|
|
60
|
+
- clarified/spec-hardened.md
|
|
61
|
+
- clarified/design.md
|
|
62
|
+
- clarified/execution-plan.md
|
|
63
|
+
required_phase_exits:
|
|
64
|
+
- clarifier
|
|
65
|
+
final_review:
|
|
66
|
+
required_artifacts:
|
|
67
|
+
- clarified/clarification.md
|
|
68
|
+
- clarified/spec-hardened.md
|
|
69
|
+
- clarified/design.md
|
|
70
|
+
- clarified/execution-plan.md
|
|
71
|
+
- artifacts/verification-proof.md
|
|
72
|
+
required_phase_exits:
|
|
73
|
+
- clarifier
|
|
74
|
+
- executor
|
|
64
75
|
roles:
|
|
65
76
|
- clarifier
|
|
66
77
|
- researcher
|
|
@@ -85,6 +96,7 @@ required_hooks:
|
|
|
85
96
|
- stop_handoff_harvest
|
|
86
97
|
- protected_path_write_guard
|
|
87
98
|
- loop_cap_guard
|
|
99
|
+
- context_mode_router
|
|
88
100
|
protected_paths:
|
|
89
101
|
- input
|
|
90
102
|
- roles
|
|
@@ -92,11 +104,8 @@ protected_paths:
|
|
|
92
104
|
- schemas
|
|
93
105
|
- exports/hosts
|
|
94
106
|
prohibited_terms:
|
|
95
|
-
- Agent OS
|
|
96
|
-
- daemon
|
|
97
107
|
- HTTP control plane
|
|
98
108
|
- web UI
|
|
99
|
-
- OpenAI Symphony
|
|
100
109
|
- Elixir
|
|
101
110
|
adapters:
|
|
102
111
|
context_mode:
|
package/workflows/clarify.md
CHANGED
|
@@ -24,6 +24,10 @@ On entering this phase, run:
|
|
|
24
24
|
- unresolved questions list
|
|
25
25
|
- scope summary
|
|
26
26
|
|
|
27
|
+
## Review Loop
|
|
28
|
+
|
|
29
|
+
Clarification artifact is reviewed by the reviewer role using the review loop pattern with spec/clarification dimensions. The reviewer is invoked with `--mode clarification-review`. The clarifier resolves findings. Clarification does not flow to specify until all review passes complete.
|
|
30
|
+
|
|
27
31
|
## Approval Gate
|
|
28
32
|
|
|
29
33
|
- no formal approval gate, but unresolved material ambiguity must be escalated
|
|
@@ -39,6 +39,10 @@ On rejection: `wazir capture event --run <run-id> --event gate_rejected --phase
|
|
|
39
39
|
On completing this phase, run:
|
|
40
40
|
`wazir capture event --run <run-id> --event phase_exit --phase <phase-name> --status completed`
|
|
41
41
|
|
|
42
|
+
## Loop Structure
|
|
43
|
+
|
|
44
|
+
Follows the review loop pattern in `docs/reference/review-loop-pattern.md` with the canonical design-review dimensions (spec coverage, design-spec consistency, accessibility, visual consistency, exported-code fidelity). The designer role resolves findings. Starts when the approved design artifact enters the `design_review` phase. Pass count determined by depth. No extension.
|
|
45
|
+
|
|
42
46
|
## Failure Conditions
|
|
43
47
|
|
|
44
48
|
- vague findings without visual evidence
|
package/workflows/design.md
CHANGED
|
@@ -33,6 +33,10 @@ On entering this phase, run:
|
|
|
33
33
|
|
|
34
34
|
- explicit human approval required before design-review
|
|
35
35
|
|
|
36
|
+
## Review Loop
|
|
37
|
+
|
|
38
|
+
After user approval, design artifact is reviewed via the design-review workflow (`workflows/design-review.md`) using the review loop pattern with the canonical design-review dimensions (spec coverage, design-spec consistency, accessibility, visual consistency, exported-code fidelity). The reviewer is invoked with `--mode design-review`. Design does not flow to planning until all review passes complete.
|
|
39
|
+
|
|
36
40
|
## Phase exit
|
|
37
41
|
|
|
38
42
|
On completing this phase, run:
|
package/workflows/discover.md
CHANGED
|
@@ -23,6 +23,10 @@ On entering this phase, run:
|
|
|
23
23
|
- research artifact
|
|
24
24
|
- cited findings
|
|
25
25
|
|
|
26
|
+
## Review Loop
|
|
27
|
+
|
|
28
|
+
Research artifact is reviewed by the reviewer role using the review loop pattern (`docs/reference/review-loop-pattern.md`) with research dimensions (coverage, source quality, relevance, gaps, contradictions). The reviewer is invoked with `--mode research-review`. The researcher resolves findings. Research does not flow to specify until all review passes complete.
|
|
29
|
+
|
|
26
30
|
## Approval Gate
|
|
27
31
|
|
|
28
32
|
- no formal approval gate, but unsupported research cannot flow forward
|
package/workflows/execute.md
CHANGED
|
@@ -34,6 +34,10 @@ If either check fails:
|
|
|
34
34
|
- code and docs changes
|
|
35
35
|
- execution notes
|
|
36
36
|
|
|
37
|
+
## Per-Task Review
|
|
38
|
+
|
|
39
|
+
Each task's output is reviewed using the review loop pattern with the 5 task-execution dimensions (correctness, tests, wiring, drift, quality). The reviewer is invoked with `--mode task-review --task-id <NNN>`. This is NOT the final review -- it is a per-task gate. Review happens BEFORE commit. Review logs use task-scoped filenames: `<phase>-task-<NNN>-review-pass-<N>.md`. See `docs/reference/review-loop-pattern.md` for code review scoping rules.
|
|
40
|
+
|
|
37
41
|
## Approval Gate
|
|
38
42
|
|
|
39
43
|
- no new scope without explicit approval
|
package/workflows/plan-review.md
CHANGED
|
@@ -37,6 +37,10 @@ On rejection: `wazir capture event --run <run-id> --event gate_rejected --phase
|
|
|
37
37
|
On completing this phase, run:
|
|
38
38
|
`wazir capture event --run <run-id> --event phase_exit --phase <phase-name> --status completed`
|
|
39
39
|
|
|
40
|
+
## Loop Structure
|
|
41
|
+
|
|
42
|
+
Follows the review loop pattern in `docs/reference/review-loop-pattern.md` with plan dimensions. The planner role resolves findings. Pass count determined by depth. No extension.
|
|
43
|
+
|
|
40
44
|
## Failure Conditions
|
|
41
45
|
|
|
42
46
|
- sequence gaps survive review
|
package/workflows/plan.md
CHANGED
|
@@ -25,6 +25,10 @@ On entering this phase, run:
|
|
|
25
25
|
- implementation plan artifact
|
|
26
26
|
- ordered tasks and verification steps
|
|
27
27
|
|
|
28
|
+
## Review Loop
|
|
29
|
+
|
|
30
|
+
Plan artifact is reviewed via the plan-review workflow (`workflows/plan-review.md`) using the review loop pattern with plan dimensions. The reviewer is invoked with `--mode plan-review`.
|
|
31
|
+
|
|
28
32
|
## Approval Gate
|
|
29
33
|
|
|
30
34
|
- explicit human approval required before execution
|
|
@@ -36,6 +36,10 @@ On rejection: `wazir capture event --run <run-id> --event gate_rejected --phase
|
|
|
36
36
|
On completing this phase, run:
|
|
37
37
|
`wazir capture event --run <run-id> --event phase_exit --phase <phase-name> --status completed`
|
|
38
38
|
|
|
39
|
+
## Loop Structure
|
|
40
|
+
|
|
41
|
+
This workflow IS a review loop. Follows the pattern in `docs/reference/review-loop-pattern.md` with spec/clarification dimensions. The specifier role resolves findings. Loop count tracked via `wazir capture loop-check --mode spec-challenge`. Pass count determined by depth (quick=3, standard=5, deep=7). No extension beyond depth pass count.
|
|
42
|
+
|
|
39
43
|
## Failure Conditions
|
|
40
44
|
|
|
41
45
|
- rubber-stamp review
|
package/workflows/specify.md
CHANGED
|
@@ -24,6 +24,10 @@ On entering this phase, run:
|
|
|
24
24
|
- acceptance criteria
|
|
25
25
|
- assumptions and non-goals
|
|
26
26
|
|
|
27
|
+
## Review Loop
|
|
28
|
+
|
|
29
|
+
Spec artifact is reviewed via the spec-challenge workflow (`workflows/spec-challenge.md`) using the review loop pattern with spec dimensions. The reviewer is invoked with `--mode spec-challenge`. The specifier resolves findings.
|
|
30
|
+
|
|
27
31
|
## Approval Gate
|
|
28
32
|
|
|
29
33
|
- explicit human approval required before planning
|
package/workflows/verify.md
CHANGED
|
@@ -32,6 +32,10 @@ On entering this phase, run:
|
|
|
32
32
|
On completing this phase, run:
|
|
33
33
|
`wazir capture event --run <run-id> --event phase_exit --phase <phase-name> --status completed`
|
|
34
34
|
|
|
35
|
+
## Relationship to Review Loops
|
|
36
|
+
|
|
37
|
+
Verification is invoked per-task during execution, not as a review loop. It produces deterministic proof, not adversarial findings.
|
|
38
|
+
|
|
35
39
|
## Failure Conditions
|
|
36
40
|
|
|
37
41
|
- stale or partial verification
|