@garygentry/system1-core 0.4.1 → 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/dist/config/consent.d.ts +11 -0
- package/dist/config/consent.d.ts.map +1 -1
- package/dist/config/consent.js +56 -2
- package/dist/config/consent.js.map +1 -1
- package/dist/config/load.d.ts +3 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +14 -1
- package/dist/config/load.js.map +1 -1
- package/dist/decide.d.ts +2 -0
- package/dist/decide.d.ts.map +1 -1
- package/dist/decide.js +2 -1
- package/dist/decide.js.map +1 -1
- package/dist/guard/check.d.ts +44 -0
- package/dist/guard/check.d.ts.map +1 -0
- package/dist/guard/check.js +325 -0
- package/dist/guard/check.js.map +1 -0
- package/dist/guard/done-check.d.ts +67 -0
- package/dist/guard/done-check.d.ts.map +1 -0
- package/dist/guard/done-check.js +165 -0
- package/dist/guard/done-check.js.map +1 -0
- package/dist/guard/gather.d.ts +65 -0
- package/dist/guard/gather.d.ts.map +1 -0
- package/dist/guard/gather.js +288 -0
- package/dist/guard/gather.js.map +1 -0
- package/dist/guard/git.d.ts +15 -0
- package/dist/guard/git.d.ts.map +1 -0
- package/dist/guard/git.js +44 -0
- package/dist/guard/git.js.map +1 -0
- package/dist/guard/packs.d.ts +51 -0
- package/dist/guard/packs.d.ts.map +1 -0
- package/dist/guard/packs.js +160 -0
- package/dist/guard/packs.js.map +1 -0
- package/dist/guard/state.d.ts +94 -0
- package/dist/guard/state.d.ts.map +1 -0
- package/dist/guard/state.js +181 -0
- package/dist/guard/state.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/opportunities/backlog.d.ts.map +1 -1
- package/dist/opportunities/backlog.js +9 -34
- package/dist/opportunities/backlog.js.map +1 -1
- package/dist/prepare.d.ts +2 -0
- package/dist/prepare.d.ts.map +1 -1
- package/dist/prepare.js +1 -0
- package/dist/prepare.js.map +1 -1
- package/dist/run/spend.d.ts +3 -0
- package/dist/run/spend.d.ts.map +1 -1
- package/dist/run/spend.js +1 -0
- package/dist/run/spend.js.map +1 -1
- package/dist/sources/read.d.ts +2 -0
- package/dist/sources/read.d.ts.map +1 -1
- package/dist/sources/read.js +31 -17
- package/dist/sources/read.js.map +1 -1
- package/dist/sources/types.d.ts +4 -1
- package/dist/sources/types.d.ts.map +1 -1
- package/dist/store/file.d.ts +25 -0
- package/dist/store/file.d.ts.map +1 -0
- package/dist/store/file.js +111 -0
- package/dist/store/file.js.map +1 -0
- package/dist/tools/context.d.ts +3 -1
- package/dist/tools/context.d.ts.map +1 -1
- package/dist/tools/context.js +2 -1
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/doctor.d.ts +8 -1
- package/dist/tools/doctor.d.ts.map +1 -1
- package/dist/tools/doctor.js +83 -1
- package/dist/tools/doctor.js.map +1 -1
- package/dist/tools/hook.d.ts +46 -0
- package/dist/tools/hook.d.ts.map +1 -0
- package/dist/tools/hook.js +156 -0
- package/dist/tools/hook.js.map +1 -0
- package/dist/tools/schemas.d.ts +24 -0
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +15 -0
- package/dist/tools/schemas.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { SourceSpec } from "../sources/types.js";
|
|
2
|
+
import type { PackContext } from "./done-check.js";
|
|
3
|
+
import { type GuardSession } from "./state.js";
|
|
4
|
+
/** git's empty tree: the base of a session that started before the first commit. */
|
|
5
|
+
export declare const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
6
|
+
/** The most criteria one check sends; the rest are listed for the agent to check. */
|
|
7
|
+
export declare const MAX_CRITERIA = 30;
|
|
8
|
+
/** A bullet longer than this is not a checkable criterion. */
|
|
9
|
+
export declare const MAX_CRITERION_CHARS = 400;
|
|
10
|
+
/** The most untracked files read into one check. */
|
|
11
|
+
export declare const MAX_UNTRACKED = 200;
|
|
12
|
+
/** The most whole files the criteria can pull in by naming them. */
|
|
13
|
+
export declare const MAX_NAMED_FILES = 10;
|
|
14
|
+
/** …and at most this many for any one criterion. */
|
|
15
|
+
export declare const MAX_NAMED_PER_CRITERION = 3;
|
|
16
|
+
/**
|
|
17
|
+
* Tracked files a criterion names: by path (`src/greet.ts`), by file name
|
|
18
|
+
* (`greet.ts`, `README.md`), or by a distinctive stem (`README`, `CHANGELOG`,
|
|
19
|
+
* five characters or more, as a whole word). Case-insensitive; in the order
|
|
20
|
+
* the criteria name them.
|
|
21
|
+
*/
|
|
22
|
+
export declare function namedFiles(criteria: readonly Criterion[], tracked: readonly string[]): string[];
|
|
23
|
+
export interface Criterion {
|
|
24
|
+
text: string;
|
|
25
|
+
/** Repo-relative path of the criteria file, and the bullet's line in it. */
|
|
26
|
+
file: string;
|
|
27
|
+
line: number;
|
|
28
|
+
}
|
|
29
|
+
export interface SelfCheck extends Criterion {
|
|
30
|
+
/** Why it isn't sent: said to the agent in the block reason or message. */
|
|
31
|
+
why: string;
|
|
32
|
+
}
|
|
33
|
+
export interface Gathered {
|
|
34
|
+
/** Sent to the model, two questions each. */
|
|
35
|
+
criteria: Criterion[];
|
|
36
|
+
/** Never sent: for the agent to check itself. */
|
|
37
|
+
checkYourself: SelfCheck[];
|
|
38
|
+
/** Said alongside the outcome, e.g. a criteria file changed mid-session. */
|
|
39
|
+
notes: string[];
|
|
40
|
+
/** The change, for `prepare()`. */
|
|
41
|
+
sources: SourceSpec[];
|
|
42
|
+
/**
|
|
43
|
+
* Files the criteria name, whole, for context. Not part of the change: a
|
|
44
|
+
* session that changed nothing is never judged just because a file was named.
|
|
45
|
+
*/
|
|
46
|
+
context: SourceSpec[];
|
|
47
|
+
/**
|
|
48
|
+
* The configured evidence files (a test log, say), sent with the change.
|
|
49
|
+
* Not part of it: a stop with no work is never judged because a log exists.
|
|
50
|
+
*/
|
|
51
|
+
evidence: SourceSpec[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The bullets of a markdown file: `-`, `*`, `+`, `1.` or `1)`, with an
|
|
55
|
+
* optional `[ ]` box. Ticked boxes (`[x]`) are done and dropped. Headings,
|
|
56
|
+
* prose and fenced code are not criteria. An indented line right after a
|
|
57
|
+
* bullet continues it.
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseBullets(text: string): Array<{
|
|
60
|
+
text: string;
|
|
61
|
+
line: number;
|
|
62
|
+
}>;
|
|
63
|
+
/** Gather the criteria and the change for one Stop. Sends nothing. */
|
|
64
|
+
export declare function gather(ctx: PackContext, session: GuardSession): Promise<Gathered>;
|
|
65
|
+
//# sourceMappingURL=gather.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../src/guard/gather.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,YAAY,CAAA;AAElE,oFAAoF;AACpF,eAAO,MAAM,UAAU,6CAA6C,CAAA;AACpE,qFAAqF;AACrF,eAAO,MAAM,YAAY,KAAK,CAAA;AAC9B,8DAA8D;AAC9D,eAAO,MAAM,mBAAmB,MAAM,CAAA;AACtC,oDAAoD;AACpD,eAAO,MAAM,aAAa,MAAM,CAAA;AAYhC,oEAAoE;AACpE,eAAO,MAAM,eAAe,KAAK,CAAA;AACjC,oDAAoD;AACpD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAoC/F;AAmBD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,iDAAiD;IACjD,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,mCAAmC;IACnC,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB;;;OAGG;IACH,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB;;;OAGG;IACH,QAAQ,EAAE,UAAU,EAAE,CAAA;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAwChF;AA0DD,sEAAsE;AACtE,wBAAsB,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiGvF"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `done-check`, part one: what to judge (M10 §5). The criteria come from the
|
|
3
|
+
* configured files' bullets, as they were when the session started; the
|
|
4
|
+
* change is this session's diff against its base, its untracked files, and
|
|
5
|
+
* any evidence files. Nothing here sends anything: the sources go through
|
|
6
|
+
* `prepare()` (excludes, scrubbing, size) before any question is asked.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, lstatSync } from "node:fs";
|
|
9
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
10
|
+
import { DecisionsError } from "../errors.js";
|
|
11
|
+
import { lintStatement } from "../spec/lint.js";
|
|
12
|
+
import { snapshotCriteria } from "./done-check.js";
|
|
13
|
+
import { git } from "./git.js";
|
|
14
|
+
import { MAX_CRITERIA_FILES } from "./state.js";
|
|
15
|
+
/** git's empty tree: the base of a session that started before the first commit. */
|
|
16
|
+
export const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
17
|
+
/** The most criteria one check sends; the rest are listed for the agent to check. */
|
|
18
|
+
export const MAX_CRITERIA = 30;
|
|
19
|
+
/** A bullet longer than this is not a checkable criterion. */
|
|
20
|
+
export const MAX_CRITERION_CHARS = 400;
|
|
21
|
+
/** The most untracked files read into one check. */
|
|
22
|
+
export const MAX_UNTRACKED = 200;
|
|
23
|
+
/** Never part of the change: decide's own state, and dependencies at any depth. */
|
|
24
|
+
const NOT_IN_DIFF = [":(exclude).system1/", ":(exclude,glob)**/node_modules/**"];
|
|
25
|
+
const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
|
|
26
|
+
/** git's `-z` path list, without decide's state or dependencies. */
|
|
27
|
+
function listed(out) {
|
|
28
|
+
return out
|
|
29
|
+
.split("\0")
|
|
30
|
+
.filter((p) => p && !p.startsWith(".system1/") && !/(^|\/)node_modules(\/|$)/.test(p));
|
|
31
|
+
}
|
|
32
|
+
/** The most whole files the criteria can pull in by naming them. */
|
|
33
|
+
export const MAX_NAMED_FILES = 10;
|
|
34
|
+
/** …and at most this many for any one criterion. */
|
|
35
|
+
export const MAX_NAMED_PER_CRITERION = 3;
|
|
36
|
+
/**
|
|
37
|
+
* Tracked files a criterion names: by path (`src/greet.ts`), by file name
|
|
38
|
+
* (`greet.ts`, `README.md`), or by a distinctive stem (`README`, `CHANGELOG`,
|
|
39
|
+
* five characters or more, as a whole word). Case-insensitive; in the order
|
|
40
|
+
* the criteria name them.
|
|
41
|
+
*/
|
|
42
|
+
export function namedFiles(criteria, tracked) {
|
|
43
|
+
// Each path's name and stem once, and each criterion's tokens once: this runs
|
|
44
|
+
// inside the hook's latency budget, over every tracked file.
|
|
45
|
+
const byName = new Map();
|
|
46
|
+
const byStem = new Map();
|
|
47
|
+
const add = (map, key, path) => map.set(key, [...(map.get(key) ?? []), path]);
|
|
48
|
+
for (const path of tracked) {
|
|
49
|
+
const lower = path.toLowerCase();
|
|
50
|
+
const name = lower.slice(lower.lastIndexOf("/") + 1);
|
|
51
|
+
add(byName, name, path);
|
|
52
|
+
const stem = name.includes(".") ? name.slice(0, name.lastIndexOf(".")) : name;
|
|
53
|
+
if (stem.length >= 5 && stem !== name)
|
|
54
|
+
add(byStem, stem, path);
|
|
55
|
+
}
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const c of criteria) {
|
|
58
|
+
const text = c.text.toLowerCase();
|
|
59
|
+
const tokens = new Set(text.split(/[^a-z0-9_./-]+/).flatMap((t) => [t, t.replace(/[./-]+$/, "")]));
|
|
60
|
+
const words = new Set(text.split(/[^a-z0-9_-]+/));
|
|
61
|
+
// Ranked: a path named in full, then a file name, then a distinctive stem;
|
|
62
|
+
// a few per criterion, so one common word can't crowd out the rest.
|
|
63
|
+
const byPath = [...tokens]
|
|
64
|
+
.filter((t) => t.includes("/"))
|
|
65
|
+
.flatMap((t) => tracked.filter((p) => p.toLowerCase() === t));
|
|
66
|
+
const byFile = [...tokens].flatMap((t) => byName.get(t) ?? []);
|
|
67
|
+
const stems = [...words].flatMap((w) => {
|
|
68
|
+
const hits = byStem.get(w) ?? [];
|
|
69
|
+
return hits.length <= 2 ? hits : []; // a stem many files share names none of them
|
|
70
|
+
});
|
|
71
|
+
const picked = [...new Set([...byPath, ...byFile, ...stems])].filter((p) => !out.includes(p));
|
|
72
|
+
out.push(...picked.slice(0, MAX_NAMED_PER_CRITERION));
|
|
73
|
+
if (out.length >= MAX_NAMED_FILES)
|
|
74
|
+
return out.slice(0, MAX_NAMED_FILES);
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Ignored files (not whole ignored directories, such as build output) changed
|
|
80
|
+
* since the session started. They are never read: an ignore rule is the
|
|
81
|
+
* user's to keep private. But a change the check can't see is said out loud.
|
|
82
|
+
*/
|
|
83
|
+
function changedIgnored(repoRoot, paths, since) {
|
|
84
|
+
return paths.filter((p) => {
|
|
85
|
+
if (p.endsWith("/"))
|
|
86
|
+
return false;
|
|
87
|
+
try {
|
|
88
|
+
const stat = lstatSync(resolve(repoRoot, p));
|
|
89
|
+
return stat.isFile() && stat.mtimeMs > since;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The bullets of a markdown file: `-`, `*`, `+`, `1.` or `1)`, with an
|
|
98
|
+
* optional `[ ]` box. Ticked boxes (`[x]`) are done and dropped. Headings,
|
|
99
|
+
* prose and fenced code are not criteria. An indented line right after a
|
|
100
|
+
* bullet continues it.
|
|
101
|
+
*/
|
|
102
|
+
export function parseBullets(text) {
|
|
103
|
+
const out = [];
|
|
104
|
+
let fence;
|
|
105
|
+
let comment = false;
|
|
106
|
+
let open;
|
|
107
|
+
text.split(/\r?\n/).forEach((raw, i) => {
|
|
108
|
+
if (comment || /^\s*<!--/.test(raw)) {
|
|
109
|
+
comment = !raw.includes("-->");
|
|
110
|
+
open = undefined;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// A fence closes only with the same character, at least as many of it.
|
|
114
|
+
const run = /^\s*(`{3,}|~{3,})/.exec(raw)?.[1];
|
|
115
|
+
if (run) {
|
|
116
|
+
if (!fence)
|
|
117
|
+
fence = run;
|
|
118
|
+
else if (run[0] === fence[0] && run.length >= fence.length && !raw.trim().slice(run.length))
|
|
119
|
+
fence = undefined;
|
|
120
|
+
open = undefined;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (fence)
|
|
124
|
+
return;
|
|
125
|
+
if (/^\s*([-*_])(\s*\1){2,}\s*$/.test(raw)) {
|
|
126
|
+
open = undefined; // a horizontal rule
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const bullet = /^\s*(?:[-*+]|\d{1,3}[.)])\s+(?:\[( |x|X)\]\s+)?(.*\S)\s*$/.exec(raw);
|
|
130
|
+
if (bullet) {
|
|
131
|
+
open = undefined;
|
|
132
|
+
if (bullet[1] === "x" || bullet[1] === "X")
|
|
133
|
+
return;
|
|
134
|
+
open = { text: bullet[2] ?? "", line: i + 1 };
|
|
135
|
+
out.push(open);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (open && /^\s{2,}\S/.test(raw)) {
|
|
139
|
+
open.text = `${open.text} ${raw.trim()}`;
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
open = undefined;
|
|
143
|
+
});
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
/** A configured path as the repo-relative form snapshots use, or undefined if it leaves the repo. */
|
|
147
|
+
function repoPath(repoRoot, path) {
|
|
148
|
+
const rel = relative(repoRoot, resolve(repoRoot, path));
|
|
149
|
+
if (!rel || rel.startsWith("..") || isAbsolute(rel))
|
|
150
|
+
return undefined;
|
|
151
|
+
return rel.split("\\").join("/");
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Each criteria file's text as the session started. The files are the ones
|
|
155
|
+
* snapshotted at SessionStart plus any configured now, so editing the config
|
|
156
|
+
* mid-session can add criteria but not drop them. An edited or emptied file
|
|
157
|
+
* is checked against its original, and the note says so. A file created
|
|
158
|
+
* mid-session is used as it is (it can only add checks). A file too long to
|
|
159
|
+
* snapshot is never used, whether it changed or not.
|
|
160
|
+
*/
|
|
161
|
+
function criteriaTexts(ctx, session, notes) {
|
|
162
|
+
const configured = ctx.pack.criteria
|
|
163
|
+
.map((p) => repoPath(ctx.repoRoot, p))
|
|
164
|
+
.filter((p) => p !== undefined);
|
|
165
|
+
const paths = [...new Set([...session.criteria.map((c) => c.path), ...configured])];
|
|
166
|
+
if (paths.length > MAX_CRITERIA_FILES) {
|
|
167
|
+
notes.push(`only the first ${MAX_CRITERIA_FILES} criteria files were read`);
|
|
168
|
+
}
|
|
169
|
+
const out = [];
|
|
170
|
+
for (const file of paths.slice(0, MAX_CRITERIA_FILES)) {
|
|
171
|
+
const atStart = session.criteria.find((c) => c.path === file);
|
|
172
|
+
if (atStart && !configured.includes(file)) {
|
|
173
|
+
notes.push(`${file} was removed from the criteria config during the session; still checked`);
|
|
174
|
+
}
|
|
175
|
+
const now = snapshotCriteria(ctx.repoRoot, [file])[0];
|
|
176
|
+
const text = atStart ? atStart.text : now?.text;
|
|
177
|
+
if ((atStart ?? now) && text === undefined) {
|
|
178
|
+
notes.push(`${file} is too long to read as criteria`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (text === undefined)
|
|
182
|
+
continue;
|
|
183
|
+
if (atStart && now?.sha256 !== atStart.sha256) {
|
|
184
|
+
notes.push(`${file} changed since the session started; checked against the original`);
|
|
185
|
+
}
|
|
186
|
+
out.push({ file, text });
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
function isRegularFile(repoRoot, path) {
|
|
191
|
+
try {
|
|
192
|
+
return lstatSync(resolve(repoRoot, path)).isFile();
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** Gather the criteria and the change for one Stop. Sends nothing. */
|
|
199
|
+
export async function gather(ctx, session) {
|
|
200
|
+
const notes = [];
|
|
201
|
+
const criteria = [];
|
|
202
|
+
const checkYourself = [];
|
|
203
|
+
for (const { file, text } of criteriaTexts(ctx, session, notes)) {
|
|
204
|
+
for (const bullet of parseBullets(text)) {
|
|
205
|
+
const c = { text: bullet.text, file, line: bullet.line };
|
|
206
|
+
if (bullet.text.length > MAX_CRITERION_CHARS) {
|
|
207
|
+
checkYourself.push({ ...c, why: "too long to check as one criterion" });
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const finding = lintStatement(bullet.text)[0];
|
|
211
|
+
if (finding) {
|
|
212
|
+
checkYourself.push({ ...c, why: `${finding.message}: check it yourself` });
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (criteria.length >= MAX_CRITERIA) {
|
|
216
|
+
checkYourself.push({ ...c, why: `over the ${MAX_CRITERIA}-criterion limit of one check` });
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
criteria.push(c);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const sources = [];
|
|
223
|
+
const context = [];
|
|
224
|
+
const evidence = [];
|
|
225
|
+
if (criteria.length > 0) {
|
|
226
|
+
const git_ = (args) => git(ctx.repoRoot, args, { signal: ctx.signal });
|
|
227
|
+
let range;
|
|
228
|
+
if (session.base) {
|
|
229
|
+
try {
|
|
230
|
+
await git_(["cat-file", "-e", `${session.base}^{commit}`]);
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
if (error.name === "AbortError")
|
|
234
|
+
throw error;
|
|
235
|
+
throw new DecisionsError("source-error", "the session's base commit no longer exists (history was rewritten), so this session's change can't be found");
|
|
236
|
+
}
|
|
237
|
+
range = session.base;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
// The empty tree, as this repo's hash function names it (SHA-1 or SHA-256).
|
|
241
|
+
range = (await git_(["hash-object", "-t", "tree", devNull])).trim();
|
|
242
|
+
}
|
|
243
|
+
sources.push({ kind: "diff", range, paths: [".", ...NOT_IN_DIFF] });
|
|
244
|
+
const untracked = listed(await git_(["ls-files", "--others", "--exclude-standard", "-z"]))
|
|
245
|
+
.filter((p) => isRegularFile(ctx.repoRoot, p))
|
|
246
|
+
.sort();
|
|
247
|
+
if (untracked.length > MAX_UNTRACKED) {
|
|
248
|
+
notes.push(`${untracked.length - MAX_UNTRACKED} untracked files were left out (over ${MAX_UNTRACKED})`);
|
|
249
|
+
}
|
|
250
|
+
for (const path of untracked.slice(0, MAX_UNTRACKED)) {
|
|
251
|
+
sources.push({ kind: "file", path, optional: true });
|
|
252
|
+
}
|
|
253
|
+
const hidden = changedIgnored(ctx.repoRoot, listed(await git_([
|
|
254
|
+
"ls-files",
|
|
255
|
+
"--others",
|
|
256
|
+
"--ignored",
|
|
257
|
+
"--exclude-standard",
|
|
258
|
+
"--directory",
|
|
259
|
+
"-z",
|
|
260
|
+
])), Date.parse(session.startedAt));
|
|
261
|
+
if (hidden.length > 0) {
|
|
262
|
+
const shown = hidden.slice(0, 5).join(", ");
|
|
263
|
+
notes.push(`ignored files changed during the session and weren't checked: ${shown}${hidden.length > 5 ? ` and ${hidden.length - 5} more` : ""}`);
|
|
264
|
+
}
|
|
265
|
+
// Files a criterion names ("README documents…", "src/greet.ts returns…"),
|
|
266
|
+
// whole and as they are now: "not done" leaves no diff, so without them
|
|
267
|
+
// the model couldn't judge a criterion about work that wasn't done.
|
|
268
|
+
const included = new Set(untracked.slice(0, MAX_UNTRACKED));
|
|
269
|
+
const tracked = listed(await git_(["ls-files", "-z"]));
|
|
270
|
+
for (const path of namedFiles(criteria, tracked)) {
|
|
271
|
+
if (included.has(path) || !isRegularFile(ctx.repoRoot, path))
|
|
272
|
+
continue;
|
|
273
|
+
included.add(path);
|
|
274
|
+
context.push({ kind: "file", path, optional: true });
|
|
275
|
+
}
|
|
276
|
+
for (const configured of ctx.pack.evidence) {
|
|
277
|
+
const path = repoPath(ctx.repoRoot, configured);
|
|
278
|
+
if (path && existsSync(resolve(ctx.repoRoot, path)) && isRegularFile(ctx.repoRoot, path)) {
|
|
279
|
+
evidence.push({ kind: "file", path, optional: true });
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
notes.push(`evidence file ${configured} was not found`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return { criteria, checkYourself, notes, sources, context, evidence };
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=gather.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gather.js","sourceRoot":"","sources":["../../src/guard/gather.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface GitOptions {
|
|
2
|
+
/** Aborts the git process: the hook's deadline. */
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
maxBuffer?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Run git in `cwd` and resolve with stdout. The engine spawns only git (0014).
|
|
8
|
+
* Asynchronous so the hook's deadline can interrupt it: a slow git (a huge
|
|
9
|
+
* repo, a network filesystem) must not hold the Stop past `latencyMs`.
|
|
10
|
+
* A failure is a `source-error`, which a guard hook reports and fails open on.
|
|
11
|
+
*/
|
|
12
|
+
export declare function git(cwd: string, args: string[], options?: GitOptions): Promise<string>;
|
|
13
|
+
/** HEAD's commit, or `null` in a repo with no commits yet. */
|
|
14
|
+
export declare function headCommit(cwd: string, signal?: AbortSignal): Promise<string | null>;
|
|
15
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/guard/git.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAyB1F;AAED,8DAA8D;AAC9D,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW1F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { DecisionsError } from "../errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Run git in `cwd` and resolve with stdout. The engine spawns only git (0014).
|
|
5
|
+
* Asynchronous so the hook's deadline can interrupt it: a slow git (a huge
|
|
6
|
+
* repo, a network filesystem) must not hold the Stop past `latencyMs`.
|
|
7
|
+
* A failure is a `source-error`, which a guard hook reports and fails open on.
|
|
8
|
+
*/
|
|
9
|
+
export function git(cwd, args, options = {}) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
execFile("git", ["-C", cwd, ...args], {
|
|
12
|
+
encoding: "utf8",
|
|
13
|
+
maxBuffer: options.maxBuffer ?? 64 * 1024 * 1024,
|
|
14
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
15
|
+
}, (error, stdout, stderr) => {
|
|
16
|
+
if (!error)
|
|
17
|
+
return resolve(stdout);
|
|
18
|
+
if (error.name === "AbortError")
|
|
19
|
+
return reject(error);
|
|
20
|
+
const detail = String(stderr || error.message)
|
|
21
|
+
.trim()
|
|
22
|
+
.split("\n")[0] ?? "";
|
|
23
|
+
reject(Object.assign(new DecisionsError("source-error", `git ${args[0]} failed: ${detail}`), {
|
|
24
|
+
exitCode: typeof error.code === "number" ? error.code : undefined,
|
|
25
|
+
}));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** HEAD's commit, or `null` in a repo with no commits yet. */
|
|
30
|
+
export async function headCommit(cwd, signal) {
|
|
31
|
+
try {
|
|
32
|
+
const out = await git(cwd, ["rev-parse", "--verify", "--quiet", "HEAD^{commit}"], {
|
|
33
|
+
...(signal ? { signal } : {}),
|
|
34
|
+
});
|
|
35
|
+
return out.trim() || null;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// `--verify --quiet` exits 1 with no output when there is no commit yet.
|
|
39
|
+
if (error.exitCode === 1)
|
|
40
|
+
return null;
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/guard/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAQ7C;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,IAAc,EAAE,OAAO,GAAe,EAAE;IACvE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,QAAQ,CACN,KAAK,EACL,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,EACpB;YACE,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI;YAChD,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACxB,IAAI,CAAC,KAAK;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;YAClC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;gBAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;YACrD,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC;iBAC5B,IAAI,EAAE;iBACN,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;YACzB,MAAM,CACJ,MAAM,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,cAAc,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,MAAM,EAAE,CAAC,EAAE;gBACpF,QAAQ,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;aAClE,CAAC,CACH,CAAA;QACH,CAAC,CACF,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,MAAoB;IAChE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE;YAChF,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,CAAA;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yEAAyE;QACzE,IAAK,KAA+B,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAChE,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guard packs (M10): hooks that check an agent's work at a harness event and
|
|
3
|
+
* send content to the decision model when they do. Each pack is dormant until
|
|
4
|
+
* the user enables it in this repo, on top of egress consent. Enabling is a
|
|
5
|
+
* consent act (plan X6), so `enabled` is read only from the repo layer, like
|
|
6
|
+
* `egress.consent` (decision 0009): a user-level setting can't switch on
|
|
7
|
+
* egress in every repo.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PACKS: {
|
|
10
|
+
readonly "done-check": {
|
|
11
|
+
readonly summary: "At Stop, checks the change against the criteria files' bullets and blocks once on a confidently unmet one";
|
|
12
|
+
readonly defaults: {
|
|
13
|
+
readonly latencyMs: 5000;
|
|
14
|
+
readonly maxUsdPerSession: 0.01;
|
|
15
|
+
readonly criteria: readonly ["TASK.md", ".system1/done.md"];
|
|
16
|
+
readonly evidence: string[];
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export type PackName = keyof typeof PACKS;
|
|
21
|
+
export declare const PACK_NAMES: PackName[];
|
|
22
|
+
export declare function isPackName(name: string): name is PackName;
|
|
23
|
+
export interface GuardPackConfig {
|
|
24
|
+
/** Only ever taken from the repo layer. */
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
/** When and how it was enabled, as `setGuardEnabled` recorded it. */
|
|
27
|
+
enabledAt?: string;
|
|
28
|
+
enabledBy?: string;
|
|
29
|
+
/** The time a check may add at the event before it fails open. */
|
|
30
|
+
latencyMs: number;
|
|
31
|
+
/** Measured spend per session (the ledger, by session id) before checks are skipped. */
|
|
32
|
+
maxUsdPerSession: number;
|
|
33
|
+
/** Files whose bullets are the criteria, relative to the repo root. */
|
|
34
|
+
criteria: string[];
|
|
35
|
+
/** Extra files sent with the change as evidence, e.g. a test log. */
|
|
36
|
+
evidence: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface GuardConfig {
|
|
39
|
+
packs: Record<PackName, GuardPackConfig>;
|
|
40
|
+
}
|
|
41
|
+
type Layer = Record<string, unknown> | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* `guard:` from both layers, with warnings for everything ignored. Options:
|
|
44
|
+
* the repo wins over the user, then the pack default; a list is taken whole
|
|
45
|
+
* from the first layer that sets it. A value of the wrong type is ignored
|
|
46
|
+
* with a warning, like the other config keys, so a bad file never stops
|
|
47
|
+
* `decide`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readGuard(user: Layer, userFile: string, repo: Layer, repoFile: string, warnings: string[]): GuardConfig;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=packs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packs.d.ts","sourceRoot":"","sources":["../../src/guard/packs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,KAAK;aAChB,YAAY;iBACV,OAAO,EACL,2GAA2G;iBAC7G,QAAQ;qBACN,SAAS,EAAE,IAAI;qBACf,gBAAgB,EAAE,IAAI;qBACtB,QAAQ,YAAG,SAAS,EAAE,kBAAkB;qBACxC,QAAQ,EAAQ,MAAM,EAAE;;;CAGpB,CAAA;AAEV,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,KAAK,CAAA;AAEzC,eAAO,MAAM,UAAU,EAAyB,QAAQ,EAAE,CAAA;AAE1D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,QAAQ,CAEzD;AAED,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAA;IAChB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAA;IACjB,wFAAwF;IACxF,gBAAgB,EAAE,MAAM,CAAA;IACxB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAA;CACzC;AAED,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;AAahD;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB,WAAW,CAoEb"}
|