copperhead 0.3.0 → 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/NOTICE +5 -0
- package/README.md +72 -9
- package/dist/agent/ledger.js +7 -0
- package/dist/agent/ledger.js.map +1 -1
- package/dist/agent/loop.js +303 -34
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/prompts.js +3 -1
- package/dist/agent/prompts.js.map +1 -1
- package/dist/agent/providers/anthropic.js +28 -13
- package/dist/agent/providers/anthropic.js.map +1 -1
- package/dist/agent/providers/codex.js +292 -0
- package/dist/agent/providers/codex.js.map +1 -0
- package/dist/agent/render.js +170 -0
- package/dist/agent/render.js.map +1 -0
- package/dist/agent/runmeta.js +124 -0
- package/dist/agent/runmeta.js.map +1 -0
- package/dist/agent/tools.js +117 -16
- package/dist/agent/tools.js.map +1 -1
- package/dist/agent/transcript.js +23 -0
- package/dist/agent/transcript.js.map +1 -1
- package/dist/cli.js +47 -11
- package/dist/cli.js.map +1 -1
- package/dist/commands/check.js +9 -2
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/create.js +57 -3
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/sync.js +3 -1
- package/dist/commands/sync.js.map +1 -1
- package/dist/config.js +16 -8
- package/dist/config.js.map +1 -1
- package/dist/kicad/cli.js +58 -8
- package/dist/kicad/cli.js.map +1 -1
- package/dist/memory/constraints.js +63 -3
- package/dist/memory/constraints.js.map +1 -1
- package/dist/memory/drift.js +31 -0
- package/dist/memory/drift.js.map +1 -1
- package/dist/memory/scaffold.js +2 -1
- package/dist/memory/scaffold.js.map +1 -1
- package/dist/memory/synap.js +152 -0
- package/dist/memory/synap.js.map +1 -0
- package/dist/util/git.js +125 -4
- package/dist/util/git.js.map +1 -1
- package/dist/util/preflight.js +24 -0
- package/dist/util/preflight.js.map +1 -0
- package/package.json +21 -6
- package/src/agent/ledger.ts +9 -1
- package/src/agent/loop.ts +333 -35
- package/src/agent/prompts.ts +3 -1
- package/src/agent/providers/anthropic.ts +40 -16
- package/src/agent/providers/codex.ts +339 -0
- package/src/agent/render.ts +194 -0
- package/src/agent/runmeta.ts +198 -0
- package/src/agent/tools.ts +119 -15
- package/src/agent/transcript.ts +49 -0
- package/src/agent/types.ts +1 -0
- package/src/cli.ts +51 -12
- package/src/commands/check.ts +9 -3
- package/src/commands/create.ts +61 -4
- package/src/commands/sync.ts +5 -0
- package/src/config.ts +29 -9
- package/src/kicad/cli.ts +60 -9
- package/src/memory/constraints.ts +90 -3
- package/src/memory/drift.ts +32 -0
- package/src/memory/scaffold.ts +2 -1
- package/src/memory/synap.ts +217 -0
- package/src/util/git.ts +134 -4
- package/src/util/preflight.ts +22 -0
package/dist/kicad/cli.js
CHANGED
|
@@ -3,9 +3,14 @@ import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { normalizeReport } from './report.js';
|
|
6
|
-
|
|
6
|
+
import { PreflightError } from '../util/preflight.js';
|
|
7
|
+
export class KicadCliMissingError extends PreflightError {
|
|
7
8
|
constructor() {
|
|
8
|
-
super('kicad-cli not found on PATH
|
|
9
|
+
super('kicad-cli not found on PATH', 'copperhead verifies every mutation with kicad-cli ERC/DRC; without it no edit can be checked, so no run can start', [
|
|
10
|
+
'install KiCad ≥ 8: https://www.kicad.org/download/',
|
|
11
|
+
'ensure the kicad-cli binary is on PATH (on macOS it ships inside KiCad.app/Contents/MacOS)',
|
|
12
|
+
'confirm with "kicad-cli version", then rerun',
|
|
13
|
+
]);
|
|
9
14
|
this.name = 'KicadCliMissingError';
|
|
10
15
|
}
|
|
11
16
|
}
|
|
@@ -25,12 +30,22 @@ async function runCheck(kind, filePath, extraArgs = []) {
|
|
|
25
30
|
const out = path.join(dir, `${kind}.json`);
|
|
26
31
|
const sub = kind === 'erc' ? ['sch', 'erc'] : ['pcb', 'drc'];
|
|
27
32
|
try {
|
|
28
|
-
await execa('kicad-cli', [...sub, '--format', 'json', '--exit-code-violations', '--output', out, ...extraArgs, filePath], { reject: false })
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const res = await execa('kicad-cli', [...sub, '--format', 'json', '--exit-code-violations', '--output', out, ...extraArgs, filePath], { reject: false });
|
|
34
|
+
if (res.failed && res.code === 'ENOENT') {
|
|
35
|
+
throw new KicadCliMissingError();
|
|
36
|
+
}
|
|
37
|
+
let raw;
|
|
38
|
+
try {
|
|
39
|
+
raw = JSON.parse(await readFile(out, 'utf8'));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// No report on disk means kicad-cli bailed before checking — usually the
|
|
43
|
+
// design file itself failed to load (syntax/schema corruption). The
|
|
44
|
+
// raw readFile ENOENT told the agent nothing actionable; kicad-cli's
|
|
45
|
+
// own output at least names the failure.
|
|
46
|
+
const detail = [res.stderr, res.stdout].filter(Boolean).join('\n').trim();
|
|
47
|
+
throw new Error(`kicad-cli ${kind} produced no report — the ${kind === 'erc' ? 'schematic' : 'board'} file likely fails to load in KiCad. kicad-cli output: ${detail || '(none)'}`);
|
|
48
|
+
}
|
|
34
49
|
return normalizeReport(raw, kind);
|
|
35
50
|
}
|
|
36
51
|
finally {
|
|
@@ -40,6 +55,41 @@ async function runCheck(kind, filePath, extraArgs = []) {
|
|
|
40
55
|
export function runErc(schPath) {
|
|
41
56
|
return runCheck('erc', schPath);
|
|
42
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Cheap loadability probe for a KiCad file: asks kicad-cli for a throwaway
|
|
60
|
+
* export and reports the failure text if the file won't load. Text edits on
|
|
61
|
+
* s-expression sources can silently corrupt the file; catching that at edit
|
|
62
|
+
* time (with KiCad's own error) beats an opaque failure at ERC/DRC time.
|
|
63
|
+
* Returns null when the file loads.
|
|
64
|
+
*/
|
|
65
|
+
/**
|
|
66
|
+
* Only schematics and boards have a cheap standalone load probe. Project
|
|
67
|
+
* files and symbol/footprint libraries do not: feeding them to a sch/pcb
|
|
68
|
+
* export "probe" would reject perfectly good files.
|
|
69
|
+
*/
|
|
70
|
+
export function isProbeableKicadFile(p) {
|
|
71
|
+
return /\.kicad_(sch|pcb)$/.test(p);
|
|
72
|
+
}
|
|
73
|
+
export async function kicadLoadError(filePath) {
|
|
74
|
+
if (!isProbeableKicadFile(filePath))
|
|
75
|
+
return null;
|
|
76
|
+
const isSch = filePath.endsWith('.kicad_sch');
|
|
77
|
+
const dir = await mkdtemp(path.join(tmpdir(), 'copperhead-validate-'));
|
|
78
|
+
const args = isSch
|
|
79
|
+
? ['sch', 'export', 'netlist', '--output', path.join(dir, 'probe.net'), filePath]
|
|
80
|
+
: ['pcb', 'export', 'pos', '--output', path.join(dir, 'probe.pos'), filePath];
|
|
81
|
+
try {
|
|
82
|
+
const res = await execa('kicad-cli', args, { reject: false });
|
|
83
|
+
if (res.failed && res.code === 'ENOENT')
|
|
84
|
+
throw new KicadCliMissingError();
|
|
85
|
+
if (res.exitCode === 0)
|
|
86
|
+
return null;
|
|
87
|
+
return [res.stderr, res.stdout].filter(Boolean).join('\n').trim() || `kicad-cli exited ${res.exitCode}`;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await rm(dir, { recursive: true, force: true });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
43
93
|
export function runDrc(pcbPath) {
|
|
44
94
|
return runCheck('drc', pcbPath);
|
|
45
95
|
}
|
package/dist/kicad/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/kicad/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAc,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/kicad/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,14 +10,74 @@ export async function loadConstraints(repoRoot) {
|
|
|
10
10
|
return {};
|
|
11
11
|
return JSON.parse(await readFile(p, 'utf8'));
|
|
12
12
|
}
|
|
13
|
-
export async function
|
|
14
|
-
const registry = await loadConstraints(repoRoot);
|
|
15
|
-
registry[key] = constraint;
|
|
13
|
+
export async function saveConstraints(repoRoot, registry) {
|
|
16
14
|
const p = constraintsPath(repoRoot);
|
|
17
15
|
await mkdir(path.dirname(p), { recursive: true });
|
|
18
16
|
await writeFile(p, JSON.stringify(registry, null, 2) + '\n', 'utf8');
|
|
17
|
+
}
|
|
18
|
+
export async function saveConstraint(repoRoot, key, constraint) {
|
|
19
|
+
const registry = await loadConstraints(repoRoot);
|
|
20
|
+
registry[key] = constraint;
|
|
21
|
+
await saveConstraints(repoRoot, registry);
|
|
19
22
|
return registry;
|
|
20
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Items that name a not-yet-built artifact are deferrable; items that name a
|
|
26
|
+
* specific refdes, net, or doc fact return null and open a revisit obligation
|
|
27
|
+
* immediately. Misclassification is cheap in both directions: an unmatched
|
|
28
|
+
* artifact item just costs one ceremonial resolve_affected call (the old
|
|
29
|
+
* behavior for everything), and a deferred item still re-opens later.
|
|
30
|
+
*/
|
|
31
|
+
export function classifyAffectsTarget(item) {
|
|
32
|
+
if (/\b(bom|part[-\s]?selection|mpn)\b/i.test(item))
|
|
33
|
+
return 'bom';
|
|
34
|
+
if (/\b(schematic|pinout|pin[-\s]?assign\w*|strapping|netlist)\b/i.test(item))
|
|
35
|
+
return 'schematic';
|
|
36
|
+
if (/\b(layout|stackup|rout(?:e|es|ing)?|vias?|pours?|keepouts?|zones?|copper|traces?|board|pcb|mounting|thermal|silkscreen|assembly|current[-\s]?carrying)\b/i.test(item))
|
|
37
|
+
return 'board';
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
export function affectsTargetExists(target, repoRoot, config) {
|
|
41
|
+
switch (target) {
|
|
42
|
+
case 'schematic':
|
|
43
|
+
return !!config.schematic;
|
|
44
|
+
case 'board':
|
|
45
|
+
return !!config.board;
|
|
46
|
+
case 'bom':
|
|
47
|
+
return existsSync(path.join(repoRoot, config.docs, 'BOM.md'));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run-start hook: re-open the revisit obligations that were deferred while
|
|
52
|
+
* their target artifact did not exist. Each re-opened item is removed from the
|
|
53
|
+
* registry's `deferred` marker in the same pass, so it re-opens exactly once —
|
|
54
|
+
* from then on it lives in the run's ledger like any other obligation.
|
|
55
|
+
*/
|
|
56
|
+
export async function reopenDeferredAffects(repoRoot, config, openObligation) {
|
|
57
|
+
const registry = await loadConstraints(repoRoot);
|
|
58
|
+
const reopened = [];
|
|
59
|
+
for (const [key, c] of Object.entries(registry)) {
|
|
60
|
+
if (!c.deferred?.length)
|
|
61
|
+
continue;
|
|
62
|
+
const stillDeferred = [];
|
|
63
|
+
for (const item of c.deferred) {
|
|
64
|
+
const target = classifyAffectsTarget(item);
|
|
65
|
+
if (target && !affectsTargetExists(target, repoRoot, config)) {
|
|
66
|
+
stillDeferred.push(item);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
openObligation(key, item);
|
|
70
|
+
reopened.push({ key, item });
|
|
71
|
+
}
|
|
72
|
+
if (stillDeferred.length)
|
|
73
|
+
c.deferred = stillDeferred;
|
|
74
|
+
else
|
|
75
|
+
delete c.deferred;
|
|
76
|
+
}
|
|
77
|
+
if (reopened.length)
|
|
78
|
+
await saveConstraints(repoRoot, registry);
|
|
79
|
+
return reopened;
|
|
80
|
+
}
|
|
21
81
|
/**
|
|
22
82
|
* Mechanical validation where possible (SPEC §2.6): forbidden pins against the
|
|
23
83
|
* pinout, numeric budget keys surfaced for the doc-level checks. Geometry
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../src/memory/constraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../src/memory/constraints.ts"],"names":[],"mappings":"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"}
|
package/dist/memory/drift.js
CHANGED
|
@@ -19,10 +19,41 @@ export function parseMarkdownTables(md) {
|
|
|
19
19
|
return rows;
|
|
20
20
|
}
|
|
21
21
|
const isHeader = (row) => row.cells.some((c) => /^(refdes|pin)$/i.test(c));
|
|
22
|
+
/**
|
|
23
|
+
* The zero-symbol carve-out in checkDrift is right for the create pipeline,
|
|
24
|
+
* but it would let `check` silently pass an established repo whose schematic
|
|
25
|
+
* was emptied by accident while BOM.md still lists parts. `check` calls this
|
|
26
|
+
* alongside checkDrift and reports the result as a warning, not a failure:
|
|
27
|
+
* an empty sheet with a populated BOM is either bootstrap (fine) or an
|
|
28
|
+
* accident (worth a human look), and only a human can tell which.
|
|
29
|
+
*/
|
|
30
|
+
export async function emptySchematicWarning(repoRoot, docsDir, schematic) {
|
|
31
|
+
const symbols = await listSymbols(path.join(repoRoot, schematic));
|
|
32
|
+
if (symbols.length)
|
|
33
|
+
return null;
|
|
34
|
+
const bomPath = path.join(repoRoot, docsDir, 'BOM.md');
|
|
35
|
+
if (!existsSync(bomPath))
|
|
36
|
+
return null;
|
|
37
|
+
const refs = parseMarkdownTables(await readFile(bomPath, 'utf8'))
|
|
38
|
+
.filter((r) => !isHeader(r))
|
|
39
|
+
.map((r) => r.cells[0])
|
|
40
|
+
.filter(Boolean);
|
|
41
|
+
if (!refs.length)
|
|
42
|
+
return null;
|
|
43
|
+
return `schematic has zero symbols but BOM.md lists ${refs.length} refdes; if this repo is not mid-bootstrap, the schematic may have been emptied accidentally`;
|
|
44
|
+
}
|
|
22
45
|
export async function checkDrift(repoRoot, docsDir, schematic) {
|
|
23
46
|
const mismatches = [];
|
|
24
47
|
const schPath = path.join(repoRoot, schematic);
|
|
25
48
|
const symbols = await listSymbols(schPath);
|
|
49
|
+
// A schematic with zero symbols is the bootstrap state: during the create
|
|
50
|
+
// pipeline the docs legitimately lead the schematic (part-selection writes
|
|
51
|
+
// BOM.md before any symbol exists), so comparing against an empty sheet
|
|
52
|
+
// deadlocks every docs-touching stage — or worse, teaches the agent to strip
|
|
53
|
+
// refdes from BOM.md to appease the gate (#21). Same reasoning as the
|
|
54
|
+
// "no schematic configured" carve-out in the check_drift tool.
|
|
55
|
+
if (!symbols.length)
|
|
56
|
+
return mismatches;
|
|
26
57
|
const byRef = new Map(symbols.map((s) => [s.ref, s]));
|
|
27
58
|
const bomPath = path.join(repoRoot, docsDir, 'BOM.md');
|
|
28
59
|
if (existsSync(bomPath)) {
|
package/dist/memory/drift.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/memory/drift.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/memory/drift.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,OAAO,EAAwB,MAAM,kBAAkB,CAAC;AAgB9E,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACjC,MAAM,KAAK,GAAG,CAAC;aACZ,KAAK,CAAC,GAAG,CAAC;aACV,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxB,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS,CAAC,gBAAgB;QACtE,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAW,EAAE,CAC1C,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAgB,EAChB,OAAe,EACf,SAAiB;IAEjB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IAClE,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;SAC9D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACtB,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,+CAA+C,IAAI,CAAC,MAAM,8FAA8F,CAAC;AAClK,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,OAAe,EAAE,SAAiB;IACnF,MAAM,UAAU,GAAoB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IAC3C,0EAA0E;IAC1E,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,sEAAsE;IACtE,+DAA+D;IAC/D,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,CAA0B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/E,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9F,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;YAC1C,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,mBAAmB,EAAE,CAAC,CAAC;gBAC9F,SAAS;YACX,CAAC;YACD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC/C,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,UAAU,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,UAAU,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC1G,CAAC;YACD,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,EAAE,IAAI,SAAS,KAAK,GAAG,CAAC,SAAS,EAAE,CAAC;gBAC/E,UAAU,CAAC,IAAI,CAAC;oBACd,GAAG,EAAE,QAAQ;oBACb,KAAK,EAAE,GAAG,GAAG,cAAc,SAAS,EAAE;oBACtC,MAAM,EAAE,GAAG,GAAG,cAAc,GAAG,CAAC,SAAS,EAAE;iBAC5C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,gBAAgB,EAAE,CAAC,CAAC;YACnH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACjG,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,AAAD,EAAG,GAAG,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;YAC1C,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS;gBAAE,SAAS;YACjC,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClB,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC;gBAC7F,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;YACpC,MAAM,OAAO,GAAG,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;YAC7D,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;gBACvB,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,EAAE,EAAE,CAAC,CAAC;YACpG,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
package/dist/memory/scaffold.js
CHANGED
|
@@ -99,7 +99,8 @@ Generated by \`copperhead init\`; regenerated on re-runs (do not hand-edit).
|
|
|
99
99
|
|
|
100
100
|
- \`schematic\` / \`board\`: repo-relative paths to the KiCad files copperhead operates on (currently: ${config.schematic ?? 'none'} / ${config.board ?? 'none'})
|
|
101
101
|
- \`docs\`: design docs directory (docs-as-memory), default \`docs/\`
|
|
102
|
-
- \`model\`: default model (\`gpt-5
|
|
102
|
+
- \`model\`: default provider/model (\`codex\`, \`gpt-5\`, or \`claude\`); overridden by \`--model\` and \`COPPERHEAD_MODEL\`
|
|
103
|
+
- local Codex uses the saved \`codex login\`; set \`COPPERHEAD_CODEX_PATH\` only when the executable is not on \`PATH\`
|
|
103
104
|
- \`maxTurns\`: agent loop turn budget per run (default 40)
|
|
104
105
|
- \`maxRepairCycles\`: ERC/DRC repair attempts before rollback (default 5)
|
|
105
106
|
- \`budgets\`: free-form hard constraints (e.g. \`"sleep_current_uA": 25\`); surfaced verbatim into every run's system prompt
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/memory/scaffold.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/memory/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-run memory via Synap (https://docs.maximem.ai).
|
|
3
|
+
*
|
|
4
|
+
* copperhead's own memory is per-repo and file-based: docs/DECISIONS.md, the
|
|
5
|
+
* constraint registry, the drift checker. Synap is the layer above that — what
|
|
6
|
+
* this user tends to want across every board they've ever asked about. It
|
|
7
|
+
* complements the docs; it does not replace them, and nothing here is a source
|
|
8
|
+
* of truth. Recalled text is advisory context in the system prompt, while
|
|
9
|
+
* as-built facts still come from the KiCad files.
|
|
10
|
+
*
|
|
11
|
+
* Three properties are load-bearing:
|
|
12
|
+
*
|
|
13
|
+
* 1. Opt-in. Inactive unless SYNAP_API_KEY is set, so the default install is
|
|
14
|
+
* unchanged and `check` stays network-free (it never constructs this).
|
|
15
|
+
* 2. Optional at runtime. @maximem/synap-js-sdk is an optionalDependency and is
|
|
16
|
+
* imported lazily through a non-literal specifier, so a missing package (or
|
|
17
|
+
* a host without the Python 3.11+ runtime its bridge needs) degrades to
|
|
18
|
+
* "no memory" instead of breaking the CLI.
|
|
19
|
+
* 3. Fail-soft on read, loud on write. A recall failure must never cost someone
|
|
20
|
+
* a design run; a record failure is reported, because silently losing writes
|
|
21
|
+
* lets memory drift away from what actually happened.
|
|
22
|
+
*/
|
|
23
|
+
import { randomUUID } from 'node:crypto';
|
|
24
|
+
import { execa } from 'execa';
|
|
25
|
+
import { redactSecrets } from '../util/redact.js';
|
|
26
|
+
/** Wall-clock ceiling on any single Synap call. The bridge is a Python subprocess. */
|
|
27
|
+
const RECALL_TIMEOUT_MS = 10_000;
|
|
28
|
+
const RECORD_TIMEOUT_MS = 15_000;
|
|
29
|
+
const MAX_RECALLED = 8;
|
|
30
|
+
export function synapEnabled(env = process.env) {
|
|
31
|
+
return Boolean(env.SYNAP_API_KEY);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Identity for memory scoping. The git committer email is the natural stable
|
|
35
|
+
* user id here: it is already the identity every run is attributed to.
|
|
36
|
+
*/
|
|
37
|
+
async function resolveUserId(repoRoot, env) {
|
|
38
|
+
if (env.SYNAP_USER_ID)
|
|
39
|
+
return env.SYNAP_USER_ID;
|
|
40
|
+
try {
|
|
41
|
+
const { stdout } = await execa('git', ['config', 'user.email'], { cwd: repoRoot });
|
|
42
|
+
if (stdout.trim())
|
|
43
|
+
return stdout.trim();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// not configured; fall through
|
|
47
|
+
}
|
|
48
|
+
return 'copperhead-local';
|
|
49
|
+
}
|
|
50
|
+
function withTimeout(p, ms, label) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
53
|
+
p.then((v) => {
|
|
54
|
+
clearTimeout(timer);
|
|
55
|
+
resolve(v);
|
|
56
|
+
}, (e) => {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
reject(e);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns null when memory is disabled or unavailable — every caller treats
|
|
64
|
+
* null as "run without cross-run memory".
|
|
65
|
+
*/
|
|
66
|
+
export async function openSynapMemory(opts) {
|
|
67
|
+
const env = opts.env ?? process.env;
|
|
68
|
+
const log = opts.log ?? (() => { });
|
|
69
|
+
if (!synapEnabled(env))
|
|
70
|
+
return null;
|
|
71
|
+
let client;
|
|
72
|
+
try {
|
|
73
|
+
// Non-literal specifier: keeps tsc from resolving an optional dependency at
|
|
74
|
+
// build time, so the package may legitimately be absent.
|
|
75
|
+
const specifier = '@maximem/synap-js-sdk';
|
|
76
|
+
const mod = (await import(specifier));
|
|
77
|
+
const createClient = mod.createClient ?? mod.default?.createClient;
|
|
78
|
+
if (!createClient)
|
|
79
|
+
throw new Error('createClient not exported');
|
|
80
|
+
client = createClient({ apiKey: env.SYNAP_API_KEY, requestTimeoutMs: RECORD_TIMEOUT_MS });
|
|
81
|
+
await withTimeout(client.init(), RECORD_TIMEOUT_MS, 'synap init');
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
// Missing package, missing Python runtime, bad key: all non-fatal.
|
|
85
|
+
log(`synap memory unavailable (${err.message}); continuing without it`);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const userId = await resolveUserId(opts.repoRoot, env);
|
|
89
|
+
const customerId = env.SYNAP_CUSTOMER_ID ?? 'copperhead';
|
|
90
|
+
const conversationId = randomUUID();
|
|
91
|
+
return {
|
|
92
|
+
async recall(request) {
|
|
93
|
+
try {
|
|
94
|
+
const res = await withTimeout(client.searchMemory({
|
|
95
|
+
userId,
|
|
96
|
+
customerId,
|
|
97
|
+
query: redactSecrets(request),
|
|
98
|
+
maxResults: MAX_RECALLED,
|
|
99
|
+
}), RECALL_TIMEOUT_MS, 'synap recall');
|
|
100
|
+
const items = (res.results ?? []).filter((r) => r.memory?.trim());
|
|
101
|
+
if (!items.length)
|
|
102
|
+
return null;
|
|
103
|
+
const lines = items.map((r) => `- ${r.memory.trim()}${r.contextType ? ` _(${r.contextType})_` : ''}`);
|
|
104
|
+
return [
|
|
105
|
+
'## Recalled from prior runs (Synap)',
|
|
106
|
+
'',
|
|
107
|
+
'Context from earlier work by this user, possibly on other boards. Advisory only:',
|
|
108
|
+
'the KiCad files and this repo’s docs remain the source of truth. If any of this',
|
|
109
|
+
'conflicts with what you read in the repo, the repo wins — say so rather than',
|
|
110
|
+
'acting on a stale memory.',
|
|
111
|
+
'',
|
|
112
|
+
...lines,
|
|
113
|
+
].join('\n');
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
log(`synap recall failed (${err.message}); continuing without it`);
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
async record(run) {
|
|
121
|
+
const assistant = [
|
|
122
|
+
`Outcome: ${run.outcome}`,
|
|
123
|
+
`Summary: ${run.summary}`,
|
|
124
|
+
`OpenSpec change: ${run.changeId ?? 'n/a'}`,
|
|
125
|
+
`Verification: ${run.verification}`,
|
|
126
|
+
run.filesTouched.length ? `Files: ${run.filesTouched.join(', ')}` : null,
|
|
127
|
+
run.decisions.length ? `Decisions:\n${run.decisions.map((d) => `- ${d}`).join('\n')}` : null,
|
|
128
|
+
]
|
|
129
|
+
.filter(Boolean)
|
|
130
|
+
.join('\n');
|
|
131
|
+
await withTimeout(client.addMemory({
|
|
132
|
+
userId,
|
|
133
|
+
customerId,
|
|
134
|
+
conversationId,
|
|
135
|
+
messages: [
|
|
136
|
+
{ role: 'user', content: redactSecrets(run.request) },
|
|
137
|
+
{ role: 'assistant', content: redactSecrets(assistant) },
|
|
138
|
+
],
|
|
139
|
+
metadata: { source: 'copperhead', outcome: run.outcome, changeId: run.changeId },
|
|
140
|
+
}), RECORD_TIMEOUT_MS, 'synap record');
|
|
141
|
+
},
|
|
142
|
+
async close() {
|
|
143
|
+
try {
|
|
144
|
+
await withTimeout(client.shutdown(), RECORD_TIMEOUT_MS, 'synap shutdown');
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Best effort: a failed shutdown must not change the run's outcome.
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=synap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synap.js","sourceRoot":"","sources":["../../src/memory/synap.ts"],"names":[],"mappings":"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"}
|
package/dist/util/git.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { execa } from 'execa';
|
|
2
|
+
import { cp, mkdir, mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { PreflightError } from './preflight.js';
|
|
2
7
|
async function git(repo, args) {
|
|
3
8
|
const { stdout } = await execa('git', args, { cwd: repo });
|
|
4
9
|
return stdout.trim();
|
|
@@ -12,10 +17,40 @@ export async function isGitRepo(repo) {
|
|
|
12
17
|
return false;
|
|
13
18
|
}
|
|
14
19
|
}
|
|
20
|
+
/** False on an unborn HEAD (fresh `git init` with no commits yet). */
|
|
21
|
+
export async function hasCommits(repo) {
|
|
22
|
+
try {
|
|
23
|
+
await git(repo, ['rev-parse', '--quiet', '--verify', 'HEAD']);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
15
30
|
export async function isDirty(repo) {
|
|
16
31
|
const status = await git(repo, ['status', '--porcelain']);
|
|
17
32
|
return status.length > 0;
|
|
18
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The run-blocking git gates, in order: repo -> commits -> dirty (AC-3.8).
|
|
36
|
+
* Throws a PreflightError whose message explains why the run is refused and
|
|
37
|
+
* how to fix it; a caller that catches only needs err.message.
|
|
38
|
+
*/
|
|
39
|
+
export async function gitPreflight(repo, opts = {}) {
|
|
40
|
+
if (!(await isGitRepo(repo))) {
|
|
41
|
+
throw new PreflightError('not a git repository; copperhead requires git for snapshots and rollback', 'every run snapshots HEAD before editing so a failed run can be rolled back losslessly; without git there is no snapshot and no undo', ['git init', 'git add -A && git commit -m "initial commit"', 'rerun the same copperhead command']);
|
|
42
|
+
}
|
|
43
|
+
if (!(await hasCommits(repo))) {
|
|
44
|
+
throw new PreflightError('repository has no commits; copperhead requires at least one commit for snapshots and rollback', 'the pre-run snapshot is the current HEAD commit; with an unborn HEAD there is nothing to roll back to if verification fails', ['git add -A && git commit -m "initial commit"', 'rerun the same copperhead command']);
|
|
45
|
+
}
|
|
46
|
+
if ((await isDirty(repo)) && !opts.allowDirty) {
|
|
47
|
+
throw new PreflightError('working tree is dirty; copperhead refuses to run on uncommitted changes by default', 'a rollback hard-resets to the pre-run snapshot, which would silently destroy your uncommitted work', [
|
|
48
|
+
'git add -A && git commit — to keep your changes (recommended)',
|
|
49
|
+
'git stash — to set them aside for now',
|
|
50
|
+
'or rerun with --allow-dirty to let copperhead preserve them via "git stash create"',
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
19
54
|
/**
|
|
20
55
|
* Snapshot the working tree before a run. On a clean tree HEAD is enough;
|
|
21
56
|
* with --allow-dirty we keep a `git stash create` object so uncommitted work
|
|
@@ -34,11 +69,97 @@ export async function snapshot(repo) {
|
|
|
34
69
|
* (.copperhead/runs/) survives rollback: it is the evidence of what failed.
|
|
35
70
|
*/
|
|
36
71
|
export async function restore(repo, snap) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
72
|
+
// `git clean -e` only protects untracked paths. A run directory can become
|
|
73
|
+
// staged (for example while preserving failed work), and `reset --hard`
|
|
74
|
+
// deletes such paths before clean runs. Copy it outside the repository so
|
|
75
|
+
// the audit trail survives regardless of its index state.
|
|
76
|
+
const runs = path.join(repo, '.copperhead', 'runs');
|
|
77
|
+
let backupRoot = null;
|
|
78
|
+
let backup = null;
|
|
79
|
+
try {
|
|
80
|
+
try {
|
|
81
|
+
backupRoot = await mkdtemp(path.join(tmpdir(), 'copperhead-runs-'));
|
|
82
|
+
backup = path.join(backupRoot, 'runs');
|
|
83
|
+
if (existsSync(runs))
|
|
84
|
+
await cp(runs, backup, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
backup = null;
|
|
88
|
+
console.warn(`warning: could not preserve failed-run audit trail before rollback: ${err.message}`);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
await git(repo, ['reset', '--hard', snap.head]);
|
|
92
|
+
await git(repo, ['clean', '-fd', '-e', '.copperhead/runs']);
|
|
93
|
+
if (snap.stash) {
|
|
94
|
+
await git(repo, ['stash', 'apply', snap.stash]);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
if (backup && existsSync(backup)) {
|
|
99
|
+
try {
|
|
100
|
+
await mkdir(path.dirname(runs), { recursive: true });
|
|
101
|
+
// Restored runs are intentionally untracked; their audit contents
|
|
102
|
+
// are ignored by the target-repository convention.
|
|
103
|
+
await cp(backup, runs, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
console.warn(`warning: could not restore failed-run audit trail: ${err.message}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
41
110
|
}
|
|
111
|
+
finally {
|
|
112
|
+
if (backupRoot) {
|
|
113
|
+
try {
|
|
114
|
+
await rm(backupRoot, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
console.warn(`warning: could not clean failed-run audit backup: ${err.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Preserve a failed run's work as a stash entry before rollback, so a failure
|
|
124
|
+
* is recoverable instead of destroyed. `git stash create` alone ignores
|
|
125
|
+
* untracked files (most of what a docs-stage run produces), so everything is
|
|
126
|
+
* staged first; restore() resets the index anyway. Never throws: preservation
|
|
127
|
+
* must not be able to block the rollback itself.
|
|
128
|
+
*/
|
|
129
|
+
export async function preserveFailedRun(repo, runId) {
|
|
130
|
+
try {
|
|
131
|
+
if (!(await isDirty(repo)))
|
|
132
|
+
return null;
|
|
133
|
+
// Never leave the audit trail staged: a staged-but-not-in-HEAD path is
|
|
134
|
+
// deleted by restore()'s `reset --hard`, which silently defeats its
|
|
135
|
+
// `clean -e .copperhead/runs` protection (that flag only spares untracked
|
|
136
|
+
// files) — the in-flight run's transcript dir vanishes mid-run. Staging
|
|
137
|
+
// then unstaging (rather than an exclude pathspec) because `git add`
|
|
138
|
+
// errors outright when a pathspec touches gitignored paths, and runs/ is
|
|
139
|
+
// gitignored in some target repos but tracked in others.
|
|
140
|
+
await git(repo, ['add', '-A']);
|
|
141
|
+
await git(repo, ['reset', '-q', '--', '.copperhead/runs']);
|
|
142
|
+
const sha = await git(repo, ['stash', 'create']);
|
|
143
|
+
if (!sha)
|
|
144
|
+
return null;
|
|
145
|
+
await git(repo, ['stash', 'store', '-m', `copperhead failed run ${runId}`, sha]);
|
|
146
|
+
return sha;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Current branch name, or "HEAD" when detached. Read-only metadata probe. */
|
|
153
|
+
export async function branchName(repo) {
|
|
154
|
+
return git(repo, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
155
|
+
}
|
|
156
|
+
export async function headCommit(repo) {
|
|
157
|
+
return git(repo, ['rev-parse', 'HEAD']);
|
|
158
|
+
}
|
|
159
|
+
/** Count of uncommitted paths (staged, unstaged, and untracked). */
|
|
160
|
+
export async function uncommittedCount(repo) {
|
|
161
|
+
const status = await git(repo, ['status', '--porcelain']);
|
|
162
|
+
return status ? status.split('\n').length : 0;
|
|
42
163
|
}
|
|
43
164
|
export async function commitAll(repo, message) {
|
|
44
165
|
await git(repo, ['add', '-A']);
|