hadara 0.1.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/LICENSE +21 -0
- package/README.md +109 -0
- package/dist/agent/evidence.js +50 -0
- package/dist/agent/loop.js +124 -0
- package/dist/cli/args.js +70 -0
- package/dist/cli/dashboard.js +185 -0
- package/dist/cli/debt.js +41 -0
- package/dist/cli/doctor.js +68 -0
- package/dist/cli/errors.js +58 -0
- package/dist/cli/evidence-json.js +75 -0
- package/dist/cli/evidence.js +80 -0
- package/dist/cli/handoff.js +16 -0
- package/dist/cli/harness.js +57 -0
- package/dist/cli/hermes-json.js +31 -0
- package/dist/cli/hermes.js +28 -0
- package/dist/cli/init.js +142 -0
- package/dist/cli/install.js +34 -0
- package/dist/cli/main.js +216 -0
- package/dist/cli/mcp.js +15 -0
- package/dist/cli/package-smoke.js +37 -0
- package/dist/cli/policy-json.js +22 -0
- package/dist/cli/policy.js +43 -0
- package/dist/cli/release-artifact.js +47 -0
- package/dist/cli/release-dry-run.js +24 -0
- package/dist/cli/release-gate.js +28 -0
- package/dist/cli/release-publish.js +41 -0
- package/dist/cli/run-scaffold.js +68 -0
- package/dist/cli/run-state.js +41 -0
- package/dist/cli/run.js +191 -0
- package/dist/cli/smoke.js +58 -0
- package/dist/cli/status-json.js +6 -0
- package/dist/cli/status.js +26 -0
- package/dist/cli/task-json.js +8 -0
- package/dist/cli/task.js +64 -0
- package/dist/cli/tools.js +25 -0
- package/dist/cli/tui.js +72 -0
- package/dist/cli/write-preflight.js +27 -0
- package/dist/core/audit.js +41 -0
- package/dist/core/events.js +63 -0
- package/dist/core/fs.js +44 -0
- package/dist/core/paths.js +59 -0
- package/dist/core/redaction.js +178 -0
- package/dist/core/schema.js +253 -0
- package/dist/core/workspace.js +47 -0
- package/dist/evidence/evidence.js +170 -0
- package/dist/evidence/private-manifest.js +101 -0
- package/dist/handoff/handoff.js +49 -0
- package/dist/harness/replay.js +200 -0
- package/dist/harness/validate.js +465 -0
- package/dist/hermes/context-export.js +104 -0
- package/dist/index.js +29 -0
- package/dist/mcp/server.js +104 -0
- package/dist/mcp/tool-dispatch.js +159 -0
- package/dist/mcp/tool-registry.js +150 -0
- package/dist/mcp/tool-schemas.js +18 -0
- package/dist/policy/command-risk.js +39 -0
- package/dist/policy/permission-matrix.js +42 -0
- package/dist/policy/policy.js +20 -0
- package/dist/policy/preflight.js +47 -0
- package/dist/policy/presets.js +24 -0
- package/dist/policy/tokenizer.js +53 -0
- package/dist/providers/fallback-executor.js +46 -0
- package/dist/providers/mock-provider.js +49 -0
- package/dist/providers/provider-contract.js +2 -0
- package/dist/providers/provider-preparation.js +220 -0
- package/dist/providers/scripted-provider.js +69 -0
- package/dist/schemas/active-run-projection.schema.json +73 -0
- package/dist/schemas/active-run-resume.schema.json +68 -0
- package/dist/schemas/clean-checkout-smoke.schema.json +126 -0
- package/dist/schemas/context-export.schema.json +35 -0
- package/dist/schemas/event.schema.json +17 -0
- package/dist/schemas/evidence-list.schema.json +49 -0
- package/dist/schemas/feature-smoke.schema.json +67 -0
- package/dist/schemas/install-plan.schema.json +93 -0
- package/dist/schemas/package-smoke.schema.json +130 -0
- package/dist/schemas/private-evidence.schema.json +48 -0
- package/dist/schemas/provider-call.schema.json +42 -0
- package/dist/schemas/provider-config.schema.json +43 -0
- package/dist/schemas/release-artifact-manifest.schema.json +55 -0
- package/dist/schemas/release-artifact.schema.json +140 -0
- package/dist/schemas/release-dry-run.schema.json +141 -0
- package/dist/schemas/release-gate.schema.json +42 -0
- package/dist/schemas/release-publish.schema.json +114 -0
- package/dist/schemas/schema-index.json +145 -0
- package/dist/schemas/smoke-evidence-summary.schema.json +88 -0
- package/dist/schemas/tools-list.schema.json +78 -0
- package/dist/schemas/write-preflight.schema.json +47 -0
- package/dist/services/active-run-state.js +215 -0
- package/dist/services/capability-registry.js +540 -0
- package/dist/services/clean-checkout-smoke.js +393 -0
- package/dist/services/evidence-list.js +136 -0
- package/dist/services/feature-smoke.js +155 -0
- package/dist/services/harness-service.js +7 -0
- package/dist/services/install-plan.js +233 -0
- package/dist/services/operational-debt.js +767 -0
- package/dist/services/operations-status-service.js +195 -0
- package/dist/services/package-smoke.js +676 -0
- package/dist/services/policy-service.js +25 -0
- package/dist/services/project-read-model.js +101 -0
- package/dist/services/release-artifact-evidence.js +77 -0
- package/dist/services/release-artifact.js +351 -0
- package/dist/services/release-dry-run.js +253 -0
- package/dist/services/release-evidence.js +138 -0
- package/dist/services/release-publish.js +163 -0
- package/dist/services/smoke-evidence.js +104 -0
- package/dist/services/task-read-model.js +125 -0
- package/dist/services/tools-list.js +26 -0
- package/dist/services/write-preflight.js +240 -0
- package/dist/task/task-capsule.js +121 -0
- package/dist/tools/fake-shell.js +56 -0
- package/dist/tui/cache.js +341 -0
- package/dist/tui/constants.js +44 -0
- package/dist/tui/layout.js +140 -0
- package/dist/tui/markdown.js +238 -0
- package/dist/tui/read-model-worker.js +24 -0
- package/dist/tui/read-model.js +502 -0
- package/dist/tui/snapshot.js +434 -0
- package/dist/tui/state.js +229 -0
- package/dist/tui/terminal.js +475 -0
- package/dist/tui/theme.js +86 -0
- package/package.json +16 -0
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const paths_1 = require("../core/paths");
|
|
5
|
+
const doctor_1 = require("./doctor");
|
|
6
|
+
const init_1 = require("./init");
|
|
7
|
+
const harness_1 = require("./harness");
|
|
8
|
+
const evidence_1 = require("./evidence");
|
|
9
|
+
const policy_1 = require("./policy");
|
|
10
|
+
const hermes_1 = require("./hermes");
|
|
11
|
+
const handoff_1 = require("./handoff");
|
|
12
|
+
const task_1 = require("./task");
|
|
13
|
+
const mcp_1 = require("./mcp");
|
|
14
|
+
const run_1 = require("./run");
|
|
15
|
+
const run_state_1 = require("./run-state");
|
|
16
|
+
const status_1 = require("./status");
|
|
17
|
+
const dashboard_1 = require("./dashboard");
|
|
18
|
+
const tools_1 = require("./tools");
|
|
19
|
+
const debt_1 = require("./debt");
|
|
20
|
+
const release_gate_1 = require("./release-gate");
|
|
21
|
+
const release_artifact_1 = require("./release-artifact");
|
|
22
|
+
const release_dry_run_1 = require("./release-dry-run");
|
|
23
|
+
const release_publish_1 = require("./release-publish");
|
|
24
|
+
const write_preflight_1 = require("./write-preflight");
|
|
25
|
+
const tui_1 = require("./tui");
|
|
26
|
+
const install_1 = require("./install");
|
|
27
|
+
const smoke_1 = require("./smoke");
|
|
28
|
+
const package_smoke_1 = require("./package-smoke");
|
|
29
|
+
const args_1 = require("./args");
|
|
30
|
+
const errors_1 = require("./errors");
|
|
31
|
+
function printHelp() {
|
|
32
|
+
console.log(`HADARA bootstrap CLI
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
hadara init [--project <path>] [--profile minimal|full|hadara-protocol]
|
|
36
|
+
hadara doctor
|
|
37
|
+
hadara task create <title>
|
|
38
|
+
hadara task list
|
|
39
|
+
hadara task show <task-id>
|
|
40
|
+
hadara evidence collect --task <task-id> [--kind note|test-log|command-log|diff-summary|screenshot] [--path <path>] [--summary <text>] [--result passed|failed|blocked|unknown] [--private|--visibility public|private]
|
|
41
|
+
hadara evidence list --task <task-id> [--limit <n>] [--include-private] [--json]
|
|
42
|
+
hadara debt list [--json]
|
|
43
|
+
hadara debt show <id> [--json]
|
|
44
|
+
hadara tools list [--json]
|
|
45
|
+
hadara handoff update --task <task-id> [--summary <text>] [--next <text>]
|
|
46
|
+
hadara write preflight <command...> [--json]
|
|
47
|
+
hadara policy check-shell <command> [--mode readonly|assisted|trusted|auto|release]
|
|
48
|
+
hadara policy preflight-shell <command> [--mode readonly|assisted|trusted|auto|release] [--json]
|
|
49
|
+
hadara harness validate --task <task-id> [--level draft|done] [--json]
|
|
50
|
+
hadara harness replay <scenario.jsonl> [--json]
|
|
51
|
+
hadara hermes detect
|
|
52
|
+
hadara hermes export-context
|
|
53
|
+
hadara mcp serve [--enable-evidence-attach]
|
|
54
|
+
hadara status [--json]
|
|
55
|
+
hadara ops status [--json]
|
|
56
|
+
hadara run-state show [--json]
|
|
57
|
+
hadara run-state resume [--json] # read-only guidance; does not resume a process
|
|
58
|
+
hadara install plan [--platform linux|windows|wsl|usb|posix] [--source <path>] [--source-kind tarball|directory|portable-bundle] [--target <path>] [--usb-root <path>] [--prefix <path>] [--launcher <path>] [--mode dry-run|execute] [--json]
|
|
59
|
+
hadara smoke run [--profile core|release-readiness] [--json]
|
|
60
|
+
hadara smoke clean-checkout --execute [--workspace <dir>] [--task <task-id>] [--timeout <seconds>] [--keep-temp] [--no-evidence|--attach-evidence] [--json]
|
|
61
|
+
hadara package smoke [--dry-run|--execute] [--from <tarball|dir>] [--workspace <dir>] [--task <task-id>] [--timeout <seconds>] [--keep-temp] [--no-evidence|--attach-evidence] [--private-logs] [--json]
|
|
62
|
+
hadara release dry-run [--json]
|
|
63
|
+
hadara release publish [--mode dry-run|execute] [--approval-actor <name>] [--approval-reason <text>] [--confirm publish-deploy] [--json]
|
|
64
|
+
hadara release artifact --execute [--output <dir>] [--task <task-id>] [--attach-evidence] [--timeout <seconds>] [--keep-temp] [--json]
|
|
65
|
+
hadara release gate [--mode advisory|strict] [--json]
|
|
66
|
+
hadara dashboard serve [--host <host>] [--port <port>]
|
|
67
|
+
hadara tui [--snapshot] [--compact] [--width <n>] [--height <n>] [--json]
|
|
68
|
+
hadara run scaffold --task <task-id> --command <command> [--stdout <text>] [--stderr <text>] [--exit-code <n>] [--json]
|
|
69
|
+
hadara run [request] --script <script.json> [--task <task-id>] [--fake-shell-fixtures <fixtures.json>] [--mode readonly|assisted|trusted|auto|release] [--max-steps <n>] [--json]
|
|
70
|
+
|
|
71
|
+
Environment:
|
|
72
|
+
HADARA_HOME Portable/USB root. Defaults to current working directory.
|
|
73
|
+
HADARA_PROJECT_ROOT Project repo root. Defaults to current working directory.
|
|
74
|
+
`);
|
|
75
|
+
}
|
|
76
|
+
async function main(args = process.argv.slice(2)) {
|
|
77
|
+
const command = args[0];
|
|
78
|
+
if (!command || command === '--help' || command === '-h') {
|
|
79
|
+
printHelp();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const paths = (0, paths_1.resolveHadaraPaths)({ projectRoot: (0, args_1.getStringOption)(args, '--project') });
|
|
83
|
+
const jsonOutput = (0, args_1.getFlag)(args, '--json');
|
|
84
|
+
switch (command) {
|
|
85
|
+
case 'init': {
|
|
86
|
+
if ((0, init_1.handleInitCommand)({ args, projectRoot: paths.projectRoot }))
|
|
87
|
+
return;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'doctor': {
|
|
91
|
+
if ((0, doctor_1.handleDoctorCommand)({ paths, jsonOutput }))
|
|
92
|
+
return;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case 'task': {
|
|
96
|
+
if ((0, task_1.handleTaskCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
97
|
+
return;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case 'evidence': {
|
|
101
|
+
if ((0, evidence_1.handleEvidenceCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
102
|
+
return;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'tools': {
|
|
106
|
+
if ((0, tools_1.handleToolsCommand)({ args, jsonOutput }))
|
|
107
|
+
return;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case 'debt': {
|
|
111
|
+
if ((0, debt_1.handleDebtCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
112
|
+
return;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case 'handoff': {
|
|
116
|
+
if ((0, handoff_1.handleHandoffCommand)({ args, projectRoot: paths.projectRoot }))
|
|
117
|
+
return;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 'write': {
|
|
121
|
+
if ((0, write_preflight_1.handleWriteCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
122
|
+
return;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
case 'policy': {
|
|
126
|
+
if ((0, policy_1.handlePolicyCommand)({ args, jsonOutput }))
|
|
127
|
+
return;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case 'hermes': {
|
|
131
|
+
if ((0, hermes_1.handleHermesCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
132
|
+
return;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
case 'harness': {
|
|
136
|
+
if (await (0, harness_1.handleHarnessCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
137
|
+
return;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case 'mcp': {
|
|
141
|
+
if ((0, mcp_1.handleMcpCommand)({ args, projectRoot: paths.projectRoot }))
|
|
142
|
+
return;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case 'status': {
|
|
146
|
+
if ((0, status_1.handleStatusCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
147
|
+
return;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case 'dashboard': {
|
|
151
|
+
if ((0, dashboard_1.handleDashboardCommand)({ args, projectRoot: paths.projectRoot }))
|
|
152
|
+
return;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case 'tui': {
|
|
156
|
+
if ((0, tui_1.handleTuiCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
157
|
+
return;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case 'ops': {
|
|
161
|
+
if ((0, status_1.handleOpsCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
162
|
+
return;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case 'run': {
|
|
166
|
+
if (await (0, run_1.handleRunCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
167
|
+
return;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
case 'run-state': {
|
|
171
|
+
if ((0, run_state_1.handleRunStateCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
172
|
+
return;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case 'release': {
|
|
176
|
+
if ((0, release_dry_run_1.handleReleaseDryRunCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
177
|
+
return;
|
|
178
|
+
if ((0, release_publish_1.handleReleasePublishCommand)({ args, paths, jsonOutput }))
|
|
179
|
+
return;
|
|
180
|
+
if ((0, release_artifact_1.handleReleaseArtifactCommand)({ args, paths, jsonOutput }))
|
|
181
|
+
return;
|
|
182
|
+
if ((0, release_gate_1.handleReleaseGateCommand)({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
183
|
+
return;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case 'install': {
|
|
187
|
+
if ((0, install_1.handleInstallCommand)({ args, jsonOutput }))
|
|
188
|
+
return;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
case 'smoke': {
|
|
192
|
+
if ((0, smoke_1.handleSmokeCommand)({ args, paths, jsonOutput }))
|
|
193
|
+
return;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case 'package': {
|
|
197
|
+
if ((0, package_smoke_1.handlePackageCommand)({ args, paths, jsonOutput }))
|
|
198
|
+
return;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
printHelp();
|
|
203
|
+
process.exitCode = 1;
|
|
204
|
+
}
|
|
205
|
+
if (require.main === module) {
|
|
206
|
+
const args = process.argv.slice(2);
|
|
207
|
+
main(args).catch((error) => {
|
|
208
|
+
if (args.includes('--json')) {
|
|
209
|
+
console.log(JSON.stringify((0, errors_1.createCliErrorReport)(args, error), null, 2));
|
|
210
|
+
process.exitCode = (0, errors_1.cliErrorExitCode)(args, error);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
console.error(`[HADARA] ERROR: ${error instanceof Error ? error.message : String(error)}`);
|
|
214
|
+
process.exitCode = (0, errors_1.cliErrorExitCode)(args, error);
|
|
215
|
+
});
|
|
216
|
+
}
|
package/dist/cli/mcp.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleMcpCommand = handleMcpCommand;
|
|
4
|
+
const server_1 = require("../mcp/server");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handleMcpCommand(input) {
|
|
7
|
+
const sub = input.args[1];
|
|
8
|
+
if (sub !== 'serve')
|
|
9
|
+
return false;
|
|
10
|
+
(0, server_1.startMcpStdioServer)({
|
|
11
|
+
projectRoot: input.projectRoot,
|
|
12
|
+
enableEvidenceAttach: (0, args_1.getFlag)(input.args, '--enable-evidence-attach')
|
|
13
|
+
});
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlePackageCommand = handlePackageCommand;
|
|
4
|
+
const package_smoke_1 = require("../services/package-smoke");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handlePackageCommand(input) {
|
|
7
|
+
if (input.args[0] !== 'package' || input.args[1] !== 'smoke')
|
|
8
|
+
return false;
|
|
9
|
+
const options = {
|
|
10
|
+
paths: input.paths,
|
|
11
|
+
dryRun: !(0, args_1.getFlag)(input.args, '--execute'),
|
|
12
|
+
from: (0, args_1.getStringOption)(input.args, '--from'),
|
|
13
|
+
workspace: (0, args_1.getStringOption)(input.args, '--workspace'),
|
|
14
|
+
taskId: (0, args_1.getStringOption)(input.args, '--task'),
|
|
15
|
+
attachEvidence: (0, args_1.getFlag)(input.args, '--attach-evidence'),
|
|
16
|
+
noEvidence: (0, args_1.getFlag)(input.args, '--no-evidence'),
|
|
17
|
+
keepTemp: (0, args_1.getFlag)(input.args, '--keep-temp'),
|
|
18
|
+
privateLogs: (0, args_1.getFlag)(input.args, '--private-logs'),
|
|
19
|
+
timeoutSeconds: (0, args_1.getIntegerOption)(input.args, '--timeout', { min: 1 })
|
|
20
|
+
};
|
|
21
|
+
const report = (0, args_1.getFlag)(input.args, '--execute') ? (0, package_smoke_1.createPackageSmokeLocalReport)(options) : (0, package_smoke_1.createPackageSmokeDryRunReport)(options);
|
|
22
|
+
if (input.jsonOutput) {
|
|
23
|
+
console.log(JSON.stringify(report, null, 2));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.log(`${report.ok ? 'passed' : 'failed'} | package smoke | ${report.mode}`);
|
|
27
|
+
for (const step of report.steps) {
|
|
28
|
+
console.log(`${step.status} | ${step.label} | ${step.summary}`);
|
|
29
|
+
}
|
|
30
|
+
for (const issue of report.issues) {
|
|
31
|
+
console.log(`${issue.severity} | ${issue.code} | ${issue.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (!report.ok)
|
|
35
|
+
process.exitCode = 6;
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createPolicyCheckReport = void 0;
|
|
4
|
+
exports.extractPolicyCommandText = extractPolicyCommandText;
|
|
5
|
+
var policy_service_1 = require("../services/policy-service");
|
|
6
|
+
Object.defineProperty(exports, "createPolicyCheckReport", { enumerable: true, get: function () { return policy_service_1.createPolicyCheckReport; } });
|
|
7
|
+
function extractPolicyCommandText(args, mode) {
|
|
8
|
+
const commandParts = [];
|
|
9
|
+
for (let index = 2; index < args.length; index += 1) {
|
|
10
|
+
const value = args[index];
|
|
11
|
+
if (value === '--json')
|
|
12
|
+
continue;
|
|
13
|
+
if (value === '--mode') {
|
|
14
|
+
index += 1;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (value === mode && args[index - 1] === '--mode')
|
|
18
|
+
continue;
|
|
19
|
+
commandParts.push(value);
|
|
20
|
+
}
|
|
21
|
+
return commandParts.join(' ').trim();
|
|
22
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlePolicyCommand = handlePolicyCommand;
|
|
4
|
+
const policy_1 = require("../policy/policy");
|
|
5
|
+
const policy_service_1 = require("../services/policy-service");
|
|
6
|
+
const args_1 = require("./args");
|
|
7
|
+
const policy_json_1 = require("./policy-json");
|
|
8
|
+
function handlePolicyCommand(input) {
|
|
9
|
+
const sub = input.args[1];
|
|
10
|
+
if (sub === 'check-shell') {
|
|
11
|
+
const mode = (0, policy_1.parsePermissionMode)((0, args_1.getStringOption)(input.args, '--mode', 'assisted') ?? 'assisted');
|
|
12
|
+
const commandText = (0, policy_json_1.extractPolicyCommandText)(input.args, mode);
|
|
13
|
+
if (!commandText)
|
|
14
|
+
throw new Error('policy check-shell requires <command>');
|
|
15
|
+
const report = (0, policy_json_1.createPolicyCheckReport)(commandText, mode);
|
|
16
|
+
if (input.jsonOutput) {
|
|
17
|
+
console.log(JSON.stringify(report, null, 2));
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
console.log(JSON.stringify(report.decision, null, 2));
|
|
21
|
+
}
|
|
22
|
+
if (!report.ok)
|
|
23
|
+
process.exitCode = 2;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (sub === 'preflight-shell') {
|
|
27
|
+
const mode = (0, policy_1.parsePermissionMode)((0, args_1.getStringOption)(input.args, '--mode', 'assisted') ?? 'assisted');
|
|
28
|
+
const commandText = (0, policy_json_1.extractPolicyCommandText)(input.args, mode);
|
|
29
|
+
if (!commandText)
|
|
30
|
+
throw new Error('policy preflight-shell requires <command>');
|
|
31
|
+
const report = (0, policy_service_1.createPolicyEvaluateReport)(commandText, mode);
|
|
32
|
+
if (input.jsonOutput) {
|
|
33
|
+
console.log(JSON.stringify(report, null, 2));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(`[HADARA] Shell preflight: ${report.execution.status} (${report.decision.risk}) - ${report.decision.reason}`);
|
|
37
|
+
}
|
|
38
|
+
if (!report.ok)
|
|
39
|
+
process.exitCode = 2;
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleReleaseArtifactCommand = handleReleaseArtifactCommand;
|
|
4
|
+
const release_artifact_evidence_1 = require("../services/release-artifact-evidence");
|
|
5
|
+
const release_artifact_1 = require("../services/release-artifact");
|
|
6
|
+
const args_1 = require("./args");
|
|
7
|
+
function handleReleaseArtifactCommand(input) {
|
|
8
|
+
if (input.args[0] !== 'release' || input.args[1] !== 'artifact')
|
|
9
|
+
return false;
|
|
10
|
+
const report = (0, release_artifact_1.createReleaseArtifactReport)({
|
|
11
|
+
paths: input.paths,
|
|
12
|
+
execute: (0, args_1.getFlag)(input.args, '--execute'),
|
|
13
|
+
output: (0, args_1.getStringOption)(input.args, '--output'),
|
|
14
|
+
keepTemp: (0, args_1.getFlag)(input.args, '--keep-temp'),
|
|
15
|
+
timeoutSeconds: (0, args_1.getIntegerOption)(input.args, '--timeout', { min: 1 })
|
|
16
|
+
});
|
|
17
|
+
const taskId = (0, args_1.getStringOption)(input.args, '--task');
|
|
18
|
+
const attachEvidence = (0, args_1.getFlag)(input.args, '--attach-evidence');
|
|
19
|
+
if (attachEvidence && !taskId) {
|
|
20
|
+
throw new Error('release artifact --attach-evidence requires --task <task-id>');
|
|
21
|
+
}
|
|
22
|
+
const attachment = attachEvidence && taskId
|
|
23
|
+
? (0, release_artifact_evidence_1.attachReleaseArtifactEvidence)({
|
|
24
|
+
projectRoot: input.paths.projectRoot,
|
|
25
|
+
taskId,
|
|
26
|
+
summary: 'hadara release artifact --execute --attach-evidence --json generated tarball/checksum/manifest metadata, retained public report artifact, and emitted hadara.releaseArtifact.v1.',
|
|
27
|
+
report
|
|
28
|
+
})
|
|
29
|
+
: undefined;
|
|
30
|
+
if (input.jsonOutput) {
|
|
31
|
+
console.log(JSON.stringify(attachment ? { ...report, attachedEvidence: attachment } : report, null, 2));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(`${report.ok ? 'passed' : 'failed'} | release artifact | ${report.output.retention}`);
|
|
35
|
+
if (attachment)
|
|
36
|
+
console.log(`evidence | ${attachment.evidence.taskId} | ${attachment.evidence.evidencePath ?? 'no-artifact'}`);
|
|
37
|
+
for (const artifact of report.artifacts) {
|
|
38
|
+
console.log(`${artifact.kind} | ${artifact.fileName} | ${artifact.hash ?? 'no-hash'}`);
|
|
39
|
+
}
|
|
40
|
+
for (const issue of report.issues) {
|
|
41
|
+
console.log(`${issue.severity} | ${issue.code} | ${issue.message}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!report.ok)
|
|
45
|
+
process.exitCode = 6;
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleReleaseDryRunCommand = handleReleaseDryRunCommand;
|
|
4
|
+
const release_dry_run_1 = require("../services/release-dry-run");
|
|
5
|
+
function handleReleaseDryRunCommand(input) {
|
|
6
|
+
if (input.args[0] !== 'release' || input.args[1] !== 'dry-run')
|
|
7
|
+
return false;
|
|
8
|
+
const report = (0, release_dry_run_1.createReleaseDryRunReport)(input.projectRoot);
|
|
9
|
+
if (input.jsonOutput) {
|
|
10
|
+
console.log(JSON.stringify(report, null, 2));
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
console.log(`${report.ok ? 'passed' : 'failed'} | release dry-run | ${report.current.packageVersion}`);
|
|
14
|
+
for (const check of report.checks) {
|
|
15
|
+
console.log(`${check.status} | ${check.name} | ${check.summary}`);
|
|
16
|
+
}
|
|
17
|
+
for (const issue of report.issues) {
|
|
18
|
+
console.log(`${issue.severity} | ${issue.code} | ${issue.message}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (!report.ok)
|
|
22
|
+
process.exitCode = 6;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleReleaseGateCommand = handleReleaseGateCommand;
|
|
4
|
+
const operational_debt_1 = require("../services/operational-debt");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handleReleaseGateCommand(input) {
|
|
7
|
+
if (input.args[0] !== 'release' || input.args[1] !== 'gate')
|
|
8
|
+
return false;
|
|
9
|
+
const mode = parseReleaseGateMode(input.args);
|
|
10
|
+
const report = (0, operational_debt_1.createReleaseGateReport)(input.projectRoot, mode);
|
|
11
|
+
if (input.jsonOutput) {
|
|
12
|
+
console.log(JSON.stringify(report, null, 2));
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
for (const check of report.checks) {
|
|
16
|
+
console.log(`${check.status} | ${check.name} | ${check.summary}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (!report.ok)
|
|
20
|
+
process.exitCode = 6;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
function parseReleaseGateMode(args) {
|
|
24
|
+
const value = (0, args_1.getStringOption)(args, '--mode', 'advisory');
|
|
25
|
+
if (value === 'advisory' || value === 'strict')
|
|
26
|
+
return value;
|
|
27
|
+
throw new Error(`unsupported release gate mode: ${value}`);
|
|
28
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleReleasePublishCommand = handleReleasePublishCommand;
|
|
4
|
+
const release_publish_1 = require("../services/release-publish");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handleReleasePublishCommand(input) {
|
|
7
|
+
if (input.args[0] !== 'release' || input.args[1] !== 'publish')
|
|
8
|
+
return false;
|
|
9
|
+
const mode = parseMode(input.args);
|
|
10
|
+
const report = (0, release_publish_1.createReleasePublishReport)({
|
|
11
|
+
projectRoot: input.paths.projectRoot,
|
|
12
|
+
auditDir: input.paths.auditDir,
|
|
13
|
+
mode,
|
|
14
|
+
approvalActor: (0, args_1.getStringOption)(input.args, '--approval-actor'),
|
|
15
|
+
approvalReason: (0, args_1.getStringOption)(input.args, '--approval-reason'),
|
|
16
|
+
confirm: (0, args_1.getStringOption)(input.args, '--confirm')
|
|
17
|
+
});
|
|
18
|
+
if (input.jsonOutput) {
|
|
19
|
+
console.log(JSON.stringify(report, null, 2));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log(`${report.ok ? 'passed' : 'blocked'} | release publish | ${report.mode} | ${report.current.packageVersion}`);
|
|
23
|
+
for (const check of report.checks) {
|
|
24
|
+
console.log(`${check.status} | ${check.name} | ${check.summary}`);
|
|
25
|
+
}
|
|
26
|
+
for (const issue of report.issues) {
|
|
27
|
+
console.log(`${issue.severity} | ${issue.code} | ${issue.message}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!report.ok)
|
|
31
|
+
process.exitCode = 6;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function parseMode(args) {
|
|
35
|
+
if ((0, args_1.getFlag)(args, '--execute'))
|
|
36
|
+
return 'execute';
|
|
37
|
+
const mode = (0, args_1.getStringOption)(args, '--mode', 'dry-run');
|
|
38
|
+
if (mode === 'dry-run' || mode === 'execute')
|
|
39
|
+
return mode;
|
|
40
|
+
throw new Error(`unsupported release publish mode: ${mode}`);
|
|
41
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.scaffoldRunScenario = scaffoldRunScenario;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const fs_1 = require("../core/fs");
|
|
10
|
+
function scaffoldRunScenario(projectRoot, input) {
|
|
11
|
+
const scenarioDir = node_path_1.default.join(projectRoot, '.hadara', 'scenarios');
|
|
12
|
+
(0, fs_1.ensureDir)(scenarioDir);
|
|
13
|
+
const fileBase = `${safeScenarioPart(input.taskId)}-${safeScenarioPart(input.command)}`;
|
|
14
|
+
const scriptPath = node_path_1.default.join(scenarioDir, `${fileBase}.script.json`);
|
|
15
|
+
const fixturesPath = node_path_1.default.join(scenarioDir, `${fileBase}.fixtures.json`);
|
|
16
|
+
const matchText = `Run ${input.taskId} scaffolded command`;
|
|
17
|
+
const script = [
|
|
18
|
+
{
|
|
19
|
+
match: matchText,
|
|
20
|
+
response: JSON.stringify({ type: 'tool_request', tool: 'fake_shell', command: input.command }),
|
|
21
|
+
finishReason: 'tool_call'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
match: input.stdout,
|
|
25
|
+
response: `Scaffolded fake-shell command completed: ${input.command}`
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
const fixtures = {
|
|
29
|
+
[input.command]: {
|
|
30
|
+
exitCode: input.exitCode,
|
|
31
|
+
stdout: input.stdout,
|
|
32
|
+
stderr: input.stderr
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const portableScriptPath = toPortablePath(node_path_1.default.relative(projectRoot, scriptPath));
|
|
36
|
+
const portableFixturesPath = toPortablePath(node_path_1.default.relative(projectRoot, fixturesPath));
|
|
37
|
+
if (node_fs_1.default.existsSync(scriptPath)) {
|
|
38
|
+
throw new Error(`scenario already exists: ${portableScriptPath}`);
|
|
39
|
+
}
|
|
40
|
+
if (node_fs_1.default.existsSync(fixturesPath)) {
|
|
41
|
+
throw new Error(`scenario already exists: ${portableFixturesPath}`);
|
|
42
|
+
}
|
|
43
|
+
if (!(0, fs_1.writeFileIfMissing)(scriptPath, `${JSON.stringify(script, null, 2)}\n`)) {
|
|
44
|
+
throw new Error(`scenario already exists: ${portableScriptPath}`);
|
|
45
|
+
}
|
|
46
|
+
if (!(0, fs_1.writeFileIfMissing)(fixturesPath, `${JSON.stringify(fixtures, null, 2)}\n`)) {
|
|
47
|
+
throw new Error(`scenario already exists: ${portableFixturesPath}`);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
schemaVersion: 'hadara.run.scaffold.v1',
|
|
51
|
+
command: 'run.scaffold',
|
|
52
|
+
ok: true,
|
|
53
|
+
taskId: input.taskId,
|
|
54
|
+
shellCommand: input.command,
|
|
55
|
+
scriptPath: portableScriptPath,
|
|
56
|
+
fixturesPath: portableFixturesPath
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function safeScenarioPart(value) {
|
|
60
|
+
return value
|
|
61
|
+
.toLowerCase()
|
|
62
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
63
|
+
.replace(/^-+|-+$/g, '')
|
|
64
|
+
.slice(0, 80) || 'scenario';
|
|
65
|
+
}
|
|
66
|
+
function toPortablePath(value) {
|
|
67
|
+
return value.split(node_path_1.default.sep).join('/');
|
|
68
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleRunStateCommand = handleRunStateCommand;
|
|
4
|
+
const active_run_state_1 = require("../services/active-run-state");
|
|
5
|
+
function handleRunStateCommand(input) {
|
|
6
|
+
if (input.args[0] !== 'run-state')
|
|
7
|
+
return false;
|
|
8
|
+
const sub = input.args[1];
|
|
9
|
+
if (sub !== 'show' && sub !== 'resume')
|
|
10
|
+
return false;
|
|
11
|
+
if (sub === 'resume') {
|
|
12
|
+
const report = (0, active_run_state_1.createActiveRunResumeReport)(input.projectRoot);
|
|
13
|
+
if (input.jsonOutput) {
|
|
14
|
+
console.log(JSON.stringify(report, null, 2));
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
console.log(formatResumeText(report));
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
const report = (0, active_run_state_1.safeCreateActiveRunProjection)(input.projectRoot);
|
|
21
|
+
if (input.jsonOutput) {
|
|
22
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
console.log(formatProjectionText(report));
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
function formatProjectionText(report) {
|
|
29
|
+
if (!report.activeRun)
|
|
30
|
+
return '[HADARA] Active run: none';
|
|
31
|
+
return [
|
|
32
|
+
'[HADARA] Active run',
|
|
33
|
+
`task: ${report.activeRun.taskId}`,
|
|
34
|
+
`status: ${report.activeRun.status}`,
|
|
35
|
+
`capsule: ${report.activeRun.capsule || report.path}`,
|
|
36
|
+
`next: ${report.resume?.nextAction ?? 'none'}`
|
|
37
|
+
].join('\n');
|
|
38
|
+
}
|
|
39
|
+
function formatResumeText(report) {
|
|
40
|
+
return ['[HADARA] Active run resume', report.resumePrompt.summary, ...report.resumePrompt.nextActions.map((action) => `- ${action}`)].join('\n');
|
|
41
|
+
}
|