@lannguyensi/harness 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +552 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/cli/add/index.d.ts +14 -0
- package/dist/cli/add/index.js +71 -0
- package/dist/cli/add/index.js.map +1 -0
- package/dist/cli/add/mutate.d.ts +39 -0
- package/dist/cli/add/mutate.js +36 -0
- package/dist/cli/add/mutate.js.map +1 -0
- package/dist/cli/adopt/derive.d.ts +38 -0
- package/dist/cli/adopt/derive.js +94 -0
- package/dist/cli/adopt/derive.js.map +1 -0
- package/dist/cli/adopt/index.d.ts +20 -0
- package/dist/cli/adopt/index.js +156 -0
- package/dist/cli/adopt/index.js.map +1 -0
- package/dist/cli/apply/apply.d.ts +49 -0
- package/dist/cli/apply/apply.js +333 -0
- package/dist/cli/apply/apply.js.map +1 -0
- package/dist/cli/apply/generate-memory-index.d.ts +17 -0
- package/dist/cli/apply/generate-memory-index.js +167 -0
- package/dist/cli/apply/generate-memory-index.js.map +1 -0
- package/dist/cli/apply/generate-settings.d.ts +15 -0
- package/dist/cli/apply/generate-settings.js +87 -0
- package/dist/cli/apply/generate-settings.js.map +1 -0
- package/dist/cli/apply/index.d.ts +1 -0
- package/dist/cli/apply/index.js +2 -0
- package/dist/cli/apply/index.js.map +1 -0
- package/dist/cli/audit.d.ts +36 -0
- package/dist/cli/audit.js +121 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/describe.d.ts +13 -0
- package/dist/cli/describe.js +26 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/diff/engine.d.ts +21 -0
- package/dist/cli/diff/engine.js +161 -0
- package/dist/cli/diff/engine.js.map +1 -0
- package/dist/cli/diff/git.d.ts +6 -0
- package/dist/cli/diff/git.js +32 -0
- package/dist/cli/diff/git.js.map +1 -0
- package/dist/cli/diff/index.d.ts +15 -0
- package/dist/cli/diff/index.js +39 -0
- package/dist/cli/diff/index.js.map +1 -0
- package/dist/cli/diff/since-apply.d.ts +57 -0
- package/dist/cli/diff/since-apply.js +255 -0
- package/dist/cli/diff/since-apply.js.map +1 -0
- package/dist/cli/doctor/format.d.ts +2 -0
- package/dist/cli/doctor/format.js +126 -0
- package/dist/cli/doctor/format.js.map +1 -0
- package/dist/cli/doctor/index.d.ts +14 -0
- package/dist/cli/doctor/index.js +281 -0
- package/dist/cli/doctor/index.js.map +1 -0
- package/dist/cli/doctor/types.d.ts +46 -0
- package/dist/cli/doctor/types.js +2 -0
- package/dist/cli/doctor/types.js.map +1 -0
- package/dist/cli/dry-run.d.ts +46 -0
- package/dist/cli/dry-run.js +168 -0
- package/dist/cli/dry-run.js.map +1 -0
- package/dist/cli/exit-codes.d.ts +10 -0
- package/dist/cli/exit-codes.js +15 -0
- package/dist/cli/exit-codes.js.map +1 -0
- package/dist/cli/explain.d.ts +14 -0
- package/dist/cli/explain.js +97 -0
- package/dist/cli/explain.js.map +1 -0
- package/dist/cli/export.d.ts +31 -0
- package/dist/cli/export.js +84 -0
- package/dist/cli/export.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +549 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init/index.d.ts +17 -0
- package/dist/cli/init/index.js +57 -0
- package/dist/cli/init/index.js.map +1 -0
- package/dist/cli/init/templates.d.ts +4 -0
- package/dist/cli/init/templates.js +175 -0
- package/dist/cli/init/templates.js.map +1 -0
- package/dist/cli/list.d.ts +12 -0
- package/dist/cli/list.js +118 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/loader.d.ts +24 -0
- package/dist/cli/loader.js +74 -0
- package/dist/cli/loader.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +6 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/policy/intercept.d.ts +34 -0
- package/dist/cli/policy/intercept.js +172 -0
- package/dist/cli/policy/intercept.js.map +1 -0
- package/dist/cli/remove/index.d.ts +18 -0
- package/dist/cli/remove/index.js +95 -0
- package/dist/cli/remove/index.js.map +1 -0
- package/dist/cli/remove/mutate.d.ts +9 -0
- package/dist/cli/remove/mutate.js +68 -0
- package/dist/cli/remove/mutate.js.map +1 -0
- package/dist/cli/validate/checks.d.ts +23 -0
- package/dist/cli/validate/checks.js +253 -0
- package/dist/cli/validate/checks.js.map +1 -0
- package/dist/cli/validate/index.d.ts +18 -0
- package/dist/cli/validate/index.js +50 -0
- package/dist/cli/validate/index.js.map +1 -0
- package/dist/cli/validate/types.d.ts +7 -0
- package/dist/cli/validate/types.js +5 -0
- package/dist/cli/validate/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/io/atomic-write.d.ts +8 -0
- package/dist/io/atomic-write.js +30 -0
- package/dist/io/atomic-write.js.map +1 -0
- package/dist/io/harness-lock.d.ts +33 -0
- package/dist/io/harness-lock.js +260 -0
- package/dist/io/harness-lock.js.map +1 -0
- package/dist/io/last-apply.d.ts +20 -0
- package/dist/io/last-apply.js +123 -0
- package/dist/io/last-apply.js.map +1 -0
- package/dist/io/lock.d.ts +11 -0
- package/dist/io/lock.js +33 -0
- package/dist/io/lock.js.map +1 -0
- package/dist/io/patch.d.ts +10 -0
- package/dist/io/patch.js +8 -0
- package/dist/io/patch.js.map +1 -0
- package/dist/io/restart-hints.d.ts +5 -0
- package/dist/io/restart-hints.js +59 -0
- package/dist/io/restart-hints.js.map +1 -0
- package/dist/io/three-state.d.ts +7 -0
- package/dist/io/three-state.js +20 -0
- package/dist/io/three-state.js.map +1 -0
- package/dist/io/validate-before-write.d.ts +12 -0
- package/dist/io/validate-before-write.js +23 -0
- package/dist/io/validate-before-write.js.map +1 -0
- package/dist/overrides/index.d.ts +2 -0
- package/dist/overrides/index.js +3 -0
- package/dist/overrides/index.js.map +1 -0
- package/dist/overrides/machines.d.ts +12 -0
- package/dist/overrides/machines.js +46 -0
- package/dist/overrides/machines.js.map +1 -0
- package/dist/overrides/merge.d.ts +6 -0
- package/dist/overrides/merge.js +173 -0
- package/dist/overrides/merge.js.map +1 -0
- package/dist/policies/duration.d.ts +5 -0
- package/dist/policies/duration.js +50 -0
- package/dist/policies/duration.js.map +1 -0
- package/dist/policies/extract.d.ts +50 -0
- package/dist/policies/extract.js +190 -0
- package/dist/policies/extract.js.map +1 -0
- package/dist/policies/index.d.ts +5 -0
- package/dist/policies/index.js +6 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/ledger-client.d.ts +39 -0
- package/dist/policies/ledger-client.js +378 -0
- package/dist/policies/ledger-client.js.map +1 -0
- package/dist/policies/requires.d.ts +44 -0
- package/dist/policies/requires.js +146 -0
- package/dist/policies/requires.js.map +1 -0
- package/dist/policies/timestamp.d.ts +14 -0
- package/dist/policies/timestamp.js +36 -0
- package/dist/policies/timestamp.js.map +1 -0
- package/dist/probes/mcp.d.ts +29 -0
- package/dist/probes/mcp.js +226 -0
- package/dist/probes/mcp.js.map +1 -0
- package/dist/probes/memory.d.ts +24 -0
- package/dist/probes/memory.js +89 -0
- package/dist/probes/memory.js.map +1 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/intercept.d.ts +53 -0
- package/dist/runtime/intercept.js +181 -0
- package/dist/runtime/intercept.js.map +1 -0
- package/dist/runtime/ledger-record.d.ts +43 -0
- package/dist/runtime/ledger-record.js +239 -0
- package/dist/runtime/ledger-record.js.map +1 -0
- package/dist/runtime/session-id.d.ts +10 -0
- package/dist/runtime/session-id.js +37 -0
- package/dist/runtime/session-id.js.map +1 -0
- package/dist/schema/extract.d.ts +5 -0
- package/dist/schema/extract.js +23 -0
- package/dist/schema/extract.js.map +1 -0
- package/dist/schema/grounding.d.ts +65 -0
- package/dist/schema/grounding.js +21 -0
- package/dist/schema/grounding.js.map +1 -0
- package/dist/schema/hooks.d.ts +86 -0
- package/dist/schema/hooks.js +42 -0
- package/dist/schema/hooks.js.map +1 -0
- package/dist/schema/index.d.ts +961 -0
- package/dist/schema/index.js +55 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/memory.d.ts +131 -0
- package/dist/schema/memory.js +38 -0
- package/dist/schema/memory.js.map +1 -0
- package/dist/schema/policies.d.ts +412 -0
- package/dist/schema/policies.js +53 -0
- package/dist/schema/policies.js.map +1 -0
- package/dist/schema/requires.d.ts +115 -0
- package/dist/schema/requires.js +57 -0
- package/dist/schema/requires.js.map +1 -0
- package/dist/schema/tools.d.ts +283 -0
- package/dist/schema/tools.js +66 -0
- package/dist/schema/tools.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/adopt/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type DriftedAsset } from "../../io/harness-lock.js";
|
|
2
|
+
import { type ThreeStateVerdict } from "../../io/three-state.js";
|
|
3
|
+
export declare const GENERATED_DIRNAME = "harness.generated";
|
|
4
|
+
export declare const SETTINGS_BASENAME = "settings.json";
|
|
5
|
+
export declare const MEMORY_BASENAME = "MEMORY.md";
|
|
6
|
+
export declare const MANIFEST_BASENAME = "harness.yaml";
|
|
7
|
+
export interface ApplyOptions {
|
|
8
|
+
configPath?: string;
|
|
9
|
+
homeDir?: string;
|
|
10
|
+
project?: string;
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
overwriteDrift?: boolean;
|
|
13
|
+
/** Test-injectable confirmation prompt; defaults to a stdin readline. */
|
|
14
|
+
prompt?: (message: string) => Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
export type ApplyOutcome = "no-changes" | "applied" | "drift-refuse" | "drift-discarded" | "would-apply";
|
|
17
|
+
export interface FileApplyOutcome {
|
|
18
|
+
basename: string;
|
|
19
|
+
path: string;
|
|
20
|
+
verdict: ThreeStateVerdict;
|
|
21
|
+
/** Unified diff, present when verdict is `drift-refuse`. */
|
|
22
|
+
diff?: string;
|
|
23
|
+
/** True when `expected !== onDiskCurrent` (whether or not we wrote). */
|
|
24
|
+
changed: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ApplyResult {
|
|
27
|
+
manifestPath: string;
|
|
28
|
+
generatedDir: string;
|
|
29
|
+
files: FileApplyOutcome[];
|
|
30
|
+
warnings: string[];
|
|
31
|
+
restartHints: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Locked assets whose on-disk SHA-256 has drifted since the lock was last
|
|
34
|
+
* written. Computed on every apply (when a lock exists), reported but
|
|
35
|
+
* not enforced: apply proceeds, the drift is surfaced as warning-style
|
|
36
|
+
* output, and the lock is rewritten with current SHAs at the end of the
|
|
37
|
+
* run. Wrap apply in a script that greps for `asset drift detected:` to
|
|
38
|
+
* upgrade to enforcement.
|
|
39
|
+
*/
|
|
40
|
+
lockDrift: DriftedAsset[];
|
|
41
|
+
outcome: ApplyOutcome;
|
|
42
|
+
written: boolean;
|
|
43
|
+
dryRun: boolean;
|
|
44
|
+
/** Path of the harness.lock that was (or would be) written. */
|
|
45
|
+
lockPath: string;
|
|
46
|
+
}
|
|
47
|
+
declare const DRIFT_HINT_MESSAGE = "run \"harness adopt <file>\" to capture changes, or re-run with --overwrite-drift to discard them";
|
|
48
|
+
export declare function apply(opts?: ApplyOptions): Promise<ApplyResult>;
|
|
49
|
+
export { DRIFT_HINT_MESSAGE };
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// `harness apply [--dry-run] [--overwrite-drift]`.
|
|
2
|
+
//
|
|
3
|
+
// Pipeline:
|
|
4
|
+
// 1. Load the effective manifest.
|
|
5
|
+
// 2. Generate expected runtime files: settings.json (Phase 3 #2),
|
|
6
|
+
// MEMORY.md index (Phase 3 #3).
|
|
7
|
+
// 3. Read `harness.generated/.last-apply` (Phase 3 #1) if present.
|
|
8
|
+
// 4. Read on-disk `harness.generated/<file>` if present.
|
|
9
|
+
// 5. If `harness.lock` exists, hash every locked asset / memory-dir
|
|
10
|
+
// Merkle and surface mismatches as `lockDrift` (Phase 3 #6,
|
|
11
|
+
// warn-only). Drift is reported on every code path including
|
|
12
|
+
// --dry-run so users can preview without writing.
|
|
13
|
+
// 6. Three-state-compare per file (Phase 3 #1):
|
|
14
|
+
// no-drift → write expected (overwrite is safe)
|
|
15
|
+
// safe-overwrite → write expected (no on-disk file existed)
|
|
16
|
+
// drift-refuse → refuse with diff + adopt-or-overwrite hint
|
|
17
|
+
// 7. `--overwrite-drift` requires literal `yes` confirmation before
|
|
18
|
+
// discarding on-disk changes; on confirm, treat refusals as
|
|
19
|
+
// safe-overwrite.
|
|
20
|
+
// 8. `--dry-run` prints the would-be diff + would-emit hints, exits 0
|
|
21
|
+
// without writing.
|
|
22
|
+
// 9. After successful write: refresh `.last-apply` (with a manifest
|
|
23
|
+
// snapshot for the next apply's restart-hint comparison), write
|
|
24
|
+
// `harness.lock` next to `harness.yaml`, emit restart hints. The
|
|
25
|
+
// idempotent no-op path also refreshes the lock when asset drift
|
|
26
|
+
// was detected so the drift report is not "sticky".
|
|
27
|
+
import * as crypto from "node:crypto";
|
|
28
|
+
import * as fs from "node:fs";
|
|
29
|
+
import * as os from "node:os";
|
|
30
|
+
import * as path from "node:path";
|
|
31
|
+
import * as readline from "node:readline/promises";
|
|
32
|
+
import { atomicWriteFile } from "../../io/atomic-write.js";
|
|
33
|
+
import { LOCK_BASENAME, buildLockEntries, computeDrift, readLock, writeLock, } from "../../io/harness-lock.js";
|
|
34
|
+
import { buildLastApply, readLastApply, sha256Hex, verifyLastApplyIntegrity, writeLastApply, } from "../../io/last-apply.js";
|
|
35
|
+
import { unifiedDiff } from "../../io/patch.js";
|
|
36
|
+
import { emitRestartHints } from "../../io/restart-hints.js";
|
|
37
|
+
import { compare } from "../../io/three-state.js";
|
|
38
|
+
import { parseManifest } from "../../schema/index.js";
|
|
39
|
+
import { EX_NOINPUT, HarnessExitError } from "../exit-codes.js";
|
|
40
|
+
import { loadManifest } from "../loader.js";
|
|
41
|
+
import { generateMemoryIndex } from "./generate-memory-index.js";
|
|
42
|
+
import { generateSettings } from "./generate-settings.js";
|
|
43
|
+
export const GENERATED_DIRNAME = "harness.generated";
|
|
44
|
+
export const SETTINGS_BASENAME = "settings.json";
|
|
45
|
+
export const MEMORY_BASENAME = "MEMORY.md";
|
|
46
|
+
export const MANIFEST_BASENAME = "harness.yaml";
|
|
47
|
+
const DRIFT_HINT_MESSAGE = 'run "harness adopt <file>" to capture changes, or re-run with --overwrite-drift to discard them';
|
|
48
|
+
function resolveManifestPath(opts) {
|
|
49
|
+
if (opts.configPath)
|
|
50
|
+
return path.resolve(opts.configPath);
|
|
51
|
+
return path.join(opts.homeDir ?? path.join(os.homedir(), ".claude"), MANIFEST_BASENAME);
|
|
52
|
+
}
|
|
53
|
+
// `harness.generated/` lives next to whichever manifest is in use. If the
|
|
54
|
+
// user passed `--config /repo/path/harness.yaml`, generated artefacts go to
|
|
55
|
+
// `/repo/path/harness.generated/` (NOT `~/.claude/harness.generated/`). This
|
|
56
|
+
// avoids the footgun of `harness apply --config <some-other-tree>` writing
|
|
57
|
+
// state into the user's global runtime directory.
|
|
58
|
+
function resolveGeneratedDir(opts, manifestPath) {
|
|
59
|
+
if (opts.homeDir !== undefined)
|
|
60
|
+
return path.join(opts.homeDir, GENERATED_DIRNAME);
|
|
61
|
+
return path.join(path.dirname(manifestPath), GENERATED_DIRNAME);
|
|
62
|
+
}
|
|
63
|
+
// Prompts must survive `harness apply | tee log` (the user still needs to
|
|
64
|
+
// see the question even when stdout is piped), so we write to stderr and
|
|
65
|
+
// read from stdin. Don't "fix" this back to stdout.
|
|
66
|
+
async function readlinePrompt(message) {
|
|
67
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
68
|
+
try {
|
|
69
|
+
return await rl.question(message);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
rl.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function buildExpectedFiles(manifest, opts) {
|
|
76
|
+
const settings = `${JSON.stringify(generateSettings(manifest), null, 2)}\n`;
|
|
77
|
+
const indexResult = generateMemoryIndex(manifest, {
|
|
78
|
+
...(opts.homeDir !== undefined ? { homeDir: opts.homeDir } : {}),
|
|
79
|
+
...(opts.project !== undefined ? { projectName: opts.project } : {}),
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
files: [
|
|
83
|
+
{ basename: SETTINGS_BASENAME, content: settings },
|
|
84
|
+
{ basename: MEMORY_BASENAME, content: indexResult.content },
|
|
85
|
+
],
|
|
86
|
+
warnings: indexResult.warnings,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function readOnDisk(filePath) {
|
|
90
|
+
try {
|
|
91
|
+
return fs.readFileSync(filePath, "utf8");
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function buildPrevManifestForHints(record) {
|
|
98
|
+
if (!record?.manifest)
|
|
99
|
+
return null;
|
|
100
|
+
// Reject a snapshot whose stored sha256 disagrees with the recorded
|
|
101
|
+
// content. Treats integrity failure as "no prev manifest" (silent: same
|
|
102
|
+
// surface as a baseline record without a manifest field), so a corrupted
|
|
103
|
+
// .last-apply does not produce confidently-wrong restart hints.
|
|
104
|
+
const integrity = verifyLastApplyIntegrity({
|
|
105
|
+
files: { manifest: record.manifest },
|
|
106
|
+
});
|
|
107
|
+
if (integrity.length > 0)
|
|
108
|
+
return null;
|
|
109
|
+
let parsed;
|
|
110
|
+
try {
|
|
111
|
+
parsed = JSON.parse(record.manifest.content);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
return parseManifest(parsed);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export async function apply(opts = {}) {
|
|
124
|
+
const manifestPath = resolveManifestPath(opts);
|
|
125
|
+
if (!fs.existsSync(manifestPath)) {
|
|
126
|
+
throw new HarnessExitError(`harness manifest not found at ${manifestPath}; run \`harness init\` first`, EX_NOINPUT);
|
|
127
|
+
}
|
|
128
|
+
const generatedDir = resolveGeneratedDir(opts, manifestPath);
|
|
129
|
+
const lockPath = path.join(path.dirname(manifestPath), LOCK_BASENAME);
|
|
130
|
+
const loaderOpts = {
|
|
131
|
+
configPath: manifestPath,
|
|
132
|
+
};
|
|
133
|
+
if (opts.homeDir !== undefined)
|
|
134
|
+
loaderOpts.homeDir = opts.homeDir;
|
|
135
|
+
if (opts.project !== undefined)
|
|
136
|
+
loaderOpts.project = opts.project;
|
|
137
|
+
const { manifest } = loadManifest(loaderOpts);
|
|
138
|
+
const { files: expected, warnings } = buildExpectedFiles(manifest, opts);
|
|
139
|
+
const lastApply = readLastApply(generatedDir);
|
|
140
|
+
// Asset-content drift detection (Phase 3 #6): if a previous apply wrote
|
|
141
|
+
// harness.lock, re-hash every locked asset / memory-dir Merkle and report
|
|
142
|
+
// mismatches. Warn-only: apply still proceeds and the lock is rewritten
|
|
143
|
+
// at the end of the run. Users wanting enforcement wrap apply in a script
|
|
144
|
+
// that greps for `asset drift detected:`.
|
|
145
|
+
//
|
|
146
|
+
// We compute against the *previous* lock (read here, before the manifest
|
|
147
|
+
// is consulted to build the new lock). An asset removed from the manifest
|
|
148
|
+
// in this same apply still surfaces if it drifted — the reportable event
|
|
149
|
+
// is "the file on disk diverged from what was last-known", regardless of
|
|
150
|
+
// whether the manifest still references it.
|
|
151
|
+
const previousLock = readLock(lockPath);
|
|
152
|
+
const lockDrift = previousLock !== null ? computeDrift(previousLock) : [];
|
|
153
|
+
const fileOutcomes = [];
|
|
154
|
+
let anyDriftRefuse = false;
|
|
155
|
+
let anyChanged = false;
|
|
156
|
+
for (const f of expected) {
|
|
157
|
+
const target = path.join(generatedDir, f.basename);
|
|
158
|
+
const onDisk = readOnDisk(target);
|
|
159
|
+
const lastAppliedContent = lastApply?.files[f.basename]?.content ?? null;
|
|
160
|
+
const verdict = compare({
|
|
161
|
+
manifestExpected: f.content,
|
|
162
|
+
lastApplied: lastAppliedContent,
|
|
163
|
+
onDiskCurrent: onDisk,
|
|
164
|
+
});
|
|
165
|
+
const outcome = {
|
|
166
|
+
basename: f.basename,
|
|
167
|
+
path: target,
|
|
168
|
+
verdict,
|
|
169
|
+
changed: f.content !== onDisk,
|
|
170
|
+
};
|
|
171
|
+
if (verdict === "drift-refuse") {
|
|
172
|
+
anyDriftRefuse = true;
|
|
173
|
+
outcome.diff = unifiedDiff({
|
|
174
|
+
fileName: f.basename,
|
|
175
|
+
oldText: lastAppliedContent ?? "",
|
|
176
|
+
newText: onDisk ?? "",
|
|
177
|
+
oldHeader: "last-apply",
|
|
178
|
+
newHeader: "on-disk",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
if (outcome.changed)
|
|
182
|
+
anyChanged = true;
|
|
183
|
+
fileOutcomes.push(outcome);
|
|
184
|
+
}
|
|
185
|
+
if (anyDriftRefuse && !opts.overwriteDrift) {
|
|
186
|
+
return {
|
|
187
|
+
manifestPath,
|
|
188
|
+
generatedDir,
|
|
189
|
+
files: fileOutcomes,
|
|
190
|
+
warnings,
|
|
191
|
+
restartHints: [],
|
|
192
|
+
outcome: "drift-refuse",
|
|
193
|
+
lockDrift,
|
|
194
|
+
written: false,
|
|
195
|
+
dryRun: opts.dryRun ?? false,
|
|
196
|
+
lockPath,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (anyDriftRefuse && opts.overwriteDrift) {
|
|
200
|
+
const promptFn = opts.prompt ?? readlinePrompt;
|
|
201
|
+
const answer = await promptFn("Type 'yes' to discard on-disk hand-edits and overwrite with manifest-expected content: ");
|
|
202
|
+
// Case-insensitive comparison: a user typing `YES` or `Yes` is clearly
|
|
203
|
+
// confirming. We still reject `y` per spec ("literal yes, not y").
|
|
204
|
+
if (answer.trim().toLowerCase() !== "yes") {
|
|
205
|
+
return {
|
|
206
|
+
manifestPath,
|
|
207
|
+
generatedDir,
|
|
208
|
+
files: fileOutcomes,
|
|
209
|
+
warnings,
|
|
210
|
+
restartHints: [],
|
|
211
|
+
outcome: "drift-discarded",
|
|
212
|
+
lockDrift,
|
|
213
|
+
written: false,
|
|
214
|
+
dryRun: opts.dryRun ?? false,
|
|
215
|
+
lockPath,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// Confirmed: continue to the write phase. The per-file `verdict` field
|
|
219
|
+
// remains `drift-refuse` so callers can still see which files would
|
|
220
|
+
// have been refused; the wrapper outcome is `applied` post-write.
|
|
221
|
+
}
|
|
222
|
+
// Restart hints: compare the previous-apply's manifest snapshot to the
|
|
223
|
+
// current effective manifest.
|
|
224
|
+
const prevManifest = buildPrevManifestForHints(lastApply);
|
|
225
|
+
const restartHints = prevManifest ? emitRestartHints(prevManifest, manifest) : [];
|
|
226
|
+
if (opts.dryRun) {
|
|
227
|
+
return {
|
|
228
|
+
manifestPath,
|
|
229
|
+
generatedDir,
|
|
230
|
+
files: fileOutcomes,
|
|
231
|
+
warnings,
|
|
232
|
+
restartHints,
|
|
233
|
+
outcome: anyChanged ? "would-apply" : "no-changes",
|
|
234
|
+
lockDrift,
|
|
235
|
+
written: false,
|
|
236
|
+
dryRun: true,
|
|
237
|
+
lockPath,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
if (!anyChanged && lastApply !== null) {
|
|
241
|
+
// Idempotent no-op for generated files. If asset-content drift was
|
|
242
|
+
// detected against harness.lock, rewrite the lock now with current
|
|
243
|
+
// SHAs so the drift is not "sticky": the user sees the drift line
|
|
244
|
+
// once, the next apply is clean. Without this, every subsequent
|
|
245
|
+
// apply re-reports the same drift forever until something else in
|
|
246
|
+
// the manifest changes.
|
|
247
|
+
if (lockDrift.length > 0) {
|
|
248
|
+
const refreshed = buildLockEntries(manifest, {
|
|
249
|
+
...(opts.homeDir !== undefined ? { homeDir: opts.homeDir } : {}),
|
|
250
|
+
...(opts.project !== undefined ? { projectName: opts.project } : {}),
|
|
251
|
+
});
|
|
252
|
+
writeLock(lockPath, refreshed);
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
manifestPath,
|
|
256
|
+
generatedDir,
|
|
257
|
+
files: fileOutcomes,
|
|
258
|
+
warnings,
|
|
259
|
+
restartHints,
|
|
260
|
+
outcome: "no-changes",
|
|
261
|
+
lockDrift,
|
|
262
|
+
written: false,
|
|
263
|
+
dryRun: false,
|
|
264
|
+
lockPath,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
fs.mkdirSync(generatedDir, { recursive: true });
|
|
268
|
+
for (const f of expected) {
|
|
269
|
+
const target = path.join(generatedDir, f.basename);
|
|
270
|
+
atomicWriteFile(target, f.content);
|
|
271
|
+
}
|
|
272
|
+
// Compute lock + memory-dir snapshot BEFORE writing .last-apply so the
|
|
273
|
+
// record is built once and persisted atomically. A previous version of
|
|
274
|
+
// this code wrote .last-apply twice (once without memoryDirs, then again
|
|
275
|
+
// with it), which produced a half-state if the process died between
|
|
276
|
+
// writes: the next `--memory-detail` diff would have seen every on-disk
|
|
277
|
+
// .md as "added" against an empty index. Single write closes that gap.
|
|
278
|
+
const lockEntries = buildLockEntries(manifest, {
|
|
279
|
+
...(opts.homeDir !== undefined ? { homeDir: opts.homeDir } : {}),
|
|
280
|
+
...(opts.project !== undefined ? { projectName: opts.project } : {}),
|
|
281
|
+
});
|
|
282
|
+
const newRecord = buildLastApply(Object.fromEntries(expected.map((f) => [f.basename, f.content])));
|
|
283
|
+
const manifestSnapshotJson = JSON.stringify(manifest);
|
|
284
|
+
newRecord.manifest = {
|
|
285
|
+
sha256: sha256Hex(manifestSnapshotJson),
|
|
286
|
+
content: manifestSnapshotJson,
|
|
287
|
+
};
|
|
288
|
+
const memoryDirSnapshots = collectMemoryDirSnapshots(lockEntries);
|
|
289
|
+
if (Object.keys(memoryDirSnapshots).length > 0) {
|
|
290
|
+
newRecord.memoryDirs = memoryDirSnapshots;
|
|
291
|
+
}
|
|
292
|
+
writeLastApply(generatedDir, newRecord);
|
|
293
|
+
writeLock(lockPath, lockEntries);
|
|
294
|
+
return {
|
|
295
|
+
manifestPath,
|
|
296
|
+
generatedDir,
|
|
297
|
+
files: fileOutcomes,
|
|
298
|
+
warnings,
|
|
299
|
+
restartHints,
|
|
300
|
+
outcome: "applied",
|
|
301
|
+
lockDrift,
|
|
302
|
+
written: true,
|
|
303
|
+
dryRun: false,
|
|
304
|
+
lockPath,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
function sha256OfFile(filePath) {
|
|
308
|
+
return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
|
|
309
|
+
}
|
|
310
|
+
function collectMemoryDirSnapshots(lockEntries) {
|
|
311
|
+
const out = {};
|
|
312
|
+
for (const e of lockEntries) {
|
|
313
|
+
if (e.kind !== "memory-dir")
|
|
314
|
+
continue;
|
|
315
|
+
const fileHashes = {};
|
|
316
|
+
let dirents;
|
|
317
|
+
try {
|
|
318
|
+
dirents = fs.readdirSync(e.path, { withFileTypes: true });
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
for (const d of dirents) {
|
|
324
|
+
if (!d.isFile() || !d.name.endsWith(".md"))
|
|
325
|
+
continue;
|
|
326
|
+
fileHashes[d.name] = sha256OfFile(path.join(e.path, d.name));
|
|
327
|
+
}
|
|
328
|
+
out[e.path] = { sha256: e.sha256, fileHashes };
|
|
329
|
+
}
|
|
330
|
+
return out;
|
|
331
|
+
}
|
|
332
|
+
export { DRIFT_HINT_MESSAGE };
|
|
333
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/cli/apply/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Manifest } from "../../schema/index.js";
|
|
2
|
+
export interface MemoryIndexEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
basename: string;
|
|
6
|
+
directory: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GenerateMemoryIndexResult {
|
|
9
|
+
content: string;
|
|
10
|
+
entries: MemoryIndexEntry[];
|
|
11
|
+
warnings: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface GenerateMemoryIndexOptions {
|
|
14
|
+
homeDir?: string;
|
|
15
|
+
projectName?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function generateMemoryIndex(manifest: Manifest, opts?: GenerateMemoryIndexOptions): GenerateMemoryIndexResult;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Generate `harness.generated/MEMORY.md`: the index that lists every memory
|
|
2
|
+
// file the router would surface, derived from `memory.directories[]`. Memory
|
|
3
|
+
// markdown files themselves stay user-owned (per ROADMAP non-goals); only
|
|
4
|
+
// the index is generated.
|
|
5
|
+
//
|
|
6
|
+
// Output format mirrors the canonical hand-curated MEMORY.md convention:
|
|
7
|
+
//
|
|
8
|
+
// - [Name](filename.md) — description
|
|
9
|
+
//
|
|
10
|
+
// Empty directories produce a header-only output; missing or unreadable
|
|
11
|
+
// frontmatter surfaces in the `warnings[]` array on the result so the
|
|
12
|
+
// caller (Phase 3 #4 `harness apply`) can render a doctor-style report
|
|
13
|
+
// without aborting.
|
|
14
|
+
//
|
|
15
|
+
// Frontmatter shape mirrors agent-memory's `MemoryFrontmatter`: `name` and
|
|
16
|
+
// `type` are required (matches the canonical loader at
|
|
17
|
+
// `agent-memory/packages/memory-router/src/memory/loader.ts`, which rejects
|
|
18
|
+
// on `!fm.name || !fm.type`). `description` is recommended (its absence is
|
|
19
|
+
// a warning but not a hard skip). `topics` and other fields are not
|
|
20
|
+
// surfaced in the index.
|
|
21
|
+
//
|
|
22
|
+
// `name` and `description` are passed through verbatim into the markdown
|
|
23
|
+
// output. The user authors their own frontmatter, so we trust it; no
|
|
24
|
+
// escaping is performed for `[`, `]`, `(`, `)`, or backticks. A maliciously
|
|
25
|
+
// crafted `name` would produce broken markdown but not security issues
|
|
26
|
+
// (the index is read by humans and by tools that already accept arbitrary
|
|
27
|
+
// markdown).
|
|
28
|
+
import * as fs from "node:fs";
|
|
29
|
+
import * as os from "node:os";
|
|
30
|
+
import * as path from "node:path";
|
|
31
|
+
import { parse as parseYaml } from "yaml";
|
|
32
|
+
// Mirror the canonical loader's regex (CRLF-tolerant) so files saved on
|
|
33
|
+
// Windows or by editors that normalise to CRLF parse identically here.
|
|
34
|
+
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
35
|
+
function expandHome(p, homeDir) {
|
|
36
|
+
const home = homeDir ?? os.homedir();
|
|
37
|
+
if (p === "~")
|
|
38
|
+
return home;
|
|
39
|
+
if (p.startsWith("~/"))
|
|
40
|
+
return path.join(home, p.slice(2));
|
|
41
|
+
return p;
|
|
42
|
+
}
|
|
43
|
+
function resolveDirPath(dirPath, opts) {
|
|
44
|
+
let resolved = expandHome(dirPath, opts.homeDir);
|
|
45
|
+
if (resolved.includes("{project}")) {
|
|
46
|
+
if (!opts.projectName)
|
|
47
|
+
return null;
|
|
48
|
+
resolved = resolved.split("{project}").join(opts.projectName);
|
|
49
|
+
}
|
|
50
|
+
return resolved;
|
|
51
|
+
}
|
|
52
|
+
function parseFrontmatter(raw) {
|
|
53
|
+
const match = FRONTMATTER_RE.exec(raw);
|
|
54
|
+
if (!match)
|
|
55
|
+
return null;
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = parseYaml(match[1] ?? "");
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
64
|
+
return null;
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
function readEntry(directory, basename, warnings) {
|
|
68
|
+
const fullPath = path.join(directory, basename);
|
|
69
|
+
let content;
|
|
70
|
+
try {
|
|
71
|
+
content = fs.readFileSync(fullPath, "utf8");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
warnings.push(`${fullPath}: unreadable`);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const fm = parseFrontmatter(content);
|
|
78
|
+
if (!fm) {
|
|
79
|
+
warnings.push(`${fullPath}: no frontmatter or malformed YAML`);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
if (typeof fm.name !== "string" || fm.name.length === 0) {
|
|
83
|
+
warnings.push(`${fullPath}: frontmatter missing required \`name\` field`);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
if (typeof fm.type !== "string" || fm.type.length === 0) {
|
|
87
|
+
// Matches the canonical loader's strict requirement; a memory missing
|
|
88
|
+
// `type` is rejected by the router at runtime and would advertise a
|
|
89
|
+
// memory the index promises but the router won't surface.
|
|
90
|
+
warnings.push(`${fullPath}: frontmatter missing required \`type\` field`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const description = typeof fm.description === "string" ? fm.description : "";
|
|
94
|
+
if (description.length === 0) {
|
|
95
|
+
warnings.push(`${fullPath}: frontmatter missing \`description\` (entry kept, hook empty)`);
|
|
96
|
+
}
|
|
97
|
+
return { name: fm.name, description, basename, directory };
|
|
98
|
+
}
|
|
99
|
+
function listMarkdownFiles(directory, warnings) {
|
|
100
|
+
let dirents;
|
|
101
|
+
try {
|
|
102
|
+
dirents = fs.readdirSync(directory, { withFileTypes: true });
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
warnings.push(`${directory}: directory not readable, skipped`);
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
return dirents
|
|
109
|
+
.filter((d) => d.isFile() &&
|
|
110
|
+
d.name.endsWith(".md") &&
|
|
111
|
+
// Skip the curated MEMORY.md itself: in the canonical layout it has
|
|
112
|
+
// no frontmatter and exists as a hand-written sibling to the entries.
|
|
113
|
+
// Excluding it here avoids a spurious "no frontmatter" warning and
|
|
114
|
+
// self-reference in multi-dir aggregation.
|
|
115
|
+
d.name !== "MEMORY.md")
|
|
116
|
+
.map((d) => d.name)
|
|
117
|
+
.sort();
|
|
118
|
+
}
|
|
119
|
+
export function generateMemoryIndex(manifest, opts = {}) {
|
|
120
|
+
const warnings = [];
|
|
121
|
+
const entries = [];
|
|
122
|
+
for (const dir of manifest.memory.directories) {
|
|
123
|
+
const resolved = resolveDirPath(dir.path, opts);
|
|
124
|
+
if (resolved === null)
|
|
125
|
+
continue; // {project}-placeholder without projectName context
|
|
126
|
+
const files = listMarkdownFiles(resolved, warnings);
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
const entry = readEntry(resolved, file, warnings);
|
|
129
|
+
if (entry !== null)
|
|
130
|
+
entries.push(entry);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Surface basename collisions across directories: the index uses
|
|
134
|
+
// basename as the link target, so two entries with the same basename
|
|
135
|
+
// resolve to the same path and one becomes unclickable. This is a
|
|
136
|
+
// documentation gap, not a hard error — the entries are still kept.
|
|
137
|
+
const basenameCounts = new Map();
|
|
138
|
+
for (const e of entries) {
|
|
139
|
+
basenameCounts.set(e.basename, (basenameCounts.get(e.basename) ?? 0) + 1);
|
|
140
|
+
}
|
|
141
|
+
for (const [base, count] of basenameCounts) {
|
|
142
|
+
if (count > 1) {
|
|
143
|
+
warnings.push(`basename collision across memory directories: \`${base}\` appears ${count} times — only one link target resolves`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
entries.sort((a, b) => {
|
|
147
|
+
// Stable sort by (name, basename, directory) so tie-breaking is
|
|
148
|
+
// deterministic across directories holding files with the same name.
|
|
149
|
+
if (a.name !== b.name)
|
|
150
|
+
return a.name < b.name ? -1 : 1;
|
|
151
|
+
if (a.basename !== b.basename)
|
|
152
|
+
return a.basename < b.basename ? -1 : 1;
|
|
153
|
+
return a.directory < b.directory ? -1 : a.directory > b.directory ? 1 : 0;
|
|
154
|
+
});
|
|
155
|
+
const lines = [];
|
|
156
|
+
for (const e of entries) {
|
|
157
|
+
if (e.description.length > 0) {
|
|
158
|
+
lines.push(`- [${e.name}](${e.basename}) — ${e.description}`);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
lines.push(`- [${e.name}](${e.basename})`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const content = lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
165
|
+
return { content, entries, warnings };
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=generate-memory-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-memory-index.js","sourceRoot":"","sources":["../../../src/cli/apply/generate-memory-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Manifest } from "../../schema/index.js";
|
|
2
|
+
export declare const DEFAULT_BUDGET_MS = 30000;
|
|
3
|
+
export interface SettingsHookCommand {
|
|
4
|
+
type: "command";
|
|
5
|
+
command: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SettingsHookGroup {
|
|
9
|
+
matcher?: string;
|
|
10
|
+
hooks: SettingsHookCommand[];
|
|
11
|
+
}
|
|
12
|
+
export interface SettingsRoot {
|
|
13
|
+
hooks: Record<string, SettingsHookGroup[]>;
|
|
14
|
+
}
|
|
15
|
+
export declare function generateSettings(manifest: Manifest): SettingsRoot;
|