@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/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;AAEnE,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,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
- return { ...DEFAULT_POLICY, ...parsed, version: 1 };
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
@@ -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;AA6BjC,MAAM,CAAC,MAAM,cAAc,GAAW,EAAE,OAAO,EAAE,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;AAE5E,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;QAClD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,WAAW,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,cAAc,CAAC;QAC5E,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,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 POSIX shell command string. Every element is quoted
97
- * unless it is plainly safe, so `node -e 'console.log("a b")'` survives the
98
- * trip through /bin/sh. A single element is returned as written, so
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.author.model)
47
- t.push([TRAILER_KEYS.model, record.author.model]);
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
- const label = ev.label ? ` ${bracketSafe(ev.label)}` : "";
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 label = m[3] || undefined;
113
- let rest = m[4];
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
- if (m[1] !== "note") {
116
- const d = DURATION.exec(rest);
117
- if (d) {
118
- rest = d[1];
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
- if (m[1] === "note")
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 POSIX shell command string. Every element is quoted
175
- * unless it is plainly safe, so `node -e 'console.log("a b")'` survives the
176
- * trip through /bin/sh. A single element is returned as written, so
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
- return argv.map((a) => (SAFE_ARG.test(a) ? a : `'${a.replace(/'/g, `'\\''`)}'`)).join(" ");
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
@@ -1 +1 @@
1
- {"version":3,"file":"record.js","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"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"}
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
- /** Minimal glob: `**` spans directories, `*` and `?` stay within one segment. */
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
- /** Minimal glob: `**` spans directories, `*` and `?` stay within one segment. */
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(/\*\*\/?/g, "\u0000")
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
@@ -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,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,IAAI,GAAG,IAAI;SACd,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC;SACpC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC;SAC7B,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC;SACvB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAClC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fourshore/graft-core",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Graft change records on plain git: the record model, git plumbing, start/evidence/land/log.",
5
5
  "license": "MIT",
6
6
  "type": "module",