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
|
@@ -0,0 +1,77 @@
|
|
|
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.createLegacyMutationBlockedReport = createLegacyMutationBlockedReport;
|
|
7
|
+
exports.printLegacyMutationBlockedReport = printLegacyMutationBlockedReport;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
function createLegacyMutationBlockedReport(projectRoot, command) {
|
|
11
|
+
const scaffoldPath = node_path_1.default.join(projectRoot, '.hadara', 'scaffold.json');
|
|
12
|
+
if (!node_fs_1.default.existsSync(scaffoldPath)) {
|
|
13
|
+
return report(command, null, {
|
|
14
|
+
severity: 'error',
|
|
15
|
+
code: 'HADARA_PROTOCOL_MISSING',
|
|
16
|
+
path: '.hadara/scaffold.json',
|
|
17
|
+
message: 'This project does not declare HADARA protocol metadata. 0.4 mutation commands are disabled.'
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(node_fs_1.default.readFileSync(scaffoldPath, 'utf8'));
|
|
22
|
+
if (parsed.hadaraProtocol === '0.4')
|
|
23
|
+
return null;
|
|
24
|
+
return report(command, typeof parsed.hadaraProtocol === 'string' ? parsed.hadaraProtocol : null, {
|
|
25
|
+
severity: 'error',
|
|
26
|
+
code: 'HADARA_PROTOCOL_UNSUPPORTED',
|
|
27
|
+
path: '.hadara/scaffold.json',
|
|
28
|
+
message: `.hadara/scaffold.json must declare hadaraProtocol "0.4" before running 0.4 mutation commands.`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return report(command, null, {
|
|
33
|
+
severity: 'error',
|
|
34
|
+
code: 'HADARA_PROTOCOL_UNSUPPORTED',
|
|
35
|
+
path: '.hadara/scaffold.json',
|
|
36
|
+
message: `.hadara/scaffold.json could not be parsed: ${error instanceof Error ? error.message : String(error)}`
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function printLegacyMutationBlockedReport(report, jsonOutput) {
|
|
41
|
+
if (jsonOutput) {
|
|
42
|
+
console.log(JSON.stringify(report, null, 2));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
console.log(`[HADARA] ${report.command} blocked: legacy or unsupported HADARA project`);
|
|
46
|
+
for (const issue of report.issues)
|
|
47
|
+
console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
|
|
48
|
+
}
|
|
49
|
+
function report(command, detectedProtocol, issue) {
|
|
50
|
+
return {
|
|
51
|
+
schemaVersion: 'hadara.legacyProjectBoundary.v1',
|
|
52
|
+
command,
|
|
53
|
+
ok: false,
|
|
54
|
+
mutationAllowed: false,
|
|
55
|
+
detectedProtocol,
|
|
56
|
+
supportedProtocol: '0.4',
|
|
57
|
+
issues: [
|
|
58
|
+
issue,
|
|
59
|
+
{
|
|
60
|
+
severity: 'error',
|
|
61
|
+
code: 'HADARA_LEGACY_PROJECT_MUTATION_BLOCKED',
|
|
62
|
+
path: '.hadara/scaffold.json',
|
|
63
|
+
message: `${command} is a 0.4 mutation command and will not write into a legacy or unsupported project.`
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
nextActions: [
|
|
67
|
+
{
|
|
68
|
+
label: 'Use the previous HADARA line for this project',
|
|
69
|
+
command: 'npx hadara@0.3.3 doctor --json'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
label: 'Initialize a new HADARA 0.4 project',
|
|
73
|
+
command: 'hadara init --json'
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
};
|
|
77
|
+
}
|
package/dist/cli/main.js
CHANGED
|
@@ -34,11 +34,33 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.normalizeGlobalArgs = normalizeGlobalArgs;
|
|
38
|
+
exports.main = main;
|
|
37
39
|
const paths_1 = require("../core/paths");
|
|
38
40
|
const args_1 = require("./args");
|
|
39
41
|
const errors_1 = require("./errors");
|
|
40
42
|
const help_1 = require("./help");
|
|
43
|
+
const GLOBAL_FLAGS = new Set(['--json']);
|
|
44
|
+
const GLOBAL_OPTIONS_WITH_VALUES = new Set(['--project']);
|
|
45
|
+
function normalizeGlobalArgs(args) {
|
|
46
|
+
let commandIndex = -1;
|
|
47
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
48
|
+
const value = args[index];
|
|
49
|
+
if (GLOBAL_FLAGS.has(value) || value === '--help' || value === '-h')
|
|
50
|
+
continue;
|
|
51
|
+
if (GLOBAL_OPTIONS_WITH_VALUES.has(value)) {
|
|
52
|
+
index += 1;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
commandIndex = index;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
if (commandIndex <= 0)
|
|
59
|
+
return args;
|
|
60
|
+
return [args[commandIndex], ...args.slice(commandIndex + 1), ...args.slice(0, commandIndex)];
|
|
61
|
+
}
|
|
41
62
|
async function main(args = process.argv.slice(2)) {
|
|
63
|
+
args = normalizeGlobalArgs(args);
|
|
42
64
|
const command = args[0];
|
|
43
65
|
if (!command || command === '--help' || command === '-h') {
|
|
44
66
|
console.log((0, help_1.renderDefaultHelp)());
|
|
@@ -101,6 +123,12 @@ async function main(args = process.argv.slice(2)) {
|
|
|
101
123
|
return;
|
|
102
124
|
break;
|
|
103
125
|
}
|
|
126
|
+
case 'validation': {
|
|
127
|
+
const { handleValidationCommand } = await Promise.resolve().then(() => __importStar(require('./validation')));
|
|
128
|
+
if (handleValidationCommand({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
129
|
+
return;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
104
132
|
case 'proof': {
|
|
105
133
|
const { handleProofCommand } = await Promise.resolve().then(() => __importStar(require('./proof')));
|
|
106
134
|
if (handleProofCommand({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
@@ -222,6 +250,9 @@ async function main(args = process.argv.slice(2)) {
|
|
|
222
250
|
break;
|
|
223
251
|
}
|
|
224
252
|
case 'release': {
|
|
253
|
+
const { handleReleaseCloseoutCommand } = await Promise.resolve().then(() => __importStar(require('./release-closeout')));
|
|
254
|
+
if (handleReleaseCloseoutCommand({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
255
|
+
return;
|
|
225
256
|
const { handleReleaseDryRunCommand } = await Promise.resolve().then(() => __importStar(require('./release-dry-run')));
|
|
226
257
|
if (handleReleaseDryRunCommand({ args, projectRoot: paths.projectRoot, jsonOutput }))
|
|
227
258
|
return;
|
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handlePackageCommand = handlePackageCommand;
|
|
4
|
+
const package_recycle_1 = require("../services/package-recycle");
|
|
4
5
|
const package_smoke_1 = require("../services/package-smoke");
|
|
5
6
|
const args_1 = require("./args");
|
|
6
7
|
function handlePackageCommand(input) {
|
|
7
|
-
if (input.args[0] !== 'package'
|
|
8
|
+
if (input.args[0] !== 'package')
|
|
9
|
+
return false;
|
|
10
|
+
if (input.args[1] === 'recycle') {
|
|
11
|
+
const report = (0, package_recycle_1.createPackageRecycleReport)({
|
|
12
|
+
paths: input.paths,
|
|
13
|
+
execute: (0, args_1.getFlag)(input.args, '--execute'),
|
|
14
|
+
packageSpecifier: (0, args_1.getStringOption)(input.args, '--package'),
|
|
15
|
+
expectedVersion: (0, args_1.getStringOption)(input.args, '--expected-version'),
|
|
16
|
+
workspace: (0, args_1.getStringOption)(input.args, '--workspace'),
|
|
17
|
+
taskId: (0, args_1.getStringOption)(input.args, '--task'),
|
|
18
|
+
attachEvidence: (0, args_1.getFlag)(input.args, '--attach-evidence'),
|
|
19
|
+
noEvidence: (0, args_1.getFlag)(input.args, '--no-evidence'),
|
|
20
|
+
keepTemp: (0, args_1.getFlag)(input.args, '--keep-temp'),
|
|
21
|
+
includeGraph: (0, args_1.getFlag)(input.args, '--include-graph'),
|
|
22
|
+
timeoutSeconds: (0, args_1.getIntegerOption)(input.args, '--timeout', { min: 1 })
|
|
23
|
+
});
|
|
24
|
+
if (input.jsonOutput) {
|
|
25
|
+
console.log(JSON.stringify(report, null, 2));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log(`${report.ok ? 'passed' : 'failed'} | package recycle | ${report.mode}`);
|
|
29
|
+
for (const step of report.steps) {
|
|
30
|
+
console.log(`${step.status} | ${step.label} | ${step.summary}`);
|
|
31
|
+
}
|
|
32
|
+
for (const issue of report.issues) {
|
|
33
|
+
console.log(`${issue.severity} | ${issue.code} | ${issue.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!report.ok)
|
|
37
|
+
process.exitCode = 6;
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (input.args[1] !== 'smoke')
|
|
8
41
|
return false;
|
|
9
42
|
const options = {
|
|
10
43
|
paths: input.paths,
|
|
@@ -5,9 +5,18 @@ const evidence_1 = require("../evidence/evidence");
|
|
|
5
5
|
const release_artifact_evidence_1 = require("../services/release-artifact-evidence");
|
|
6
6
|
const release_artifact_1 = require("../services/release-artifact");
|
|
7
7
|
const args_1 = require("./args");
|
|
8
|
+
const legacy_boundary_1 = require("./legacy-boundary");
|
|
8
9
|
function handleReleaseArtifactCommand(input) {
|
|
9
10
|
if (input.args[0] !== 'release' || input.args[1] !== 'artifact')
|
|
10
11
|
return false;
|
|
12
|
+
if ((0, args_1.getFlag)(input.args, '--execute')) {
|
|
13
|
+
const legacyReport = (0, legacy_boundary_1.createLegacyMutationBlockedReport)(input.paths.projectRoot, 'release.artifact');
|
|
14
|
+
if (legacyReport) {
|
|
15
|
+
(0, legacy_boundary_1.printLegacyMutationBlockedReport)(legacyReport, input.jsonOutput);
|
|
16
|
+
process.exitCode = 6;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
11
20
|
const report = (0, release_artifact_1.createReleaseArtifactReport)({
|
|
12
21
|
paths: input.paths,
|
|
13
22
|
execute: (0, args_1.getFlag)(input.args, '--execute'),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleReleaseCloseoutCommand = handleReleaseCloseoutCommand;
|
|
4
|
+
const release_closeout_1 = require("../services/release-closeout");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handleReleaseCloseoutCommand(input) {
|
|
7
|
+
if (input.args[0] !== 'release' || input.args[1] !== 'closeout')
|
|
8
|
+
return false;
|
|
9
|
+
const report = (0, release_closeout_1.createReleaseCloseoutReport)(input.projectRoot, {
|
|
10
|
+
version: (0, args_1.getStringOption)(input.args, '--version'),
|
|
11
|
+
taskId: (0, args_1.getStringOption)(input.args, '--task')
|
|
12
|
+
});
|
|
13
|
+
if (input.jsonOutput) {
|
|
14
|
+
console.log(JSON.stringify(report, null, 2));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.log((0, release_closeout_1.formatReleaseCloseoutReport)(report));
|
|
18
|
+
}
|
|
19
|
+
if (!report.ok)
|
|
20
|
+
process.exitCode = 6;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
@@ -3,10 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.handleReleasePublishCommand = handleReleasePublishCommand;
|
|
4
4
|
const release_publish_1 = require("../services/release-publish");
|
|
5
5
|
const args_1 = require("./args");
|
|
6
|
+
const legacy_boundary_1 = require("./legacy-boundary");
|
|
6
7
|
function handleReleasePublishCommand(input) {
|
|
7
8
|
if (input.args[0] !== 'release' || input.args[1] !== 'publish')
|
|
8
9
|
return false;
|
|
9
10
|
const mode = parseMode(input.args);
|
|
11
|
+
if (mode === 'execute') {
|
|
12
|
+
const legacyReport = (0, legacy_boundary_1.createLegacyMutationBlockedReport)(input.paths.projectRoot, 'release.publish');
|
|
13
|
+
if (legacyReport) {
|
|
14
|
+
(0, legacy_boundary_1.printLegacyMutationBlockedReport)(legacyReport, input.jsonOutput);
|
|
15
|
+
process.exitCode = 6;
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
10
19
|
const report = (0, release_publish_1.createReleasePublishReport)({
|
|
11
20
|
projectRoot: input.paths.projectRoot,
|
|
12
21
|
auditDir: input.paths.auditDir,
|
package/dist/cli/task.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.handleTaskCommand = handleTaskCommand;
|
|
4
4
|
exports.extractTaskCreateTitle = extractTaskCreateTitle;
|
|
5
5
|
const task_close_1 = require("../task/task-close");
|
|
6
|
-
const task_close_repair_plan_1 = require("../task/task-close-repair-plan");
|
|
7
6
|
const task_complete_flow_1 = require("../task/task-complete-flow");
|
|
8
7
|
const task_create_1 = require("../task/task-create");
|
|
9
8
|
const task_finalize_1 = require("../task/task-finalize");
|
|
@@ -15,10 +14,14 @@ const task_upgrade_scaffold_1 = require("../task/task-upgrade-scaffold");
|
|
|
15
14
|
const task_workbench_1 = require("../services/task-workbench");
|
|
16
15
|
const actor_1 = require("./actor");
|
|
17
16
|
const args_1 = require("./args");
|
|
17
|
+
const legacy_boundary_1 = require("./legacy-boundary");
|
|
18
18
|
const task_json_1 = require("./task-json");
|
|
19
19
|
function handleTaskCommand(input) {
|
|
20
|
+
const startedAtMs = Date.now();
|
|
20
21
|
const sub = input.args[1];
|
|
21
22
|
if (sub === 'create') {
|
|
23
|
+
if (blockLegacyMutation(input, 'task.create'))
|
|
24
|
+
return true;
|
|
22
25
|
const title = extractTaskCreateTitle(input.args);
|
|
23
26
|
if (!title)
|
|
24
27
|
throw new Error('task create requires a title');
|
|
@@ -74,6 +77,8 @@ function handleTaskCommand(input) {
|
|
|
74
77
|
return true;
|
|
75
78
|
}
|
|
76
79
|
if (sub === 'upgrade-scaffold') {
|
|
80
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'task.upgrade-scaffold'))
|
|
81
|
+
return true;
|
|
77
82
|
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
78
83
|
if (!id || id.startsWith('--'))
|
|
79
84
|
throw new Error('task upgrade-scaffold requires --task <task-id>');
|
|
@@ -91,6 +96,8 @@ function handleTaskCommand(input) {
|
|
|
91
96
|
return true;
|
|
92
97
|
}
|
|
93
98
|
if (sub === 'close') {
|
|
99
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'task.close'))
|
|
100
|
+
return true;
|
|
94
101
|
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
95
102
|
if (!id || id.startsWith('--'))
|
|
96
103
|
throw new Error('task close requires --task <task-id>');
|
|
@@ -112,11 +119,46 @@ function handleTaskCommand(input) {
|
|
|
112
119
|
process.exitCode = 6;
|
|
113
120
|
return true;
|
|
114
121
|
}
|
|
115
|
-
if (sub === '
|
|
122
|
+
if (sub === 'close-source') {
|
|
116
123
|
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
117
124
|
if (!id || id.startsWith('--'))
|
|
118
|
-
throw new Error('task
|
|
119
|
-
const report = (0,
|
|
125
|
+
throw new Error('task close-source requires --task <task-id>');
|
|
126
|
+
const report = (0, task_close_1.createTaskCloseSourceReport)(input.projectRoot, id);
|
|
127
|
+
if (input.jsonOutput) {
|
|
128
|
+
console.log(JSON.stringify(report, null, 2));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(`[HADARA] task close-source ${id}: ${report.ok ? 'ok' : 'issues'}`);
|
|
132
|
+
console.log(`sourceHash\t${report.sourceHash}`);
|
|
133
|
+
for (const unit of report.sourceUnits)
|
|
134
|
+
console.log(`${unit.closeSourceRole}\t${unit.kind}\t${unit.path}\t${unit.selector ?? ''}\t${unit.sha256}`);
|
|
135
|
+
for (const issue of report.issues)
|
|
136
|
+
console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
|
|
137
|
+
}
|
|
138
|
+
if (!report.ok)
|
|
139
|
+
process.exitCode = 6;
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (sub === 'status') {
|
|
143
|
+
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
144
|
+
if (!id || id.startsWith('--')) {
|
|
145
|
+
const report = (0, task_workbench_1.createTaskStatusSelectionReport)(input.projectRoot);
|
|
146
|
+
attachCliDiagnostics(report, startedAtMs, 'task.status');
|
|
147
|
+
if (input.jsonOutput) {
|
|
148
|
+
console.log(JSON.stringify(report, null, 2));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.log((0, task_workbench_1.formatTaskStatusSelectionReport)(report));
|
|
152
|
+
}
|
|
153
|
+
if (!report.ok)
|
|
154
|
+
process.exitCode = 6;
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
const detail = (0, args_1.getStringOption)(input.args, '--detail');
|
|
158
|
+
if (detail && detail !== 'fast' && detail !== 'full')
|
|
159
|
+
throw new Error('task status --detail must be fast or full');
|
|
160
|
+
const report = (0, task_workbench_1.createTaskWorkbenchReport)(input.projectRoot, id, new Date(), { detail: detail === 'full' ? 'full' : 'fast' });
|
|
161
|
+
attachCliDiagnostics(report, startedAtMs, 'task.status');
|
|
120
162
|
if (input.jsonOutput) {
|
|
121
163
|
console.log(JSON.stringify(report, null, 2));
|
|
122
164
|
}
|
|
@@ -128,6 +170,8 @@ function handleTaskCommand(input) {
|
|
|
128
170
|
return true;
|
|
129
171
|
}
|
|
130
172
|
if (sub === 'complete') {
|
|
173
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'task.complete'))
|
|
174
|
+
return true;
|
|
131
175
|
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
132
176
|
if (!id || id.startsWith('--'))
|
|
133
177
|
throw new Error('task complete requires --task <task-id>');
|
|
@@ -143,14 +187,19 @@ function handleTaskCommand(input) {
|
|
|
143
187
|
return true;
|
|
144
188
|
}
|
|
145
189
|
if (sub === 'finalize') {
|
|
190
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'task.finalize'))
|
|
191
|
+
return true;
|
|
146
192
|
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
147
193
|
if (!id || id.startsWith('--'))
|
|
148
194
|
throw new Error('task finalize requires --task <task-id>');
|
|
195
|
+
const executeRequested = (0, args_1.getFlag)(input.args, '--execute');
|
|
149
196
|
const report = (0, task_finalize_1.createTaskFinalizeReport)(input.projectRoot, id, {
|
|
150
|
-
executeRequested
|
|
197
|
+
executeRequested,
|
|
151
198
|
planHash: (0, args_1.getStringOption)(input.args, '--plan-hash'),
|
|
152
|
-
actor: (0, actor_1.getActorContextOption)(input.args)
|
|
199
|
+
actor: (0, actor_1.getActorContextOption)(input.args),
|
|
200
|
+
onProgress: executeRequested ? createTaskFinalizeProgressWriter(id) : undefined
|
|
153
201
|
});
|
|
202
|
+
attachCliDiagnostics(report, startedAtMs, 'task.finalize');
|
|
154
203
|
if (input.jsonOutput) {
|
|
155
204
|
console.log(JSON.stringify(report, null, 2));
|
|
156
205
|
}
|
|
@@ -176,22 +225,9 @@ function handleTaskCommand(input) {
|
|
|
176
225
|
process.exitCode = 6;
|
|
177
226
|
return true;
|
|
178
227
|
}
|
|
179
|
-
if (sub === 'close-repair-plan') {
|
|
180
|
-
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
181
|
-
if (!id || id.startsWith('--'))
|
|
182
|
-
throw new Error('task close-repair-plan requires --task <task-id>');
|
|
183
|
-
const report = (0, task_close_repair_plan_1.createTaskCloseRepairPlanReport)(input.projectRoot, id, { actor: (0, actor_1.getActorContextOption)(input.args) });
|
|
184
|
-
if (input.jsonOutput) {
|
|
185
|
-
console.log(JSON.stringify(report, null, 2));
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
console.log((0, task_close_repair_plan_1.formatTaskCloseRepairPlanReport)(report));
|
|
189
|
-
}
|
|
190
|
-
if (!report.ok)
|
|
191
|
-
process.exitCode = 6;
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
228
|
if (sub === 'finish') {
|
|
229
|
+
if ((0, args_1.getFlag)(input.args, '--execute') && blockLegacyMutation(input, 'task.finish'))
|
|
230
|
+
return true;
|
|
195
231
|
const id = (0, args_1.getStringOption)(input.args, '--task') ?? input.args[2];
|
|
196
232
|
if (!id || id.startsWith('--'))
|
|
197
233
|
throw new Error('task finish requires --task <task-id>');
|
|
@@ -245,6 +281,34 @@ function handleTaskCommand(input) {
|
|
|
245
281
|
}
|
|
246
282
|
return false;
|
|
247
283
|
}
|
|
284
|
+
function createTaskFinalizeProgressWriter(taskId) {
|
|
285
|
+
return (event) => {
|
|
286
|
+
const ok = event.ok === undefined ? '' : ` ok=${event.ok}`;
|
|
287
|
+
process.stderr.write(`[HADARA] task finalize ${taskId}: ${event.step} ${event.phase}${ok} - ${event.summary}\n`);
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function attachCliDiagnostics(report, startedAtMs, commandPath) {
|
|
291
|
+
const durationMs = Math.max(0, Date.now() - startedAtMs);
|
|
292
|
+
const slowThresholdMs = 10000;
|
|
293
|
+
const slow = durationMs >= slowThresholdMs;
|
|
294
|
+
report.diagnostics = {
|
|
295
|
+
generatedBy: 'cli',
|
|
296
|
+
commandPath,
|
|
297
|
+
durationMs,
|
|
298
|
+
slowThresholdMs,
|
|
299
|
+
slow,
|
|
300
|
+
...(slow ? { note: 'This command was slow enough to affect interactive agent UX; prefer narrower diagnostics or progress-aware follow-up work if this repeats.' } : {})
|
|
301
|
+
};
|
|
302
|
+
return report;
|
|
303
|
+
}
|
|
304
|
+
function blockLegacyMutation(input, command) {
|
|
305
|
+
const report = (0, legacy_boundary_1.createLegacyMutationBlockedReport)(input.projectRoot, command);
|
|
306
|
+
if (!report)
|
|
307
|
+
return false;
|
|
308
|
+
(0, legacy_boundary_1.printLegacyMutationBlockedReport)(report, input.jsonOutput);
|
|
309
|
+
process.exitCode = 6;
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
248
312
|
function extractTaskCreateTitle(args) {
|
|
249
313
|
const explicitTitle = (0, args_1.getStringOption)(args, '--title');
|
|
250
314
|
if (explicitTitle)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleValidationCommand = handleValidationCommand;
|
|
4
|
+
const validation_run_1 = require("../services/validation-run");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
const legacy_boundary_1 = require("./legacy-boundary");
|
|
7
|
+
function handleValidationCommand(input) {
|
|
8
|
+
const sub = input.args[1];
|
|
9
|
+
if (sub !== 'run')
|
|
10
|
+
return false;
|
|
11
|
+
if (blockLegacyMutation(input, 'validation.run'))
|
|
12
|
+
return true;
|
|
13
|
+
const separator = input.args.indexOf('--');
|
|
14
|
+
const commandArgs = separator >= 0 ? input.args.slice(separator + 1) : [];
|
|
15
|
+
const optionArgs = separator >= 0 ? input.args.slice(0, separator) : input.args;
|
|
16
|
+
const taskId = (0, args_1.getRequiredStringOption)(optionArgs, '--task');
|
|
17
|
+
const check = (0, args_1.getRequiredStringOption)(optionArgs, '--check');
|
|
18
|
+
const report = (0, validation_run_1.createValidationRunReport)(input.projectRoot, {
|
|
19
|
+
taskId,
|
|
20
|
+
check,
|
|
21
|
+
argv: commandArgs,
|
|
22
|
+
tags: resolutionTagsFromArgs(optionArgs),
|
|
23
|
+
timeoutMs: (0, args_1.getIntegerOption)(optionArgs, '--timeout-ms', { min: 1, max: 3_600_000 }),
|
|
24
|
+
updateTask: (0, args_1.getFlag)(optionArgs, '--update-task')
|
|
25
|
+
});
|
|
26
|
+
if (input.jsonOutput) {
|
|
27
|
+
console.log(JSON.stringify(report, null, 2));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
console.log(`[HADARA] validation run ${taskId}: ${report.result}`);
|
|
31
|
+
if (report.evidence)
|
|
32
|
+
console.log(`evidence=${report.evidence.id}`);
|
|
33
|
+
if (!report.taskValidationRow.updated)
|
|
34
|
+
console.log(`taskValidationRow=${report.taskValidationRow.mode}`);
|
|
35
|
+
for (const issue of report.issues)
|
|
36
|
+
console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
|
|
37
|
+
for (const action of report.nextActions)
|
|
38
|
+
console.log(`next=${action.command ?? action.message}`);
|
|
39
|
+
}
|
|
40
|
+
if (!report.ok)
|
|
41
|
+
process.exitCode = 6;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
function blockLegacyMutation(input, command) {
|
|
45
|
+
const report = (0, legacy_boundary_1.createLegacyMutationBlockedReport)(input.projectRoot, command);
|
|
46
|
+
if (!report)
|
|
47
|
+
return false;
|
|
48
|
+
(0, legacy_boundary_1.printLegacyMutationBlockedReport)(report, input.jsonOutput);
|
|
49
|
+
process.exitCode = 6;
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
function resolutionTagsFromArgs(args) {
|
|
53
|
+
const tags = [];
|
|
54
|
+
for (const id of getRepeatedStringOptions(args, '--resolves'))
|
|
55
|
+
tags.push(`resolves:${id}`);
|
|
56
|
+
for (const id of getRepeatedStringOptions(args, '--supersedes'))
|
|
57
|
+
tags.push(`supersedes:${id}`);
|
|
58
|
+
return tags.length > 0 ? tags : undefined;
|
|
59
|
+
}
|
|
60
|
+
function getRepeatedStringOptions(args, option) {
|
|
61
|
+
const values = [];
|
|
62
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
63
|
+
if (args[index] !== option)
|
|
64
|
+
continue;
|
|
65
|
+
const value = args[index + 1];
|
|
66
|
+
if (!value || value.startsWith('--'))
|
|
67
|
+
throw new Error(`missing value for ${option}`);
|
|
68
|
+
values.push(value);
|
|
69
|
+
}
|
|
70
|
+
return values;
|
|
71
|
+
}
|