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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCliErrorReport = createCliErrorReport;
|
|
4
|
+
exports.cliErrorExitCode = cliErrorExitCode;
|
|
5
|
+
exports.cliErrorCode = cliErrorCode;
|
|
6
|
+
const args_1 = require("./args");
|
|
7
|
+
function createCliErrorReport(args, error) {
|
|
8
|
+
return {
|
|
9
|
+
schemaVersion: 'hadara.cli.error.v1',
|
|
10
|
+
command: 'cli.error',
|
|
11
|
+
ok: false,
|
|
12
|
+
input: {
|
|
13
|
+
...(args[0] ? { command: args[0] } : {}),
|
|
14
|
+
...(args[1] && !args[1].startsWith('--') ? { subcommand: args[1] } : {})
|
|
15
|
+
},
|
|
16
|
+
issues: [
|
|
17
|
+
{
|
|
18
|
+
severity: 'error',
|
|
19
|
+
code: cliErrorCode(error),
|
|
20
|
+
message: error instanceof Error ? error.message : String(error)
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function cliErrorExitCode(args, error) {
|
|
26
|
+
if (isGlobalParseError(error))
|
|
27
|
+
return 1;
|
|
28
|
+
const command = args[0];
|
|
29
|
+
if (command === 'policy')
|
|
30
|
+
return 2;
|
|
31
|
+
if (command === 'doctor')
|
|
32
|
+
return 7;
|
|
33
|
+
if (command === 'run' || command === 'evidence' || command === 'harness')
|
|
34
|
+
return 6;
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
function cliErrorCode(error) {
|
|
38
|
+
if (error instanceof args_1.CliArgsError)
|
|
39
|
+
return error.code;
|
|
40
|
+
const maybeCode = typeof error === 'object' && error !== null && 'code' in error ? error.code : undefined;
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
if (typeof maybeCode === 'string' && maybeCode.startsWith('WORKSPACE_'))
|
|
43
|
+
return maybeCode;
|
|
44
|
+
if (/unsupported permission mode/.test(message))
|
|
45
|
+
return 'PERMISSION_MODE_UNSUPPORTED';
|
|
46
|
+
if (/unsupported evidence result/.test(message))
|
|
47
|
+
return 'EVIDENCE_RESULT_UNSUPPORTED';
|
|
48
|
+
if (/unsupported evidence visibility/.test(message))
|
|
49
|
+
return 'EVIDENCE_VISIBILITY_UNSUPPORTED';
|
|
50
|
+
if (/unsupported harness validation level/.test(message))
|
|
51
|
+
return 'HARNESS_LEVEL_UNSUPPORTED';
|
|
52
|
+
return 'CLI_COMMAND_FAILED';
|
|
53
|
+
}
|
|
54
|
+
function isGlobalParseError(error) {
|
|
55
|
+
if (!(error instanceof args_1.CliArgsError))
|
|
56
|
+
return false;
|
|
57
|
+
return error.message.startsWith('--project ');
|
|
58
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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.createEvidenceCollectReport = createEvidenceCollectReport;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const evidence_1 = require("../evidence/evidence");
|
|
10
|
+
const task_capsule_1 = require("../task/task-capsule");
|
|
11
|
+
const workspace_1 = require("../core/workspace");
|
|
12
|
+
function createEvidenceCollectReport(projectRoot, input) {
|
|
13
|
+
const task = (0, task_capsule_1.listTaskCapsules)(projectRoot).find((item) => item.id === input.taskId);
|
|
14
|
+
if (!task) {
|
|
15
|
+
return {
|
|
16
|
+
schemaVersion: 'hadara.evidence.collect.v1',
|
|
17
|
+
command: 'evidence.collect',
|
|
18
|
+
ok: false,
|
|
19
|
+
issues: [
|
|
20
|
+
{
|
|
21
|
+
severity: 'error',
|
|
22
|
+
code: 'TASK_NOT_FOUND',
|
|
23
|
+
message: `Task Capsule not found: ${input.taskId}`
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
let markdownPath;
|
|
29
|
+
try {
|
|
30
|
+
markdownPath = (0, evidence_1.appendEvidence)(projectRoot, {
|
|
31
|
+
taskId: input.taskId,
|
|
32
|
+
kind: input.kind,
|
|
33
|
+
path: input.path,
|
|
34
|
+
summary: input.summary,
|
|
35
|
+
result: input.result,
|
|
36
|
+
visibility: input.visibility
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof workspace_1.WorkspaceFileError || error instanceof evidence_1.EvidenceArtifactPolicyError) {
|
|
41
|
+
return {
|
|
42
|
+
schemaVersion: 'hadara.evidence.collect.v1',
|
|
43
|
+
command: 'evidence.collect',
|
|
44
|
+
ok: false,
|
|
45
|
+
issues: [
|
|
46
|
+
{
|
|
47
|
+
severity: 'error',
|
|
48
|
+
code: error.code,
|
|
49
|
+
message: error.message
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
const indexRecord = readLastEvidenceIndexRecord(task.dir);
|
|
57
|
+
return {
|
|
58
|
+
schemaVersion: 'hadara.evidence.collect.v1',
|
|
59
|
+
command: 'evidence.collect',
|
|
60
|
+
ok: true,
|
|
61
|
+
evidence: {
|
|
62
|
+
...indexRecord,
|
|
63
|
+
markdownPath: toPortablePath(node_path_1.default.relative(projectRoot, markdownPath))
|
|
64
|
+
},
|
|
65
|
+
issues: []
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function readLastEvidenceIndexRecord(taskDir) {
|
|
69
|
+
const indexPath = node_path_1.default.join(taskDir, 'evidence.jsonl');
|
|
70
|
+
const lines = node_fs_1.default.readFileSync(indexPath, 'utf8').trim().split(/\r?\n/);
|
|
71
|
+
return JSON.parse(lines.at(-1) ?? '{}');
|
|
72
|
+
}
|
|
73
|
+
function toPortablePath(value) {
|
|
74
|
+
return value.split(node_path_1.default.sep).join('/');
|
|
75
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleEvidenceCommand = handleEvidenceCommand;
|
|
4
|
+
exports.parseEvidenceKind = parseEvidenceKind;
|
|
5
|
+
exports.parseEvidenceResult = parseEvidenceResult;
|
|
6
|
+
exports.parseEvidenceVisibility = parseEvidenceVisibility;
|
|
7
|
+
const evidence_1 = require("../evidence/evidence");
|
|
8
|
+
const evidence_json_1 = require("./evidence-json");
|
|
9
|
+
const evidence_list_1 = require("../services/evidence-list");
|
|
10
|
+
const args_1 = require("./args");
|
|
11
|
+
function handleEvidenceCommand(input) {
|
|
12
|
+
const sub = input.args[1];
|
|
13
|
+
if (sub === 'list') {
|
|
14
|
+
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
15
|
+
const report = (0, evidence_list_1.createEvidenceListReport)(input.projectRoot, {
|
|
16
|
+
taskId,
|
|
17
|
+
limit: (0, args_1.getIntegerOption)(input.args, '--limit', { min: 0, max: 500 }),
|
|
18
|
+
includePrivate: (0, args_1.getFlag)(input.args, '--include-private')
|
|
19
|
+
});
|
|
20
|
+
if (input.jsonOutput) {
|
|
21
|
+
console.log(JSON.stringify(report, null, 2));
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
for (const record of report.records) {
|
|
25
|
+
console.log(`${record.time} | ${record.kind} | ${record.result} | ${record.visibility} | ${record.summary}`);
|
|
26
|
+
}
|
|
27
|
+
for (const issue of report.issues) {
|
|
28
|
+
console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!report.ok)
|
|
32
|
+
process.exitCode = 6;
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (sub !== 'collect')
|
|
36
|
+
return false;
|
|
37
|
+
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
38
|
+
const kind = parseEvidenceKind((0, args_1.getStringOption)(input.args, '--kind', 'note') ?? 'note');
|
|
39
|
+
const summary = (0, args_1.getStringOption)(input.args, '--summary') ?? 'Manual evidence collection placeholder.';
|
|
40
|
+
const result = parseEvidenceResult((0, args_1.getStringOption)(input.args, '--result', 'unknown') ?? 'unknown');
|
|
41
|
+
const evidenceFile = (0, args_1.getStringOption)(input.args, '--path');
|
|
42
|
+
const visibility = parseEvidenceVisibility((0, args_1.getStringOption)(input.args, '--visibility', 'public') ?? 'public', (0, args_1.getFlag)(input.args, '--private'));
|
|
43
|
+
if (input.jsonOutput) {
|
|
44
|
+
const report = (0, evidence_json_1.createEvidenceCollectReport)(input.projectRoot, {
|
|
45
|
+
taskId,
|
|
46
|
+
kind,
|
|
47
|
+
path: evidenceFile,
|
|
48
|
+
summary,
|
|
49
|
+
result,
|
|
50
|
+
visibility
|
|
51
|
+
});
|
|
52
|
+
console.log(JSON.stringify(report, null, 2));
|
|
53
|
+
if (!report.ok)
|
|
54
|
+
process.exitCode = 6;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const filePath = (0, evidence_1.appendEvidence)(input.projectRoot, { taskId, kind, path: evidenceFile, summary, result, visibility });
|
|
58
|
+
console.log(`[HADARA] Evidence updated: ${filePath}`);
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
function parseEvidenceKind(value) {
|
|
63
|
+
if (['test-log', 'command-log', 'diff-summary', 'screenshot', 'note'].includes(value)) {
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`unsupported evidence kind: ${value}`);
|
|
67
|
+
}
|
|
68
|
+
function parseEvidenceResult(value) {
|
|
69
|
+
if (value === 'passed' || value === 'failed' || value === 'blocked' || value === 'unknown') {
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`unsupported evidence result: ${value}`);
|
|
73
|
+
}
|
|
74
|
+
function parseEvidenceVisibility(value, privateFlag = false) {
|
|
75
|
+
if (privateFlag)
|
|
76
|
+
return 'private';
|
|
77
|
+
if (value === 'public' || value === 'private')
|
|
78
|
+
return value;
|
|
79
|
+
throw new Error(`unsupported evidence visibility: ${value}`);
|
|
80
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleHandoffCommand = handleHandoffCommand;
|
|
4
|
+
const handoff_1 = require("../handoff/handoff");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handleHandoffCommand(input) {
|
|
7
|
+
const sub = input.args[1];
|
|
8
|
+
if (sub !== 'update')
|
|
9
|
+
return false;
|
|
10
|
+
const taskId = (0, args_1.getStringOption)(input.args, '--task');
|
|
11
|
+
const summary = (0, args_1.getStringOption)(input.args, '--summary');
|
|
12
|
+
const nextStep = (0, args_1.getStringOption)(input.args, '--next');
|
|
13
|
+
const filePath = (0, handoff_1.updateHandoff)({ projectRoot: input.projectRoot, taskId, summary, nextStep });
|
|
14
|
+
console.log(`[HADARA] Handoff updated: ${filePath}`);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleHarnessCommand = handleHarnessCommand;
|
|
4
|
+
exports.parseHarnessValidationLevel = parseHarnessValidationLevel;
|
|
5
|
+
const replay_1 = require("../harness/replay");
|
|
6
|
+
const harness_service_1 = require("../services/harness-service");
|
|
7
|
+
const args_1 = require("./args");
|
|
8
|
+
async function handleHarnessCommand(input) {
|
|
9
|
+
const sub = input.args[1];
|
|
10
|
+
if (sub === 'validate') {
|
|
11
|
+
const taskId = (0, args_1.getRequiredStringOption)(input.args, '--task');
|
|
12
|
+
const level = parseHarnessValidationLevel((0, args_1.getStringOption)(input.args, '--level', 'draft') ?? 'draft');
|
|
13
|
+
const result = (0, harness_service_1.createHarnessValidateReport)(input.projectRoot, taskId, { level });
|
|
14
|
+
if (input.jsonOutput) {
|
|
15
|
+
console.log(JSON.stringify(result, null, 2));
|
|
16
|
+
}
|
|
17
|
+
else if (result.ok) {
|
|
18
|
+
console.log(`[HADARA] Harness validation passed: ${result.task.id}`);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
console.log(`[HADARA] Harness validation failed: ${result.task.id}`);
|
|
22
|
+
for (const issue of result.issues) {
|
|
23
|
+
console.log(`- ${issue.code}: ${issue.message}${issue.path ? ` (${issue.path})` : ''}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (!result.ok)
|
|
27
|
+
process.exitCode = 6;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (sub === 'replay') {
|
|
31
|
+
const scenarioPath = input.args[2];
|
|
32
|
+
if (!scenarioPath || scenarioPath.startsWith('--'))
|
|
33
|
+
throw new Error('harness replay requires <scenario.jsonl>');
|
|
34
|
+
const result = await (0, replay_1.replayScenario)(input.projectRoot, scenarioPath);
|
|
35
|
+
if (input.jsonOutput) {
|
|
36
|
+
console.log(JSON.stringify(result, null, 2));
|
|
37
|
+
}
|
|
38
|
+
else if (result.ok) {
|
|
39
|
+
console.log(`[HADARA] Harness replay passed: ${result.scenario}`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(`[HADARA] Harness replay failed: ${result.scenario}`);
|
|
43
|
+
for (const issue of result.issues) {
|
|
44
|
+
console.log(`- ${issue.code}: ${issue.message}${issue.line ? ` (line ${issue.line})` : ''}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!result.ok)
|
|
48
|
+
process.exitCode = 6;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function parseHarnessValidationLevel(value) {
|
|
54
|
+
if (value === 'draft' || value === 'done')
|
|
55
|
+
return value;
|
|
56
|
+
throw new Error(`unsupported harness validation level: ${value}`);
|
|
57
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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.createHermesDetectReport = createHermesDetectReport;
|
|
7
|
+
exports.createHermesExportContextReport = createHermesExportContextReport;
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const context_export_1 = require("../hermes/context-export");
|
|
10
|
+
function createHermesDetectReport(projectRoot) {
|
|
11
|
+
return {
|
|
12
|
+
schemaVersion: 'hadara.hermes.detect.v1',
|
|
13
|
+
command: 'hermes.detect',
|
|
14
|
+
ok: true,
|
|
15
|
+
contextFiles: (0, context_export_1.detectHermesContext)(projectRoot)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function createHermesExportContextReport(projectRoot) {
|
|
19
|
+
const outputPath = (0, context_export_1.exportHadaraContext)(projectRoot);
|
|
20
|
+
return {
|
|
21
|
+
schemaVersion: 'hadara.hermes.export-context.v1',
|
|
22
|
+
command: 'hermes.export-context',
|
|
23
|
+
ok: true,
|
|
24
|
+
output: {
|
|
25
|
+
path: toPortablePath(node_path_1.default.relative(projectRoot, outputPath))
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function toPortablePath(value) {
|
|
30
|
+
return value.split(node_path_1.default.sep).join('/');
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleHermesCommand = handleHermesCommand;
|
|
4
|
+
const context_export_1 = require("../hermes/context-export");
|
|
5
|
+
const hermes_json_1 = require("./hermes-json");
|
|
6
|
+
function handleHermesCommand(input) {
|
|
7
|
+
const sub = input.args[1];
|
|
8
|
+
if (sub === 'detect') {
|
|
9
|
+
if (input.jsonOutput) {
|
|
10
|
+
console.log(JSON.stringify((0, hermes_json_1.createHermesDetectReport)(input.projectRoot), null, 2));
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
console.log(JSON.stringify((0, context_export_1.detectHermesContext)(input.projectRoot), null, 2));
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
if (sub === 'export-context') {
|
|
18
|
+
if (input.jsonOutput) {
|
|
19
|
+
console.log(JSON.stringify((0, hermes_json_1.createHermesExportContextReport)(input.projectRoot), null, 2));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const filePath = (0, context_export_1.exportHadaraContext)(input.projectRoot);
|
|
23
|
+
console.log(`[HADARA] Exported Hermes/Harness context: ${filePath}`);
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
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.initProject = initProject;
|
|
7
|
+
exports.parseInitProfile = parseInitProfile;
|
|
8
|
+
exports.handleInitCommand = handleInitCommand;
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const paths_1 = require("../core/paths");
|
|
11
|
+
const fs_1 = require("../core/fs");
|
|
12
|
+
const audit_1 = require("../core/audit");
|
|
13
|
+
const args_1 = require("./args");
|
|
14
|
+
function initProject(projectRoot, profile = 'minimal') {
|
|
15
|
+
const normalizedProfile = parseInitProfile(profile);
|
|
16
|
+
const paths = (0, paths_1.resolveHadaraPaths)({ projectRoot });
|
|
17
|
+
for (const dir of [
|
|
18
|
+
paths.dataRoot,
|
|
19
|
+
paths.configDir,
|
|
20
|
+
paths.secretsDir,
|
|
21
|
+
paths.sessionsDir,
|
|
22
|
+
paths.logsDir,
|
|
23
|
+
paths.auditDir,
|
|
24
|
+
paths.exportsDir,
|
|
25
|
+
paths.projectDocsDir,
|
|
26
|
+
paths.projectTasksDir,
|
|
27
|
+
paths.projectContextDir
|
|
28
|
+
]) {
|
|
29
|
+
(0, fs_1.ensureDir)(dir);
|
|
30
|
+
}
|
|
31
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'PROJECT_STATE.md'), '# PROJECT_STATE\n\nStatus: Bootstrap initialized.\nPhase: bootstrap-development.\n\n## Current Phase\n\nbootstrap-development\n');
|
|
32
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'TASK_BOARD.md'), '# TASK_BOARD\n\n| ID | Title | Status | Capsule | Notes |\n|---|---|---|---|---|\n');
|
|
33
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'AGENT_HANDOFF.md'), '# AGENT_HANDOFF\n\nRead PROJECT_STATE.md and TASK_BOARD.md before continuing.\n');
|
|
34
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'ARCHITECTURE.md'), createArchitectureDoc(normalizedProfile));
|
|
35
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'IMPLEMENTATION_SOP.md'), createImplementationSopDoc());
|
|
36
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'DEVELOPMENT_SLICES.md'), createDevelopmentSlicesDoc());
|
|
37
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'DECISIONS.md'), '# DECISIONS\n\n');
|
|
38
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'REFACTOR_LOG.md'), '# REFACTOR_LOG\n\n');
|
|
39
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'SECURITY_MODEL.md'), '# SECURITY_MODEL\n\nUse assisted mode by default.\n');
|
|
40
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'TEST_STRATEGY.md'), '# TEST_STRATEGY\n\nRun unit, contract, harness, security, and release smoke tests.\n');
|
|
41
|
+
if (normalizedProfile === 'full' || normalizedProfile === 'hadara-protocol') {
|
|
42
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'docs', 'ROADMAP.md'), createRoadmapDoc());
|
|
43
|
+
}
|
|
44
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'AGENTS.md'), '# AGENTS\n\nAgents must follow HADARA Task Capsule and Handoff Protocol.\n');
|
|
45
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, '.hermes.md'), '# Hermes Agent Context\n\nRead `.hadara/context/HADARA_CONTEXT.md` when available.\n');
|
|
46
|
+
(0, fs_1.writeFileIfMissing)(node_path_1.default.join(projectRoot, 'HERMES.md'), '# HERMES\n\nThis project is HADARA-compatible.\n');
|
|
47
|
+
(0, audit_1.writeAuditEvent)(paths.auditDir, {
|
|
48
|
+
actor: 'system',
|
|
49
|
+
event_type: 'init',
|
|
50
|
+
summary: `Initialized project at ${projectRoot} with ${normalizedProfile} profile`,
|
|
51
|
+
payload: { projectRoot, profile: normalizedProfile }
|
|
52
|
+
});
|
|
53
|
+
console.log(`[HADARA] Initialized project: ${projectRoot}`);
|
|
54
|
+
console.log(`[HADARA] Init profile: ${normalizedProfile}`);
|
|
55
|
+
}
|
|
56
|
+
function parseInitProfile(value) {
|
|
57
|
+
if (value === 'minimal' || value === 'full' || value === 'hadara-protocol')
|
|
58
|
+
return value;
|
|
59
|
+
throw new Error(`unsupported init profile: ${value}`);
|
|
60
|
+
}
|
|
61
|
+
function handleInitCommand(input) {
|
|
62
|
+
initProject(input.projectRoot, parseInitProfile((0, args_1.getStringOption)(input.args, '--profile', 'minimal') ?? 'minimal'));
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
function createArchitectureDoc(profile) {
|
|
66
|
+
return `# ARCHITECTURE
|
|
67
|
+
|
|
68
|
+
## Overview
|
|
69
|
+
|
|
70
|
+
This project was initialized with HADARA using the \`${profile}\` profile.
|
|
71
|
+
|
|
72
|
+
## Boundaries
|
|
73
|
+
|
|
74
|
+
- Keep project source, docs, and Task Capsules in the repository.
|
|
75
|
+
- Keep portable/local machine state under \`.hadara/local/\`.
|
|
76
|
+
- Do not commit secrets, private logs, or machine-local state.
|
|
77
|
+
|
|
78
|
+
## Current Components
|
|
79
|
+
|
|
80
|
+
- Task Capsules in \`tasks/T-*/\`.
|
|
81
|
+
- Evidence records in \`EVIDENCE.md\` and \`evidence.jsonl\`.
|
|
82
|
+
- Handoff state in \`docs/AGENT_HANDOFF.md\`.
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
function createImplementationSopDoc() {
|
|
86
|
+
return `# IMPLEMENTATION_SOP
|
|
87
|
+
|
|
88
|
+
## Session Start
|
|
89
|
+
|
|
90
|
+
1. Read \`docs/PROJECT_STATE.md\`.
|
|
91
|
+
2. Read \`docs/AGENT_HANDOFF.md\`.
|
|
92
|
+
3. Read \`docs/TASK_BOARD.md\`.
|
|
93
|
+
4. Pick or create one Task Capsule.
|
|
94
|
+
5. Read the active Task Capsule files before implementation.
|
|
95
|
+
|
|
96
|
+
## Implementation
|
|
97
|
+
|
|
98
|
+
1. Keep work inside one Task Capsule whenever possible.
|
|
99
|
+
2. Preserve the portable/project store boundary.
|
|
100
|
+
3. Make the smallest coherent change that satisfies acceptance criteria.
|
|
101
|
+
4. Update task-local docs when scope changes.
|
|
102
|
+
|
|
103
|
+
## Validation
|
|
104
|
+
|
|
105
|
+
1. Run relevant tests.
|
|
106
|
+
2. Run \`hadara harness validate --task <task-id> --json\`.
|
|
107
|
+
3. Record evidence in \`EVIDENCE.md\` and \`evidence.jsonl\`.
|
|
108
|
+
|
|
109
|
+
## Session End
|
|
110
|
+
|
|
111
|
+
1. Update Task Capsule status.
|
|
112
|
+
2. Update \`docs/TASK_BOARD.md\`.
|
|
113
|
+
3. Update \`docs/PROJECT_STATE.md\` when capability state changes.
|
|
114
|
+
4. Update \`docs/AGENT_HANDOFF.md\` before stopping.
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
function createDevelopmentSlicesDoc() {
|
|
118
|
+
return `# DEVELOPMENT_SLICES
|
|
119
|
+
|
|
120
|
+
HADARA development should proceed in small, evidence-backed slices.
|
|
121
|
+
|
|
122
|
+
| Order | Slice | Capsule | Purpose | Done Evidence |
|
|
123
|
+
|---|---|---|---|---|
|
|
124
|
+
| 1 | First validated task | TBD | Create a Task Capsule, implement a small change, and attach evidence. | Harness validation passes. |
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
function createRoadmapDoc() {
|
|
128
|
+
return `# ROADMAP
|
|
129
|
+
|
|
130
|
+
## Near Term
|
|
131
|
+
|
|
132
|
+
- Define the first Task Capsule.
|
|
133
|
+
- Attach evidence for meaningful checks.
|
|
134
|
+
- Keep handoff current between sessions.
|
|
135
|
+
|
|
136
|
+
## Deferred
|
|
137
|
+
|
|
138
|
+
- Dashboard read model.
|
|
139
|
+
- Real provider adapters.
|
|
140
|
+
- MCP server expansion.
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleInstallCommand = handleInstallCommand;
|
|
4
|
+
const install_plan_1 = require("../services/install-plan");
|
|
5
|
+
const args_1 = require("./args");
|
|
6
|
+
function handleInstallCommand(input) {
|
|
7
|
+
if (input.args[0] !== 'install' || input.args[1] !== 'plan')
|
|
8
|
+
return false;
|
|
9
|
+
const report = (0, install_plan_1.createInstallPlanReport)({
|
|
10
|
+
mode: (0, args_1.getStringOption)(input.args, '--mode', 'dry-run'),
|
|
11
|
+
platform: (0, args_1.getStringOption)(input.args, '--platform'),
|
|
12
|
+
source: (0, args_1.getStringOption)(input.args, '--source'),
|
|
13
|
+
sourceKind: (0, args_1.getStringOption)(input.args, '--source-kind'),
|
|
14
|
+
target: (0, args_1.getStringOption)(input.args, '--target'),
|
|
15
|
+
usbRoot: (0, args_1.getStringOption)(input.args, '--usb-root'),
|
|
16
|
+
prefix: (0, args_1.getStringOption)(input.args, '--prefix'),
|
|
17
|
+
launcher: (0, args_1.getStringOption)(input.args, '--launcher')
|
|
18
|
+
});
|
|
19
|
+
if (input.jsonOutput) {
|
|
20
|
+
console.log(JSON.stringify(report, null, 2));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.log(`${report.ok ? 'passed' : 'failed'} | install plan | ${report.platform} | ${report.mode}`);
|
|
24
|
+
for (const action of report.actions) {
|
|
25
|
+
console.log(`${action.wouldWrite ? 'would-write' : 'read'} | ${action.kind} | ${action.description}`);
|
|
26
|
+
}
|
|
27
|
+
for (const issue of report.issues) {
|
|
28
|
+
console.log(`${issue.severity} | ${issue.code} | ${issue.message}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!report.ok)
|
|
32
|
+
process.exitCode = 6;
|
|
33
|
+
return true;
|
|
34
|
+
}
|