hadara 0.3.3 → 0.4.0-rc.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/README.md +26 -18
- package/dist/cli/dashboard.js +28 -9
- package/dist/cli/docs.js +50 -0
- package/dist/cli/evidence.js +113 -0
- package/dist/cli/handoff.js +13 -0
- package/dist/cli/help.js +4 -3
- package/dist/cli/init.js +615 -111
- package/dist/cli/legacy-boundary.js +77 -0
- package/dist/cli/main.js +31 -0
- package/dist/cli/package-smoke.js +34 -1
- package/dist/cli/release-artifact.js +9 -0
- package/dist/cli/release-closeout.js +22 -0
- package/dist/cli/release-publish.js +9 -0
- package/dist/cli/task.js +85 -21
- package/dist/cli/validation.js +71 -0
- package/dist/context/context-pack.js +204 -26
- package/dist/context/session-start.js +85 -6
- package/dist/context/task-extractors.js +3 -2
- package/dist/core/schema.js +22 -0
- package/dist/evidence/evidence.js +131 -9
- package/dist/evidence/semantics.js +3 -1
- package/dist/handoff/handoff-stale-problems.js +155 -0
- package/dist/handoff/handoff-suggestion.js +6 -1
- package/dist/harness/validate.js +316 -58
- package/dist/schemas/close-source.schema.json +33 -0
- package/dist/schemas/context-pack.schema.json +23 -0
- package/dist/schemas/docs-inbox.schema.json +50 -0
- package/dist/schemas/docs-read-map.schema.json +83 -0
- package/dist/schemas/docs-register.schema.json +70 -0
- package/dist/schemas/evidence-projection.schema.json +35 -0
- package/dist/schemas/evidence-summary.schema.json +73 -0
- package/dist/schemas/handoff-stale-problems.schema.json +64 -0
- package/dist/schemas/package-recycle.schema.json +150 -0
- package/dist/schemas/release-closeout.schema.json +39 -0
- package/dist/schemas/schema-index.json +79 -2
- package/dist/schemas/session-start.schema.json +30 -0
- package/dist/schemas/smoke-evidence-summary.schema.json +1 -1
- package/dist/schemas/task-audit-close.schema.json +7 -0
- package/dist/schemas/task-close.schema.json +4 -0
- package/dist/schemas/task-finalize.schema.json +40 -1
- package/dist/schemas/task-status.schema.json +117 -0
- package/dist/schemas/task-workbench.schema.json +97 -2
- package/dist/schemas/validation-run.schema.json +103 -0
- package/dist/services/capability-registry.js +326 -47
- package/dist/services/ci-gate.js +4 -2
- package/dist/services/dashboard-bootstrap.js +6 -6
- package/dist/services/dashboard-cache.js +2 -0
- package/dist/services/dashboard-task-detail.js +42 -13
- package/dist/services/dashboard-timeline.js +2 -2
- package/dist/services/docs-registry.js +485 -30
- package/dist/services/evidence-lint.js +9 -3
- package/dist/services/evidence-summary.js +66 -0
- package/dist/services/lifecycle-guide.js +11 -12
- package/dist/services/operational-debt.js +8 -14
- package/dist/services/operations-status-service.js +7 -1
- package/dist/services/package-recycle.js +762 -0
- package/dist/services/protocol-consistency.js +11 -5
- package/dist/services/protocol-migration.js +1 -1
- package/dist/services/release-closeout.js +136 -0
- package/dist/services/state-projection.js +31 -16
- package/dist/services/task-read-model.js +3 -7
- package/dist/services/task-workbench.js +582 -29
- package/dist/services/validation-run.js +325 -0
- package/dist/services/workbench-next-actions.js +31 -20
- package/dist/services/write-preflight.js +0 -7
- package/dist/task/authoring-guidance.js +74 -0
- package/dist/task/lifecycle-next-actions.js +0 -1
- package/dist/task/task-capsule.js +6 -11
- package/dist/task/task-close-repair-plan.js +3 -2
- package/dist/task/task-close.js +319 -39
- package/dist/task/task-complete-flow.js +4 -3
- package/dist/task/task-finalize.js +184 -20
- package/dist/task/task-finish.js +36 -8
- package/dist/task/task-lifecycle.js +14 -9
- package/dist/task/task-templates.js +5 -24
- package/dist/task/task-upgrade-scaffold.js +9 -60
- package/dist/tui/constants.js +1 -7
- package/dist/tui/read-model.js +4 -4
- package/dist/tui/snapshot.js +14 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<img alt="Stable npm release" src="https://img.shields.io/badge/npm-0.3.3-blue">
|
|
9
|
-
<img alt="Source version" src="https://img.shields.io/badge/source-0.
|
|
9
|
+
<img alt="Source version" src="https://img.shields.io/badge/source-0.4.0--rc.0-blue">
|
|
10
10
|
<img alt="Node.js" src="https://img.shields.io/badge/node-%3E%3D22-brightgreen">
|
|
11
11
|
<img alt="License" src="https://img.shields.io/badge/license-MIT-lightgrey">
|
|
12
12
|
</p>
|
|
@@ -27,20 +27,27 @@ Current stable npm release:
|
|
|
27
27
|
hadara@0.3.3
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Current source release candidate:
|
|
31
31
|
|
|
32
32
|
```text
|
|
33
|
-
hadara@0.
|
|
33
|
+
hadara@0.4.0-rc.0
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Previous published release candidate:
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
```text
|
|
39
|
+
hadara@0.3.4-rc.0
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The 0.4.0 source line is a breaking productization release candidate after stable 0.3.3 and the published 0.3.4-rc.0 agent UX line. It keeps the context-routing and finalize-first lifecycle baseline, then simplifies new projects around a productized 0.4 scaffold, registry-backed docs read maps, a four-file Task Capsule, generated evidence projection, a normalized close-source contract, and fail-closed legacy mutation boundaries.
|
|
43
|
+
|
|
44
|
+
Phase labels are internal implementation phases, not npm release-candidate labels. The stable `0.3.3` package is the default install target; `0.4.0-rc.0` is the current source candidate and must not be treated as published until an approval-gated publish capsule completes.
|
|
39
45
|
|
|
40
46
|
| Surface | Status |
|
|
41
47
|
|---|---|
|
|
42
48
|
| Current stable | [`hadara@0.3.3`](docs/RELEASE_NOTES.md#033) |
|
|
43
|
-
|
|
|
49
|
+
| Source candidate | [`hadara@0.4.0-rc.0`](docs/RELEASE_NOTES.md#040-rc0) |
|
|
50
|
+
| Previous RC | [`hadara@0.3.4-rc.0`](docs/RELEASE_NOTES.md#034-rc0) |
|
|
44
51
|
| Previous stable | [`hadara@0.3.2`](docs/RELEASE_NOTES.md#032) |
|
|
45
52
|
| Historical RCs | See [Release Notes](docs/RELEASE_NOTES.md). |
|
|
46
53
|
| GitHub Release | Secondary target, approval-gated. |
|
|
@@ -48,7 +55,7 @@ Phase labels are internal implementation phases, not npm release-candidate label
|
|
|
48
55
|
| PyPI/Python package | `hadara==0.2.0rc1` published preview bridge. |
|
|
49
56
|
| Installer scripts / USB launchers | Deferred. |
|
|
50
57
|
|
|
51
|
-
No release command should publish, create a GitHub Release, build Docker images, upload artifacts, or load token values unless an operator explicitly approves the mutation path for the active release capsule. Stable `0.3.3` is the npm package line; GitHub Release, Docker/PyPI publish, installer execution, and MCP release/package execution remain separate explicit mutations.
|
|
58
|
+
No release command should publish, create a GitHub Release, build Docker images, upload artifacts, or load token values unless an operator explicitly approves the mutation path for the active release capsule. Stable `0.3.3` is the npm package line until the `0.4.0-rc.0` publish capsule completes; GitHub Release, Docker/PyPI publish, installer execution, and MCP release/package execution remain separate explicit mutations.
|
|
52
59
|
|
|
53
60
|
## Install
|
|
54
61
|
|
|
@@ -69,11 +76,11 @@ npx hadara@0.3.3 help
|
|
|
69
76
|
npx hadara@0.3.3 doctor --json
|
|
70
77
|
```
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
After `0.4.0-rc.0` is published, evaluate it explicitly:
|
|
73
80
|
|
|
74
81
|
```bash
|
|
75
|
-
npm install -g hadara@0.
|
|
76
|
-
npx hadara@0.
|
|
82
|
+
npm install -g hadara@0.4.0-rc.0
|
|
83
|
+
npx hadara@0.4.0-rc.0 help
|
|
77
84
|
```
|
|
78
85
|
|
|
79
86
|
For release or recycle evidence, prefer an isolated prefix install when PATH, global installs, or `npx` cache behavior may be stale:
|
|
@@ -109,7 +116,7 @@ Ask the CLI for the workflow before choosing commands:
|
|
|
109
116
|
```bash
|
|
110
117
|
hadara help
|
|
111
118
|
hadara help lifecycle
|
|
112
|
-
hadara task
|
|
119
|
+
hadara task status --json
|
|
113
120
|
```
|
|
114
121
|
|
|
115
122
|
Use structured discovery when an agent or tool needs machine-readable command metadata:
|
|
@@ -122,15 +129,15 @@ hadara help command task.close
|
|
|
122
129
|
|
|
123
130
|
## Primary Capsule Lifecycle
|
|
124
131
|
|
|
125
|
-
The 0.
|
|
132
|
+
The 0.4 primary path is intentionally small. Agents should start with compact context and use `task finalize` as the default lifecycle close path:
|
|
126
133
|
|
|
127
134
|
```bash
|
|
128
|
-
hadara task
|
|
135
|
+
hadara task status --json
|
|
136
|
+
hadara session start --task T-XXXX --json
|
|
129
137
|
hadara task create "implement a focused change" --json
|
|
130
138
|
hadara task status --task T-XXXX --json
|
|
131
139
|
hadara evidence add-command --task T-XXXX --summary "..." --result passed --category validation --idempotency-key "command:T-XXXX:check" --json
|
|
132
140
|
# Finalize Task Capsule docs and tracked state docs before closing.
|
|
133
|
-
hadara task lifecycle --task T-XXXX --json
|
|
134
141
|
hadara task finalize --task T-XXXX --json
|
|
135
142
|
hadara task finalize --task T-XXXX --execute --plan-hash sha256:... --json
|
|
136
143
|
hadara handoff suggest --task T-XXXX --json
|
|
@@ -154,8 +161,9 @@ Deferred Evidence v2 scope is explicit: rebuild preview/execute, `check-id`, `su
|
|
|
154
161
|
Use read-only lifecycle diagnostics when you want a compact current-stage report, next recommended action, or close-proof repair explanation:
|
|
155
162
|
|
|
156
163
|
```bash
|
|
164
|
+
hadara task status --task T-XXXX --json
|
|
157
165
|
hadara task complete --task T-XXXX --json
|
|
158
|
-
hadara task lifecycle --task T-XXXX --json
|
|
166
|
+
hadara task lifecycle --task T-XXXX --json # compatibility
|
|
159
167
|
hadara task close-repair-plan --task T-XXXX --json
|
|
160
168
|
```
|
|
161
169
|
|
|
@@ -260,7 +268,7 @@ Dashboard, TUI, Hermes, MCP, installer, package, release, and run commands stay
|
|
|
260
268
|
|
|
261
269
|
## Safety Boundaries
|
|
262
270
|
|
|
263
|
-
HADARA 0.
|
|
271
|
+
HADARA 0.4.0-rc.0 is not:
|
|
264
272
|
|
|
265
273
|
- a full agent runtime;
|
|
266
274
|
- Rack/enterprise behavior;
|
|
@@ -300,7 +308,7 @@ Portable/local state is not committed. Project docs, Task Capsules, and reduced
|
|
|
300
308
|
|
|
301
309
|
`evidence.jsonl` is the canonical Task Capsule evidence source. `EVIDENCE.md` is a non-canonical human summary that can help review validation history, but it must not be treated as the source of truth for rebuild, migration, or resolution logic.
|
|
302
310
|
|
|
303
|
-
0.
|
|
311
|
+
0.4.0-rc.0 does not implement `hadara evidence rebuild --json` or an execute mode. Future rebuild work must first define whether a difference is formatting regeneration, managed-section drift, or data inconsistency before reporting `wouldChange`. Any later write-capable rebuild flow must be dry-run-first, reviewed, and before-hash guarded before it rewrites derived Markdown.
|
|
304
312
|
|
|
305
313
|
## Development / Contributing
|
|
306
314
|
|
|
@@ -313,7 +321,7 @@ hadara init --profile standard
|
|
|
313
321
|
hadara init --profile governed
|
|
314
322
|
```
|
|
315
323
|
|
|
316
|
-
Every profile generates
|
|
324
|
+
Every profile generates the 0.4 project scaffold with compact agent entry docs, a docs registry, a workflow guide, and the current context-aware finalize-first lifecycle loop plus low-level proof-boundary reference commands.
|
|
317
325
|
|
|
318
326
|
| Profile | Use When |
|
|
319
327
|
|---|---|
|
package/dist/cli/dashboard.js
CHANGED
|
@@ -20,7 +20,6 @@ const dashboard_heavy_projection_1 = require("../services/dashboard-heavy-projec
|
|
|
20
20
|
const evidence_lint_1 = require("../services/evidence-lint");
|
|
21
21
|
const evidence_list_1 = require("../services/evidence-list");
|
|
22
22
|
const dashboard_timeline_1 = require("../services/dashboard-timeline");
|
|
23
|
-
const operational_debt_1 = require("../services/operational-debt");
|
|
24
23
|
const operations_status_service_1 = require("../services/operations-status-service");
|
|
25
24
|
const task_read_model_1 = require("../services/task-read-model");
|
|
26
25
|
const task_workbench_1 = require("../services/task-workbench");
|
|
@@ -93,8 +92,11 @@ function createDashboardApiResponse(projectRoot, requestUrl, method) {
|
|
|
93
92
|
if (!url || !url.pathname.startsWith('/api/'))
|
|
94
93
|
return null;
|
|
95
94
|
const headOnly = normalizedMethod === 'HEAD';
|
|
96
|
-
if (url.pathname === '/api/status')
|
|
97
|
-
|
|
95
|
+
if (url.pathname === '/api/status') {
|
|
96
|
+
// Dashboard clients fetch operational debt separately; keep the status
|
|
97
|
+
// route cheap so a single slow debt scan cannot block first API paint.
|
|
98
|
+
return jsonResponse(readCachedOpsStatus(projectRoot, false, url.searchParams.get('cache') === 'bypass'), headOnly);
|
|
99
|
+
}
|
|
98
100
|
if (url.pathname === '/api/dashboard/core') {
|
|
99
101
|
const bypassProjection = url.searchParams.get('cache') === 'bypass';
|
|
100
102
|
const status = bypassProjection ? null : (0, dashboard_refresh_1.createDashboardProjectionStatusReport)(projectRoot);
|
|
@@ -116,14 +118,19 @@ function createDashboardApiResponse(projectRoot, requestUrl, method) {
|
|
|
116
118
|
return jsonResponse((0, dashboard_heavy_projection_1.createProjectedDashboardDebtReport)(projectRoot), headOnly);
|
|
117
119
|
if (url.pathname === '/api/dashboard/bootstrap') {
|
|
118
120
|
const selectedTaskId = url.searchParams.get('selectedTaskId')?.trim();
|
|
119
|
-
const tier = url.searchParams.get('tier') === '
|
|
121
|
+
const tier = url.searchParams.get('tier') === 'full' ? 'full' : 'core';
|
|
120
122
|
const keyParts = ['bootstrap'];
|
|
121
123
|
if (tier === 'core')
|
|
122
124
|
keyParts.push('core');
|
|
123
125
|
if (selectedTaskId)
|
|
124
126
|
keyParts.push('selected', selectedTaskId);
|
|
125
127
|
const key = (0, dashboard_cache_1.createDashboardCacheKey)(projectRoot, ...keyParts);
|
|
126
|
-
const cached = (0, dashboard_cache_1.getOrCreateCachedReport)(key, { ttlMs: dashboard_cache_1.DASHBOARD_CACHE_TTLS.bootstrap, bypass: url.searchParams.get('cache') === 'bypass' }, () => (0, dashboard_bootstrap_1.createDashboardBootstrapReport)(projectRoot, {
|
|
128
|
+
const cached = (0, dashboard_cache_1.getOrCreateCachedReport)(key, { ttlMs: dashboard_cache_1.DASHBOARD_CACHE_TTLS.bootstrap, bypass: url.searchParams.get('cache') === 'bypass' }, () => (0, dashboard_bootstrap_1.createDashboardBootstrapReport)(projectRoot, {
|
|
129
|
+
tier,
|
|
130
|
+
...(selectedTaskId ? { selectedTaskId } : {}),
|
|
131
|
+
status: readCachedOpsStatus(projectRoot, tier === 'full', url.searchParams.get('cache') === 'bypass'),
|
|
132
|
+
tasks: readCachedTaskList(projectRoot, url.searchParams.get('cache') === 'bypass')
|
|
133
|
+
}));
|
|
127
134
|
return jsonResponse((0, dashboard_cache_1.withDashboardCacheMetadata)(cached.value, cached.cache), headOnly);
|
|
128
135
|
}
|
|
129
136
|
if (url.pathname === '/api/dashboard/task-detail') {
|
|
@@ -137,11 +144,16 @@ function createDashboardApiResponse(projectRoot, requestUrl, method) {
|
|
|
137
144
|
if (url.pathname === '/api/dashboard/cache/status')
|
|
138
145
|
return jsonResponse((0, dashboard_cache_1.createDashboardCacheStatusReport)(), headOnly);
|
|
139
146
|
if (url.pathname === '/api/tasks')
|
|
140
|
-
return jsonResponse((
|
|
147
|
+
return jsonResponse(readCachedTaskList(projectRoot, url.searchParams.get('cache') === 'bypass'), headOnly);
|
|
141
148
|
if (url.pathname === '/api/active-run')
|
|
142
149
|
return jsonResponse((0, active_run_state_1.safeCreateActiveRunProjection)(projectRoot), headOnly);
|
|
143
|
-
if (url.pathname === '/api/debt')
|
|
144
|
-
|
|
150
|
+
if (url.pathname === '/api/debt') {
|
|
151
|
+
// Keep the legacy dashboard debt route on the same fast aggregate path as
|
|
152
|
+
// /api/dashboard/debt. The full operational-debt read model remains
|
|
153
|
+
// available through CLI/MCP surfaces; dashboard request handlers must not
|
|
154
|
+
// perform broad capsule scans on the hot API path.
|
|
155
|
+
return jsonResponse((0, dashboard_heavy_projection_1.createProjectedDashboardDebtReport)(projectRoot), headOnly);
|
|
156
|
+
}
|
|
145
157
|
if (url.pathname === '/api/timeline') {
|
|
146
158
|
const taskId = url.searchParams.get('taskId')?.trim();
|
|
147
159
|
const key = taskId ? (0, dashboard_cache_1.createDashboardCacheKey)(projectRoot, 'timeline', taskId) : (0, dashboard_cache_1.createDashboardCacheKey)(projectRoot, 'timeline');
|
|
@@ -152,7 +164,8 @@ function createDashboardApiResponse(projectRoot, requestUrl, method) {
|
|
|
152
164
|
const taskId = url.searchParams.get('taskId')?.trim();
|
|
153
165
|
if (!taskId)
|
|
154
166
|
return missingTaskId(headOnly);
|
|
155
|
-
|
|
167
|
+
const detail = url.searchParams.get('detail') === 'full' ? 'full' : 'fast';
|
|
168
|
+
return jsonResponse((0, task_workbench_1.createTaskWorkbenchReport)(projectRoot, taskId, new Date(), { detail }), headOnly);
|
|
156
169
|
}
|
|
157
170
|
if (url.pathname === '/api/evidence-lint') {
|
|
158
171
|
const taskId = url.searchParams.get('taskId')?.trim();
|
|
@@ -168,6 +181,12 @@ function createDashboardApiResponse(projectRoot, requestUrl, method) {
|
|
|
168
181
|
}
|
|
169
182
|
return notFound();
|
|
170
183
|
}
|
|
184
|
+
function readCachedOpsStatus(projectRoot, includeDebt, bypass) {
|
|
185
|
+
return (0, dashboard_cache_1.getOrCreateCachedReport)((0, dashboard_cache_1.createDashboardCacheKey)(projectRoot, 'status', includeDebt ? 'full' : 'core'), { ttlMs: dashboard_cache_1.DASHBOARD_CACHE_TTLS.status, bypass }, () => (0, operations_status_service_1.createOpsStatusReport)(projectRoot, { includeDebt })).value;
|
|
186
|
+
}
|
|
187
|
+
function readCachedTaskList(projectRoot, bypass) {
|
|
188
|
+
return (0, dashboard_cache_1.getOrCreateCachedReport)((0, dashboard_cache_1.createDashboardCacheKey)(projectRoot, 'tasks'), { ttlMs: dashboard_cache_1.DASHBOARD_CACHE_TTLS.tasks, bypass }, () => (0, task_read_model_1.createTaskListReport)(projectRoot)).value;
|
|
189
|
+
}
|
|
171
190
|
function missingTaskId(headOnly) {
|
|
172
191
|
return jsonResponse({
|
|
173
192
|
schemaVersion: 'hadara.dashboard.api.error.v1',
|
package/dist/cli/docs.js
CHANGED
|
@@ -5,6 +5,7 @@ const args_1 = require("./args");
|
|
|
5
5
|
const docs_cleanup_1 = require("../services/docs-cleanup");
|
|
6
6
|
const docs_registry_1 = require("../services/docs-registry");
|
|
7
7
|
const managed_sections_1 = require("../services/managed-sections");
|
|
8
|
+
const legacy_boundary_1 = require("./legacy-boundary");
|
|
8
9
|
function handleDocsCommand(input) {
|
|
9
10
|
const sub = input.args[1];
|
|
10
11
|
if (sub === 'list') {
|
|
@@ -26,6 +27,39 @@ function handleDocsCommand(input) {
|
|
|
26
27
|
printReport(report, input.jsonOutput);
|
|
27
28
|
return true;
|
|
28
29
|
}
|
|
30
|
+
if (sub === 'read-map') {
|
|
31
|
+
const report = (0, docs_registry_1.createDocsReadMapReport)(input.projectRoot, (0, args_1.getRequiredStringOption)(input.args, '--task'));
|
|
32
|
+
printReport(report, input.jsonOutput);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (sub === 'inbox') {
|
|
36
|
+
const report = (0, docs_registry_1.createDocsInboxReport)(input.projectRoot);
|
|
37
|
+
printReport(report, input.jsonOutput);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (sub === 'register') {
|
|
41
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'docs.register'))
|
|
42
|
+
return true;
|
|
43
|
+
const report = (0, docs_registry_1.createDocsRegisterReport)(input.projectRoot, {
|
|
44
|
+
documentPath: (0, args_1.getRequiredStringOption)(input.args, '--path'),
|
|
45
|
+
title: (0, args_1.getStringOption)(input.args, '--title'),
|
|
46
|
+
kind: (0, args_1.getStringOption)(input.args, '--kind'),
|
|
47
|
+
status: (0, args_1.getStringOption)(input.args, '--status'),
|
|
48
|
+
readWhen: (0, args_1.getStringOption)(input.args, '--read-when'),
|
|
49
|
+
readTier: (0, args_1.getStringOption)(input.args, '--read-tier'),
|
|
50
|
+
authority: (0, args_1.getStringOption)(input.args, '--authority'),
|
|
51
|
+
editPolicy: (0, args_1.getStringOption)(input.args, '--edit-policy'),
|
|
52
|
+
activeForTasks: splitCsv((0, args_1.getStringOption)(input.args, '--active-for-task')),
|
|
53
|
+
driftRisk: (0, args_1.getStringOption)(input.args, '--drift'),
|
|
54
|
+
driftReviewRequired: (0, args_1.getFlag)(input.args, '--drift-review-required'),
|
|
55
|
+
driftReason: (0, args_1.getStringOption)(input.args, '--drift-reason'),
|
|
56
|
+
requiredReading: (0, args_1.getFlag)(input.args, '--required-reading'),
|
|
57
|
+
requireExists: (0, args_1.getFlag)(input.args, '--require-exists'),
|
|
58
|
+
mode: (0, args_1.getFlag)(input.args, '--execute') ? 'execute' : 'dry-run'
|
|
59
|
+
});
|
|
60
|
+
printReport(report, input.jsonOutput);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
29
63
|
if (sub === 'managed') {
|
|
30
64
|
const managedSub = input.args[2];
|
|
31
65
|
if (managedSub === 'list') {
|
|
@@ -38,6 +72,8 @@ function handleDocsCommand(input) {
|
|
|
38
72
|
}
|
|
39
73
|
}
|
|
40
74
|
if (sub === 'patch') {
|
|
75
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'docs.patch'))
|
|
76
|
+
return true;
|
|
41
77
|
const report = (0, managed_sections_1.createDocsPatchPlanReport)(input.projectRoot, {
|
|
42
78
|
targetPath: (0, args_1.getRequiredStringOption)(input.args, '--path'),
|
|
43
79
|
sectionId: (0, args_1.getRequiredStringOption)(input.args, '--section'),
|
|
@@ -72,6 +108,14 @@ function handleDocsCommand(input) {
|
|
|
72
108
|
}
|
|
73
109
|
return false;
|
|
74
110
|
}
|
|
111
|
+
function blockLegacyMutation(input, command) {
|
|
112
|
+
const report = (0, legacy_boundary_1.createLegacyMutationBlockedReport)(input.projectRoot, command);
|
|
113
|
+
if (!report)
|
|
114
|
+
return false;
|
|
115
|
+
(0, legacy_boundary_1.printLegacyMutationBlockedReport)(report, input.jsonOutput);
|
|
116
|
+
process.exitCode = 6;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
75
119
|
function printReport(report, jsonOutput) {
|
|
76
120
|
if (jsonOutput) {
|
|
77
121
|
console.log(JSON.stringify(report, null, 2));
|
|
@@ -79,3 +123,9 @@ function printReport(report, jsonOutput) {
|
|
|
79
123
|
}
|
|
80
124
|
console.log(JSON.stringify(report, null, 2));
|
|
81
125
|
}
|
|
126
|
+
function splitCsv(value) {
|
|
127
|
+
if (value === undefined)
|
|
128
|
+
return undefined;
|
|
129
|
+
const items = value.split(',').map((item) => item.trim()).filter(Boolean);
|
|
130
|
+
return items.length > 0 ? items : undefined;
|
|
131
|
+
}
|
package/dist/cli/evidence.js
CHANGED
|
@@ -11,9 +11,15 @@ const evidence_json_1 = require("./evidence-json");
|
|
|
11
11
|
const evidence_lint_1 = require("../services/evidence-lint");
|
|
12
12
|
const evidence_list_1 = require("../services/evidence-list");
|
|
13
13
|
const evidence_migration_1 = require("../services/evidence-migration");
|
|
14
|
+
const evidence_summary_1 = require("../services/evidence-summary");
|
|
14
15
|
const args_1 = require("./args");
|
|
16
|
+
const legacy_boundary_1 = require("./legacy-boundary");
|
|
15
17
|
function handleEvidenceCommand(input) {
|
|
16
18
|
const sub = input.args[1];
|
|
19
|
+
if (hasHelpFlag(input.args)) {
|
|
20
|
+
console.log(renderEvidenceCommandHelp(sub));
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
17
23
|
if (sub === 'list') {
|
|
18
24
|
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
19
25
|
const report = (0, evidence_list_1.createEvidenceListReport)(input.projectRoot, {
|
|
@@ -52,7 +58,50 @@ function handleEvidenceCommand(input) {
|
|
|
52
58
|
process.exitCode = 6;
|
|
53
59
|
return true;
|
|
54
60
|
}
|
|
61
|
+
if (sub === 'summary') {
|
|
62
|
+
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
63
|
+
const report = (0, evidence_summary_1.createEvidenceSummaryReport)(input.projectRoot, {
|
|
64
|
+
taskId,
|
|
65
|
+
limit: (0, args_1.getIntegerOption)(input.args, '--limit', { min: 0, max: 500 }),
|
|
66
|
+
includePrivate: (0, args_1.getFlag)(input.args, '--include-private')
|
|
67
|
+
});
|
|
68
|
+
if (input.jsonOutput) {
|
|
69
|
+
console.log(JSON.stringify(report, null, 2));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(`[HADARA] evidence summary ${taskId}: ${report.ok ? 'ok' : 'issues'} | records ${report.summary.count} | durable ${report.summary.durableCount}`);
|
|
73
|
+
if (report.latest)
|
|
74
|
+
console.log(`latest: ${evidenceSummaryDisplay(report.latest)}`);
|
|
75
|
+
if (report.latestCloseEvidence)
|
|
76
|
+
console.log(`latest-close: ${evidenceSummaryDisplay(report.latestCloseEvidence)}`);
|
|
77
|
+
for (const record of report.records)
|
|
78
|
+
console.log(`- ${evidenceSummaryDisplay(record)}`);
|
|
79
|
+
for (const issue of report.issues) {
|
|
80
|
+
console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!report.ok)
|
|
84
|
+
process.exitCode = 6;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (sub === 'project') {
|
|
88
|
+
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
89
|
+
const report = (0, evidence_1.createEvidenceProjectionReport)(input.projectRoot, taskId, (0, args_1.getFlag)(input.args, '--execute'));
|
|
90
|
+
if (input.jsonOutput) {
|
|
91
|
+
console.log(JSON.stringify(report, null, 2));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(`[HADARA] evidence project ${taskId}: ${report.ok ? 'ok' : 'issues'} | mode ${report.mode} | wouldChange ${report.wouldChange}`);
|
|
95
|
+
for (const issue of report.issues)
|
|
96
|
+
console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
|
|
97
|
+
}
|
|
98
|
+
if (!report.ok)
|
|
99
|
+
process.exitCode = 6;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
55
102
|
if (sub === 'migrate') {
|
|
103
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'evidence.migrate'))
|
|
104
|
+
return true;
|
|
56
105
|
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
57
106
|
const report = (0, evidence_migration_1.createEvidenceMigrationPreviewReport)({
|
|
58
107
|
projectRoot: input.projectRoot,
|
|
@@ -76,6 +125,8 @@ function handleEvidenceCommand(input) {
|
|
|
76
125
|
return true;
|
|
77
126
|
}
|
|
78
127
|
if (sub === 'add-command') {
|
|
128
|
+
if (blockLegacyMutation(input, 'evidence.add-command'))
|
|
129
|
+
return true;
|
|
79
130
|
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
80
131
|
const summary = (0, args_1.getStringOption)(input.args, '--summary') ?? 'Command completed.';
|
|
81
132
|
const outcome = parseOptionalEvidenceOutcome((0, args_1.getStringOption)(input.args, '--outcome'));
|
|
@@ -131,6 +182,8 @@ function handleEvidenceCommand(input) {
|
|
|
131
182
|
}
|
|
132
183
|
if (sub !== 'collect')
|
|
133
184
|
return false;
|
|
185
|
+
if (blockLegacyMutation(input, 'evidence.collect'))
|
|
186
|
+
return true;
|
|
134
187
|
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
135
188
|
const kind = parseEvidenceKind((0, args_1.getStringOption)(input.args, '--kind', 'note') ?? 'note');
|
|
136
189
|
const summary = (0, args_1.getStringOption)(input.args, '--summary') ?? 'Manual evidence collection placeholder.';
|
|
@@ -163,6 +216,51 @@ function handleEvidenceCommand(input) {
|
|
|
163
216
|
}
|
|
164
217
|
return true;
|
|
165
218
|
}
|
|
219
|
+
function hasHelpFlag(args) {
|
|
220
|
+
return args.includes('--help') || args.includes('-h');
|
|
221
|
+
}
|
|
222
|
+
function renderEvidenceCommandHelp(sub) {
|
|
223
|
+
if (sub === 'add-command') {
|
|
224
|
+
return [
|
|
225
|
+
'[HADARA] evidence add-command',
|
|
226
|
+
'',
|
|
227
|
+
'Usage:',
|
|
228
|
+
' hadara evidence add-command --task T-XXXX --summary "..." --result passed --category validation --json',
|
|
229
|
+
'',
|
|
230
|
+
'Records an already-run command result. It does not execute shell commands.',
|
|
231
|
+
'Options:',
|
|
232
|
+
' --task <id> Task Capsule id.',
|
|
233
|
+
' --summary <text> Human-readable result summary.',
|
|
234
|
+
' --result <value> Legacy-compatible result: passed, failed, blocked, unknown.',
|
|
235
|
+
' --outcome <value> Evidence v2 outcome.',
|
|
236
|
+
' --category <value> Evidence v2 category.',
|
|
237
|
+
' --resolves <id> Add a resolves:<id> tag. Repeatable.',
|
|
238
|
+
' --supersedes <id> Add a supersedes:<id> tag. Repeatable.',
|
|
239
|
+
' --idempotency-key <key> Reuse an existing keyed record instead of appending duplicates.',
|
|
240
|
+
' --private Store as private evidence metadata.'
|
|
241
|
+
].join('\n');
|
|
242
|
+
}
|
|
243
|
+
return [
|
|
244
|
+
'[HADARA] evidence',
|
|
245
|
+
'',
|
|
246
|
+
'Usage:',
|
|
247
|
+
' hadara evidence list --task T-XXXX --json',
|
|
248
|
+
' hadara evidence lint --task T-XXXX --json',
|
|
249
|
+
' hadara evidence summary --task T-XXXX --json',
|
|
250
|
+
' hadara evidence project --task T-XXXX [--execute] --json',
|
|
251
|
+
' hadara evidence add-command --task T-XXXX --summary "..." --result passed --json',
|
|
252
|
+
'',
|
|
253
|
+
'Use `hadara help command evidence.add-command` for registry metadata.'
|
|
254
|
+
].join('\n');
|
|
255
|
+
}
|
|
256
|
+
function blockLegacyMutation(input, command) {
|
|
257
|
+
const report = (0, legacy_boundary_1.createLegacyMutationBlockedReport)(input.projectRoot, command);
|
|
258
|
+
if (!report)
|
|
259
|
+
return false;
|
|
260
|
+
(0, legacy_boundary_1.printLegacyMutationBlockedReport)(report, input.jsonOutput);
|
|
261
|
+
process.exitCode = 6;
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
166
264
|
function persistedEvidenceId(record) {
|
|
167
265
|
return record.schemaVersion === 'hadara.evidence.v2' && record.id ? record.id : 'evidence.jsonl';
|
|
168
266
|
}
|
|
@@ -175,6 +273,21 @@ function evidenceListCategory(record) {
|
|
|
175
273
|
function evidenceListOutcome(record) {
|
|
176
274
|
return record.outcome;
|
|
177
275
|
}
|
|
276
|
+
function evidenceSummaryDisplay(record) {
|
|
277
|
+
const tags = record.tags.length > 0 ? ` | tags:${record.tags.slice(0, 3).map(compactEvidenceTag).join(',')}${record.tags.length > 3 ? ',...' : ''}` : '';
|
|
278
|
+
return `${record.id} | ${record.time} | ${record.category}/${record.outcome} | ${record.visibility} | ${truncateSummary(record.summary)}${tags}`;
|
|
279
|
+
}
|
|
280
|
+
function truncateSummary(value) {
|
|
281
|
+
const maxLength = 160;
|
|
282
|
+
if (value.length <= maxLength)
|
|
283
|
+
return value;
|
|
284
|
+
return `${value.slice(0, maxLength - 3)}...`;
|
|
285
|
+
}
|
|
286
|
+
function compactEvidenceTag(value) {
|
|
287
|
+
if (value.startsWith('idempotency:'))
|
|
288
|
+
return 'idempotency:*';
|
|
289
|
+
return truncateSummary(value);
|
|
290
|
+
}
|
|
178
291
|
function parseEvidenceKind(value) {
|
|
179
292
|
if (['test-log', 'command-log', 'diff-summary', 'screenshot', 'note'].includes(value)) {
|
|
180
293
|
return value;
|
package/dist/cli/handoff.js
CHANGED
|
@@ -2,11 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleHandoffCommand = handleHandoffCommand;
|
|
4
4
|
const handoff_1 = require("../handoff/handoff");
|
|
5
|
+
const handoff_stale_problems_1 = require("../handoff/handoff-stale-problems");
|
|
5
6
|
const handoff_suggestion_1 = require("../handoff/handoff-suggestion");
|
|
6
7
|
const actor_1 = require("./actor");
|
|
7
8
|
const args_1 = require("./args");
|
|
8
9
|
function handleHandoffCommand(input) {
|
|
9
10
|
const sub = input.args[1];
|
|
11
|
+
if (sub === 'stale-problems') {
|
|
12
|
+
const report = (0, handoff_stale_problems_1.createHandoffStaleProblemsReport)(input.projectRoot);
|
|
13
|
+
if (input.jsonOutput) {
|
|
14
|
+
console.log(JSON.stringify(report, null, 2));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.log((0, handoff_stale_problems_1.formatHandoffStaleProblemsReport)(report));
|
|
18
|
+
}
|
|
19
|
+
if (!report.ok)
|
|
20
|
+
process.exitCode = 6;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
10
23
|
if (sub === 'suggest') {
|
|
11
24
|
const taskId = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
12
25
|
if (!taskId || taskId.startsWith('--'))
|
package/dist/cli/help.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.renderCommandHelp = renderCommandHelp;
|
|
|
7
7
|
exports.renderFamilyHelp = renderFamilyHelp;
|
|
8
8
|
const capability_registry_1 = require("../services/capability-registry");
|
|
9
9
|
const lifecycle_guide_1 = require("../services/lifecycle-guide");
|
|
10
|
-
const LIFECYCLE_ORDER = ['
|
|
10
|
+
const LIFECYCLE_ORDER = ['inspect', 'create', 'evidence', 'finalize', 'handoff'];
|
|
11
11
|
function handleHelpCommand(input) {
|
|
12
12
|
const topic = input.args[1];
|
|
13
13
|
if (!topic) {
|
|
@@ -51,7 +51,7 @@ function renderDefaultHelp() {
|
|
|
51
51
|
'',
|
|
52
52
|
'Start:',
|
|
53
53
|
' hadara help lifecycle',
|
|
54
|
-
' hadara task
|
|
54
|
+
' hadara task status --json',
|
|
55
55
|
' hadara task status --task T-XXXX --json',
|
|
56
56
|
'',
|
|
57
57
|
'Primary capsule lifecycle:',
|
|
@@ -74,7 +74,7 @@ function renderLifecycleHelp() {
|
|
|
74
74
|
const report = (0, lifecycle_guide_1.createLifecycleGuideReport)();
|
|
75
75
|
const diagnostics = (0, capability_registry_1.listCommandRegistryEntries)({ family: 'proof-diagnostics' }).filter((entry) => entry.requiredness === 'diagnostic');
|
|
76
76
|
const lines = [
|
|
77
|
-
'HADARA 0.
|
|
77
|
+
'HADARA 0.4 primary task lifecycle',
|
|
78
78
|
'',
|
|
79
79
|
'Primary capsule lifecycle:'
|
|
80
80
|
];
|
|
@@ -104,6 +104,7 @@ function renderCommandHelp(id) {
|
|
|
104
104
|
`Scope: ${entry.scope}`,
|
|
105
105
|
`Lifecycle stage: ${entry.lifecycleStage}`,
|
|
106
106
|
`Requiredness: ${entry.requiredness}`,
|
|
107
|
+
`Status: ${entry.status}`,
|
|
107
108
|
`Write boundary: ${entry.writeBoundary}`,
|
|
108
109
|
`Read-only: ${entry.readOnly ? 'yes' : 'no'}`,
|
|
109
110
|
`Risk: ${entry.risk}`,
|