@fourshore/graft-core 0.0.8 → 0.0.10
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/dist/agents.d.ts +1 -1
- package/dist/agents.js +10 -4
- package/dist/agents.js.map +1 -1
- package/dist/capture.d.ts +21 -0
- package/dist/capture.js +64 -0
- package/dist/capture.js.map +1 -0
- package/dist/ci.d.ts +18 -0
- package/dist/ci.js +50 -0
- package/dist/ci.js.map +1 -0
- package/dist/claude-code.d.ts +46 -0
- package/dist/claude-code.js +72 -0
- package/dist/claude-code.js.map +1 -0
- package/dist/context.d.ts +37 -0
- package/dist/context.js +77 -0
- package/dist/context.js.map +1 -0
- package/dist/graft.d.ts +105 -1
- package/dist/graft.js +278 -26
- package/dist/graft.js.map +1 -1
- package/dist/hooks.d.ts +17 -0
- package/dist/hooks.js +81 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/policy.d.ts +75 -0
- package/dist/policy.js +99 -1
- package/dist/policy.js.map +1 -1
- package/dist/record.d.ts +35 -8
- package/dist/record.js +57 -25
- package/dist/record.js.map +1 -1
- package/dist/redact.d.ts +8 -1
- package/dist/redact.js +18 -3
- package/dist/redact.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
export { Graft, GraftError, buildCommitMessage } from "./graft.js";
|
|
1
|
+
export { Graft, GraftError, buildCommitMessage, recordBlock, runShell } from "./graft.js";
|
|
2
2
|
export * from "./policy.js";
|
|
3
3
|
export * from "./record.js";
|
|
4
4
|
export * from "./redact.js";
|
|
5
5
|
export * from "./agents.js";
|
|
6
|
+
export * from "./capture.js";
|
|
7
|
+
export * from "./claude-code.js";
|
|
8
|
+
export * from "./hooks.js";
|
|
9
|
+
export * from "./context.js";
|
|
10
|
+
export * from "./ci.js";
|
|
6
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1F,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
|
package/dist/policy.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import type { Evidence } from "./record.js";
|
|
2
|
+
/** Which named commands a change that touches these paths must carry as passing evidence. */
|
|
3
|
+
export interface CoverageRule {
|
|
4
|
+
/** Globs relative to the repo root, same rules as secretFiles. */
|
|
5
|
+
paths: string[];
|
|
6
|
+
/** Names from `commands`. */
|
|
7
|
+
require: string[];
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
10
|
* Repo policy, read from .graft/policy.json at the working tree root.
|
|
3
11
|
* Version 1 has one rule. More arrive with the review view and the server.
|
|
@@ -23,7 +31,74 @@ export interface Policy {
|
|
|
23
31
|
* "specs/**"). Same glob rules as secretFiles.
|
|
24
32
|
*/
|
|
25
33
|
behaviorFiles?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* Trailers added to every landed commit, each "Key: value", so the ones you
|
|
36
|
+
* pass on every land (a session link, a Co-Authored-By) cannot be forgotten.
|
|
37
|
+
* `$NAME` and `${NAME}` expand from the environment; a trailer that names a
|
|
38
|
+
* variable which is not set is left out of that commit rather than written
|
|
39
|
+
* with a hole in it.
|
|
40
|
+
*/
|
|
41
|
+
trailers?: string[];
|
|
42
|
+
/**
|
|
43
|
+
* Extra regular expressions (as strings) for commands the capture hooks
|
|
44
|
+
* record as evidence, on top of the built-in test, build, lint and
|
|
45
|
+
* type-check patterns: for example "^\\./scripts/verify".
|
|
46
|
+
*/
|
|
47
|
+
captureCommands?: string[];
|
|
48
|
+
/**
|
|
49
|
+
* When `graft check --rerun` re-runs recorded commands, only commands
|
|
50
|
+
* matching one of these regular expressions (as strings) are run. Unset
|
|
51
|
+
* means every recorded passing command. Set it where a PR from a stranger
|
|
52
|
+
* could record a command you would not want CI to execute.
|
|
53
|
+
*/
|
|
54
|
+
checkCommands?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* The repo's checks, named once: `{ "test": "go test ./...", "vet386":
|
|
57
|
+
* "env GOOS=windows GOARCH=386 go vet ./..." }`. `graft evidence <name>`
|
|
58
|
+
* runs one; the capture hooks record a typed command that matches one
|
|
59
|
+
* under its name; `graft check --rerun` runs the current definition of a
|
|
60
|
+
* name, so a command can change without invalidating history. Names are
|
|
61
|
+
* what `rules` refer to.
|
|
62
|
+
*/
|
|
63
|
+
commands?: Record<string, string>;
|
|
64
|
+
/**
|
|
65
|
+
* The repo's definition of done, by path: a change that touches a file
|
|
66
|
+
* matching a rule's `paths` must carry a passing run (by Graft or a
|
|
67
|
+
* harness, not attested) of every command the rule names. `land` refuses
|
|
68
|
+
* otherwise, and `graft check` fails the commit.
|
|
69
|
+
*/
|
|
70
|
+
rules?: CoverageRule[];
|
|
26
71
|
}
|
|
27
72
|
export declare const DEFAULT_POLICY: Policy;
|
|
28
73
|
export declare const POLICY_PATH = ".graft/policy.json";
|
|
29
74
|
export declare function readPolicy(topLevel: string): Promise<Policy>;
|
|
75
|
+
/** Whitespace-insensitive form of a command, for matching what was typed against the catalog. */
|
|
76
|
+
export declare function normalizeCommand(command: string): string;
|
|
77
|
+
/** The catalog name whose command is what was typed, or null. */
|
|
78
|
+
export declare function matchCatalog(policy: Policy, command: string): string | null;
|
|
79
|
+
/** A named command that is not met by the evidence, with the files that asked for it. */
|
|
80
|
+
export interface UnmetRule {
|
|
81
|
+
name: string;
|
|
82
|
+
command: string;
|
|
83
|
+
files: string[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Which named commands the rules demand for these files that the evidence
|
|
87
|
+
* does not cover. A run covers a name when it exited 0, was run by Graft or
|
|
88
|
+
* a harness (not attested), and carries the name, or the name as its label
|
|
89
|
+
* (a record rebuilt from a commit message keeps only the label), or the
|
|
90
|
+
* catalog's command for that name.
|
|
91
|
+
*/
|
|
92
|
+
export declare function evaluateRules(policy: Policy, files: string[], evidence: Evidence[]): UnmetRule[];
|
|
93
|
+
/**
|
|
94
|
+
* Expand `$NAME` / `${NAME}` in policy trailers from `env`. Returns the
|
|
95
|
+
* trailers to write and the ones skipped because a variable was unset, with
|
|
96
|
+
* the variable's name, so the caller can say so.
|
|
97
|
+
*/
|
|
98
|
+
export declare function expandTrailers(trailers: string[], env?: Record<string, string | undefined>): {
|
|
99
|
+
trailers: string[];
|
|
100
|
+
skipped: {
|
|
101
|
+
trailer: string;
|
|
102
|
+
missing: string;
|
|
103
|
+
}[];
|
|
104
|
+
};
|
package/dist/policy.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { globToRegExp } from "./redact.js";
|
|
3
4
|
export const DEFAULT_POLICY = { version: 1, requireEvidence: true };
|
|
4
5
|
export const POLICY_PATH = ".graft/policy.json";
|
|
5
6
|
export async function readPolicy(topLevel) {
|
|
@@ -9,7 +10,9 @@ export async function readPolicy(topLevel) {
|
|
|
9
10
|
if (parsed.version !== undefined && parsed.version !== 1) {
|
|
10
11
|
throw new Error(`Unsupported policy version ${String(parsed.version)} in ${POLICY_PATH}`);
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
const policy = { ...DEFAULT_POLICY, ...parsed, version: 1 };
|
|
14
|
+
validatePolicy(policy);
|
|
15
|
+
return policy;
|
|
13
16
|
}
|
|
14
17
|
catch (err) {
|
|
15
18
|
if (err.code === "ENOENT")
|
|
@@ -17,4 +20,99 @@ export async function readPolicy(topLevel) {
|
|
|
17
20
|
throw err;
|
|
18
21
|
}
|
|
19
22
|
}
|
|
23
|
+
const COMMAND_NAME = /^[A-Za-z0-9][A-Za-z0-9_.:-]*$/;
|
|
24
|
+
function validatePolicy(policy) {
|
|
25
|
+
for (const [name, command] of Object.entries(policy.commands ?? {})) {
|
|
26
|
+
if (!COMMAND_NAME.test(name))
|
|
27
|
+
throw new Error(`${POLICY_PATH}: command name "${name}" must be a word (letters, digits, _ . : -).`);
|
|
28
|
+
if (typeof command !== "string" || !command.trim())
|
|
29
|
+
throw new Error(`${POLICY_PATH}: command "${name}" must be a non-empty string.`);
|
|
30
|
+
}
|
|
31
|
+
for (const rule of policy.rules ?? []) {
|
|
32
|
+
if (!Array.isArray(rule.paths) || !rule.paths.length)
|
|
33
|
+
throw new Error(`${POLICY_PATH}: every rule needs a non-empty "paths" list.`);
|
|
34
|
+
if (!Array.isArray(rule.require) || !rule.require.length)
|
|
35
|
+
throw new Error(`${POLICY_PATH}: every rule needs a non-empty "require" list.`);
|
|
36
|
+
for (const name of rule.require) {
|
|
37
|
+
if (!policy.commands?.[name]) {
|
|
38
|
+
throw new Error(`${POLICY_PATH}: rule for ${rule.paths.join(", ")} requires "${name}", which "commands" does not define.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Whitespace-insensitive form of a command, for matching what was typed against the catalog. */
|
|
44
|
+
export function normalizeCommand(command) {
|
|
45
|
+
return command.replace(/\s+/g, " ").trim();
|
|
46
|
+
}
|
|
47
|
+
/** The catalog name whose command is what was typed, or null. */
|
|
48
|
+
export function matchCatalog(policy, command) {
|
|
49
|
+
const typed = normalizeCommand(command);
|
|
50
|
+
for (const [name, c] of Object.entries(policy.commands ?? {}))
|
|
51
|
+
if (normalizeCommand(c) === typed)
|
|
52
|
+
return name;
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Which named commands the rules demand for these files that the evidence
|
|
57
|
+
* does not cover. A run covers a name when it exited 0, was run by Graft or
|
|
58
|
+
* a harness (not attested), and carries the name, or the name as its label
|
|
59
|
+
* (a record rebuilt from a commit message keeps only the label), or the
|
|
60
|
+
* catalog's command for that name.
|
|
61
|
+
*/
|
|
62
|
+
export function evaluateRules(policy, files, evidence) {
|
|
63
|
+
const commands = policy.commands ?? {};
|
|
64
|
+
const unmet = new Map();
|
|
65
|
+
for (const rule of policy.rules ?? []) {
|
|
66
|
+
const hit = files.filter((f) => rule.paths.some((g) => globToRegExp(g).test(f.replace(/\\/g, "/"))));
|
|
67
|
+
if (!hit.length)
|
|
68
|
+
continue;
|
|
69
|
+
for (const name of rule.require) {
|
|
70
|
+
if (commands[name] && covers(evidence, name, commands[name]))
|
|
71
|
+
continue;
|
|
72
|
+
const set = unmet.get(name) ?? new Set();
|
|
73
|
+
for (const f of hit)
|
|
74
|
+
set.add(f);
|
|
75
|
+
unmet.set(name, set);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return [...unmet].map(([name, set]) => ({ name, command: commands[name] ?? "", files: [...set] }));
|
|
79
|
+
}
|
|
80
|
+
function covers(evidence, name, command) {
|
|
81
|
+
const want = normalizeCommand(command);
|
|
82
|
+
return evidence.some((e) => e.kind === "command" &&
|
|
83
|
+
e.exitCode === 0 &&
|
|
84
|
+
!e.attested &&
|
|
85
|
+
(e.name === name || e.label === name || normalizeCommand(e.command) === want));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Expand `$NAME` / `${NAME}` in policy trailers from `env`. Returns the
|
|
89
|
+
* trailers to write and the ones skipped because a variable was unset, with
|
|
90
|
+
* the variable's name, so the caller can say so.
|
|
91
|
+
*/
|
|
92
|
+
export function expandTrailers(trailers, env = process.env) {
|
|
93
|
+
const out = [];
|
|
94
|
+
const skipped = [];
|
|
95
|
+
for (const t of trailers) {
|
|
96
|
+
let missing;
|
|
97
|
+
const expanded = t.replace(/\$(?:\{([A-Za-z_][A-Za-z0-9_]*)(?:([#%])([^}]*))?\}|([A-Za-z_][A-Za-z0-9_]*))/g, (_, braced, op, affix, bare) => {
|
|
98
|
+
const name = braced ?? bare;
|
|
99
|
+
let v = env[name];
|
|
100
|
+
if (v === undefined || v === "") {
|
|
101
|
+
missing ??= name;
|
|
102
|
+
return "";
|
|
103
|
+
}
|
|
104
|
+
// `${NAME#prefix}` and `${NAME%suffix}` strip a literal affix, as in sh.
|
|
105
|
+
if (op === "#" && affix && v.startsWith(affix))
|
|
106
|
+
v = v.slice(affix.length);
|
|
107
|
+
if (op === "%" && affix && v.endsWith(affix))
|
|
108
|
+
v = v.slice(0, -affix.length);
|
|
109
|
+
return v;
|
|
110
|
+
});
|
|
111
|
+
if (missing)
|
|
112
|
+
skipped.push({ trailer: t, missing });
|
|
113
|
+
else
|
|
114
|
+
out.push(expanded);
|
|
115
|
+
}
|
|
116
|
+
return { trailers: out, skipped };
|
|
117
|
+
}
|
|
20
118
|
//# sourceMappingURL=policy.js.map
|
package/dist/policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
package/dist/record.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface ChangeRecord {
|
|
|
11
11
|
task: string;
|
|
12
12
|
/** How they intended to do it. Optional while a change is open. */
|
|
13
13
|
plan?: string;
|
|
14
|
+
/** Where the task came from: the thread, issue or ticket that asked for it, as a URL or id. */
|
|
15
|
+
ref?: string;
|
|
14
16
|
/** Who did the work. */
|
|
15
17
|
author: ChangeAuthor;
|
|
16
18
|
/** ISO 8601 timestamps. */
|
|
@@ -24,14 +26,19 @@ export interface ChangeRecord {
|
|
|
24
26
|
* original SHA, not the one the note is now attached to.
|
|
25
27
|
*/
|
|
26
28
|
commit?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Set when a capture hook opened the change from the harness's own event
|
|
31
|
+
* (the prompt, or a recorded run with nothing open) rather than an explicit
|
|
32
|
+
* `graft start`. A later `graft start` adopts such a change, naming the
|
|
33
|
+
* task and keeping the evidence, instead of refusing.
|
|
34
|
+
*/
|
|
35
|
+
capturedBy?: string;
|
|
27
36
|
}
|
|
28
37
|
export interface ChangeAuthor {
|
|
29
38
|
/** "agent" or "human". */
|
|
30
39
|
kind: "agent" | "human";
|
|
31
40
|
/** e.g. "claude-code", "cursor", or a person's handle. */
|
|
32
41
|
name: string;
|
|
33
|
-
/** Model identifier when the author is an agent. */
|
|
34
|
-
model?: string;
|
|
35
42
|
}
|
|
36
43
|
export type Evidence = CommandEvidence | NoteEvidence;
|
|
37
44
|
export interface CommandEvidence {
|
|
@@ -43,8 +50,22 @@ export interface CommandEvidence {
|
|
|
43
50
|
durationMs: number;
|
|
44
51
|
/** Trimmed tail of combined stdout/stderr, capped at EVIDENCE_OUTPUT_CAP bytes. */
|
|
45
52
|
output: string;
|
|
46
|
-
/** Optional label, e.g. "unit tests". */
|
|
53
|
+
/** Optional label, e.g. "unit tests". Kept in the note; the message line carries `name` when there is one. */
|
|
47
54
|
label?: string;
|
|
55
|
+
/** The policy catalog name this run satisfies, when it was run or matched by name. */
|
|
56
|
+
name?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Set when a harness reported the run through a hook ("claude-code")
|
|
59
|
+
* instead of Graft running it. The exit code and output are the harness's
|
|
60
|
+
* own, so this is still a pass or a fail, not a claim.
|
|
61
|
+
*/
|
|
62
|
+
via?: string;
|
|
63
|
+
/**
|
|
64
|
+
* True when the author attached a run they made themselves instead of
|
|
65
|
+
* letting Graft run the command. The exit code and output are their claim;
|
|
66
|
+
* readers show it as "attested", not "pass".
|
|
67
|
+
*/
|
|
68
|
+
attested?: true;
|
|
48
69
|
}
|
|
49
70
|
export interface NoteEvidence {
|
|
50
71
|
kind: "note";
|
|
@@ -62,8 +83,8 @@ export declare function evidenceSummary(evidence: Evidence[]): string;
|
|
|
62
83
|
export declare const TRAILER_KEYS: {
|
|
63
84
|
readonly change: "Graft-Change";
|
|
64
85
|
readonly task: "Graft-Task";
|
|
86
|
+
readonly ref: "Graft-Task-Ref";
|
|
65
87
|
readonly author: "Graft-Author";
|
|
66
|
-
readonly model: "Graft-Model";
|
|
67
88
|
readonly evidence: "Graft-Evidence";
|
|
68
89
|
};
|
|
69
90
|
export declare function trailersFor(record: ChangeRecord): Array<[string, string]>;
|
|
@@ -82,6 +103,8 @@ export declare const EVIDENCE_HEADER = "Evidence:";
|
|
|
82
103
|
*
|
|
83
104
|
* [pass unit tests] npm test (12.3s)
|
|
84
105
|
* [fail 1] npm run lint (0.4s)
|
|
106
|
+
* [attested go tests] go test ./...
|
|
107
|
+
* [attested fail 2 build] yarn build
|
|
85
108
|
* [note] manually verified in browser
|
|
86
109
|
*/
|
|
87
110
|
export declare function evidenceLines(evidence: Evidence[]): string[];
|
|
@@ -93,9 +116,13 @@ export declare function evidenceLines(evidence: Evidence[]): string[];
|
|
|
93
116
|
*/
|
|
94
117
|
export declare function parseMessageRecord(message: string, authoredAt: string): ChangeRecord | null;
|
|
95
118
|
/**
|
|
96
|
-
* Turn an argv into one
|
|
97
|
-
* unless it is plainly safe, so
|
|
98
|
-
*
|
|
119
|
+
* Turn an argv into one shell command string for the platform's shell.
|
|
120
|
+
* Every element is quoted unless it is plainly safe, so
|
|
121
|
+
* `node -e 'console.log("a b")'` survives the trip through /bin/sh, or
|
|
122
|
+
* through cmd.exe on Windows, where the quoting follows the rules the C
|
|
123
|
+
* runtime uses to split a command line and cmd's own metacharacters are
|
|
124
|
+
* escaped with `^`. A single element is returned as written, so
|
|
99
125
|
* `graft evidence -- "npm test && npm run lint"` still runs through the shell.
|
|
126
|
+
* A redirect or pipe given as its own element is therefore a literal argument.
|
|
100
127
|
*/
|
|
101
|
-
export declare function shellJoin(argv: string[]): string;
|
|
128
|
+
export declare function shellJoin(argv: string[], platform?: NodeJS.Platform): string;
|
package/dist/record.js
CHANGED
|
@@ -33,25 +33,25 @@ export function evidenceSummary(evidence) {
|
|
|
33
33
|
export const TRAILER_KEYS = {
|
|
34
34
|
change: "Graft-Change",
|
|
35
35
|
task: "Graft-Task",
|
|
36
|
+
ref: "Graft-Task-Ref",
|
|
36
37
|
author: "Graft-Author",
|
|
37
|
-
model: "Graft-Model",
|
|
38
38
|
evidence: "Graft-Evidence",
|
|
39
39
|
};
|
|
40
40
|
export function trailersFor(record) {
|
|
41
41
|
const t = [
|
|
42
42
|
[TRAILER_KEYS.change, record.id],
|
|
43
43
|
[TRAILER_KEYS.task, oneLine(record.task)],
|
|
44
|
-
[TRAILER_KEYS.author, `${record.author.kind}:${record.author.name}`],
|
|
45
44
|
];
|
|
46
|
-
if (record.
|
|
47
|
-
t.push([TRAILER_KEYS.
|
|
45
|
+
if (record.ref)
|
|
46
|
+
t.push([TRAILER_KEYS.ref, oneLine(record.ref)]);
|
|
47
|
+
t.push([TRAILER_KEYS.author, `${record.author.kind}:${record.author.name}`]);
|
|
48
48
|
t.push([TRAILER_KEYS.evidence, evidenceSummary(record.evidence)]);
|
|
49
49
|
return t;
|
|
50
50
|
}
|
|
51
51
|
export function parseTrailers(message) {
|
|
52
52
|
const out = {};
|
|
53
53
|
for (const line of message.split("\n")) {
|
|
54
|
-
const m = /^(Graft-[A-Za-z]+):\s*(.*)$/.exec(line);
|
|
54
|
+
const m = /^(Graft-[A-Za-z-]+):\s*(.*)$/.exec(line);
|
|
55
55
|
if (m)
|
|
56
56
|
out[m[1]] = m[2].trim();
|
|
57
57
|
}
|
|
@@ -74,13 +74,20 @@ const MESSAGE_LINE_CAP = 200;
|
|
|
74
74
|
*
|
|
75
75
|
* [pass unit tests] npm test (12.3s)
|
|
76
76
|
* [fail 1] npm run lint (0.4s)
|
|
77
|
+
* [attested go tests] go test ./...
|
|
78
|
+
* [attested fail 2 build] yarn build
|
|
77
79
|
* [note] manually verified in browser
|
|
78
80
|
*/
|
|
79
81
|
export function evidenceLines(evidence) {
|
|
80
82
|
return evidence.map((ev) => {
|
|
81
|
-
|
|
83
|
+
// A catalog name is the run's identity, so it is what the message keeps; a free label rides in the note.
|
|
84
|
+
const shown = ev.kind === "command" && ev.name ? ev.name : ev.label;
|
|
85
|
+
const label = shown ? ` ${bracketSafe(shown)}` : "";
|
|
82
86
|
if (ev.kind === "note")
|
|
83
87
|
return ` [note${label}] ${clip(oneLine(ev.text))}`;
|
|
88
|
+
const failed = ev.exitCode === 0 ? "" : ` fail ${ev.exitCode}`;
|
|
89
|
+
if (ev.attested)
|
|
90
|
+
return ` [attested${failed}${label}] ${clip(oneLine(ev.command))}`;
|
|
84
91
|
const status = ev.exitCode === 0 ? "pass" : `fail ${ev.exitCode}`;
|
|
85
92
|
return ` [${status}${label}] ${clip(oneLine(ev.command))} (${(ev.durationMs / 1000).toFixed(1)}s)`;
|
|
86
93
|
});
|
|
@@ -89,7 +96,7 @@ export function evidenceLines(evidence) {
|
|
|
89
96
|
function bracketSafe(label) {
|
|
90
97
|
return oneLine(label).replace(/[[\]]/g, "").slice(0, 60);
|
|
91
98
|
}
|
|
92
|
-
const EVIDENCE_LINE = /^\s*\[(pass|fail (-?\d+)|note)(?: ([^\]]*))?\] (.*)$/;
|
|
99
|
+
const EVIDENCE_LINE = /^\s*\[(pass|fail (-?\d+)|note|attested(?: fail (-?\d+))?)(?: ([^\]]*))?\] (.*)$/;
|
|
93
100
|
const DURATION = /^(.*) \((\d+(?:\.\d+)?)s\)$/;
|
|
94
101
|
/**
|
|
95
102
|
* Rebuild a record from a commit message alone: trailers, the Plan: block and
|
|
@@ -109,31 +116,36 @@ export function parseMessageRecord(message, authoredAt) {
|
|
|
109
116
|
const m = EVIDENCE_LINE.exec(line);
|
|
110
117
|
if (!m)
|
|
111
118
|
continue;
|
|
112
|
-
const
|
|
113
|
-
|
|
119
|
+
const [, status, failCode, attestedFailCode, rawLabel, tail] = m;
|
|
120
|
+
const label = rawLabel || undefined;
|
|
121
|
+
if (status === "note") {
|
|
122
|
+
evidence.push({ kind: "note", at: authoredAt, text: tail, label });
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (status.startsWith("attested")) {
|
|
126
|
+
const exitCode = attestedFailCode ? Number(attestedFailCode) : 0;
|
|
127
|
+
evidence.push({ kind: "command", at: authoredAt, command: tail, exitCode, durationMs: 0, output: "", label, attested: true });
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
let rest = tail;
|
|
114
131
|
let durationMs = 0;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
durationMs = Math.round(Number(d[2]) * 1000);
|
|
120
|
-
}
|
|
132
|
+
const d = DURATION.exec(rest);
|
|
133
|
+
if (d) {
|
|
134
|
+
rest = d[1];
|
|
135
|
+
durationMs = Math.round(Number(d[2]) * 1000);
|
|
121
136
|
}
|
|
122
|
-
|
|
123
|
-
evidence.push({ kind: "note", at: authoredAt, text: rest, label });
|
|
124
|
-
else
|
|
125
|
-
evidence.push({ kind: "command", at: authoredAt, command: rest, exitCode: m[2] ? Number(m[2]) : 0, durationMs, output: "", label });
|
|
137
|
+
evidence.push({ kind: "command", at: authoredAt, command: rest, exitCode: failCode ? Number(failCode) : 0, durationMs, output: "", label });
|
|
126
138
|
}
|
|
127
139
|
const [kind, ...name] = (trailers[TRAILER_KEYS.author] ?? "human:unknown").split(":");
|
|
128
140
|
return {
|
|
129
141
|
version: 1,
|
|
130
142
|
id,
|
|
131
143
|
task: trailers[TRAILER_KEYS.task] ?? lines[0],
|
|
144
|
+
ref: trailers[TRAILER_KEYS.ref] || undefined,
|
|
132
145
|
plan: plan || undefined,
|
|
133
146
|
author: {
|
|
134
147
|
kind: kind === "agent" ? "agent" : "human",
|
|
135
148
|
name: name.join(":") || "unknown",
|
|
136
|
-
model: trailers[TRAILER_KEYS.model] || undefined,
|
|
137
149
|
},
|
|
138
150
|
startedAt: authoredAt,
|
|
139
151
|
landedAt: authoredAt,
|
|
@@ -170,15 +182,35 @@ function clip(s) {
|
|
|
170
182
|
return s.length > MESSAGE_LINE_CAP ? s.slice(0, MESSAGE_LINE_CAP - 1) + "…" : s;
|
|
171
183
|
}
|
|
172
184
|
const SAFE_ARG = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
185
|
+
const WIN_SAFE_ARG = /^[A-Za-z0-9_@+=:,./\\-]+$/;
|
|
186
|
+
const WIN_META = /[()%!^"<>&|]/g;
|
|
173
187
|
/**
|
|
174
|
-
* Turn an argv into one
|
|
175
|
-
* unless it is plainly safe, so
|
|
176
|
-
*
|
|
188
|
+
* Turn an argv into one shell command string for the platform's shell.
|
|
189
|
+
* Every element is quoted unless it is plainly safe, so
|
|
190
|
+
* `node -e 'console.log("a b")'` survives the trip through /bin/sh, or
|
|
191
|
+
* through cmd.exe on Windows, where the quoting follows the rules the C
|
|
192
|
+
* runtime uses to split a command line and cmd's own metacharacters are
|
|
193
|
+
* escaped with `^`. A single element is returned as written, so
|
|
177
194
|
* `graft evidence -- "npm test && npm run lint"` still runs through the shell.
|
|
195
|
+
* A redirect or pipe given as its own element is therefore a literal argument.
|
|
178
196
|
*/
|
|
179
|
-
export function shellJoin(argv) {
|
|
197
|
+
export function shellJoin(argv, platform = process.platform) {
|
|
180
198
|
if (argv.length === 1)
|
|
181
199
|
return argv[0];
|
|
182
|
-
|
|
200
|
+
const quote = platform === "win32" ? winQuote : posixQuote;
|
|
201
|
+
return argv.map(quote).join(" ");
|
|
202
|
+
}
|
|
203
|
+
function posixQuote(a) {
|
|
204
|
+
return SAFE_ARG.test(a) ? a : `'${a.replace(/'/g, `'\\''`)}'`;
|
|
205
|
+
}
|
|
206
|
+
function winQuote(a) {
|
|
207
|
+
if (WIN_SAFE_ARG.test(a))
|
|
208
|
+
return a;
|
|
209
|
+
// Backslashes only escape when they precede a quote, so double those runs
|
|
210
|
+
// and the trailing run, then escape quotes, then wrap in double quotes.
|
|
211
|
+
const inner = a.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1");
|
|
212
|
+
// cmd.exe reads the line before the program does; `^` makes it pass the
|
|
213
|
+
// metacharacters, including the quotes, through untouched.
|
|
214
|
+
return `"${inner}"`.replace(WIN_META, "^$&");
|
|
183
215
|
}
|
|
184
216
|
//# sourceMappingURL=record.js.map
|
package/dist/record.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.js","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"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"}
|
package/dist/redact.d.ts
CHANGED
|
@@ -22,5 +22,12 @@ export declare function redact(text: string, env?: NodeJS.ProcessEnv): string;
|
|
|
22
22
|
* file name anywhere in the tree, one with a slash is anchored at the root.
|
|
23
23
|
*/
|
|
24
24
|
export declare function looksLikeSecretFile(path: string, extra?: string[]): boolean;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* The words of a shell command that name a credential file, so the output of
|
|
27
|
+
* `cat nova.json && go test ./...` is withheld from the record instead of
|
|
28
|
+
* copying the key into history. Quotes and `--flag=` prefixes are stripped;
|
|
29
|
+
* the split is on whitespace and shell operators, not a real parse.
|
|
30
|
+
*/
|
|
31
|
+
export declare function secretFilesNamed(command: string, extra?: string[]): string[];
|
|
32
|
+
/** Minimal glob: `**` spans directories (`a/**` is everything under a), `*` and `?` stay within one segment. */
|
|
26
33
|
export declare function globToRegExp(glob: string): RegExp;
|
package/dist/redact.js
CHANGED
|
@@ -51,14 +51,29 @@ export function looksLikeSecretFile(path, extra = []) {
|
|
|
51
51
|
return false;
|
|
52
52
|
return SECRET_FILE_PATTERNS.some((re) => re.test(p)) || extra.some((g) => globToRegExp(g).test(p));
|
|
53
53
|
}
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The words of a shell command that name a credential file, so the output of
|
|
56
|
+
* `cat nova.json && go test ./...` is withheld from the record instead of
|
|
57
|
+
* copying the key into history. Quotes and `--flag=` prefixes are stripped;
|
|
58
|
+
* the split is on whitespace and shell operators, not a real parse.
|
|
59
|
+
*/
|
|
60
|
+
export function secretFilesNamed(command, extra = []) {
|
|
61
|
+
const words = command
|
|
62
|
+
.split(/[\s;&|<>()`=]+/)
|
|
63
|
+
.map((w) => w.replace(/^["']+|["']+$/g, ""))
|
|
64
|
+
.filter((w) => w && !w.startsWith("-"));
|
|
65
|
+
return [...new Set(words.filter((w) => looksLikeSecretFile(w, extra)))];
|
|
66
|
+
}
|
|
67
|
+
/** Minimal glob: `**` spans directories (`a/**` is everything under a), `*` and `?` stay within one segment. */
|
|
55
68
|
export function globToRegExp(glob) {
|
|
56
69
|
const body = glob
|
|
57
70
|
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
58
|
-
.replace(
|
|
71
|
+
.replace(/\*\*\//g, "\u0000")
|
|
72
|
+
.replace(/\*\*/g, "\u0001")
|
|
59
73
|
.replace(/\*/g, "[^/]*")
|
|
60
74
|
.replace(/\?/g, "[^/]")
|
|
61
|
-
.replace(/\u0000/g, "(?:.*/)?")
|
|
75
|
+
.replace(/\u0000/g, "(?:.*/)?")
|
|
76
|
+
.replace(/\u0001/g, ".*");
|
|
62
77
|
return new RegExp(glob.includes("/") ? `^${body}$` : `(^|/)${body}$`);
|
|
63
78
|
}
|
|
64
79
|
//# sourceMappingURL=redact.js.map
|
package/dist/redact.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,gFAAgF;AAChF,sDAAsD;AACtD,MAAM,eAAe,GAAG,4GAA4G,CAAC;AACrI,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,MAAM,KAAK,GAAsC,EAAE,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,iBAAiB;YAAE,SAAS;QACzD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,MAAyB,OAAO,CAAC,GAAG;IACvE,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,oBAAoB,GAAa;IACrC,wBAAwB,EAAE,oCAAoC;IAC9D,oCAAoC;IACpC,2CAA2C;IAC3C,kDAAkD;IAClD,+BAA+B;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,QAAkB,EAAE;IACpE,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACnC,IAAI,yCAAyC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrG,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"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"}
|