@turri-dev/cli 0.1.6 → 0.1.7-next.9aec40e
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/ask.d.ts +83 -0
- package/dist/brand.d.ts +13 -0
- package/dist/btw.d.ts +67 -0
- package/dist/chat-models.d.ts +22 -0
- package/dist/chat-skills.d.ts +17 -0
- package/dist/cli-options.d.ts +25 -0
- package/dist/cli.d.ts +9 -0
- package/dist/config-command.d.ts +26 -0
- package/dist/config-edit.d.ts +69 -0
- package/dist/config.d.ts +321 -0
- package/dist/conform-cli.d.ts +1 -0
- package/dist/cultivate-cli.d.ts +1 -0
- package/dist/drift-cli.d.ts +1 -0
- package/dist/environment.d.ts +39 -0
- package/dist/extension.d.ts +147 -0
- package/dist/extension.js +36 -10
- package/dist/genome.d.ts +62 -0
- package/dist/graph.d.ts +52 -0
- package/dist/host.d.ts +20 -0
- package/dist/host.js +23 -0
- package/dist/identity.d.ts +2 -0
- package/dist/init-config.d.ts +106 -0
- package/dist/jellyfish.d.ts +25 -0
- package/dist/judge.d.ts +25 -0
- package/dist/lineage-cli.d.ts +1 -0
- package/dist/loop-cli.d.ts +34 -0
- package/dist/loop-tools.d.ts +80 -0
- package/dist/mature-tools.d.ts +53 -0
- package/dist/model-check.d.ts +42 -0
- package/dist/module-report.d.ts +9 -0
- package/dist/pi-launch.d.ts +1 -0
- package/dist/pi.d.ts +246 -0
- package/dist/picture-row.d.ts +10 -0
- package/dist/plain/check.d.ts +23 -0
- package/dist/plain/concepts.d.ts +11 -0
- package/dist/plain/errors.d.ts +22 -0
- package/dist/plain/files.d.ts +12 -0
- package/dist/plain/highlight.d.ts +42 -0
- package/dist/plain/index.d.ts +15 -0
- package/dist/plain/liquid.d.ts +22 -0
- package/dist/plain/markdown.d.ts +74 -0
- package/dist/plain/parser.d.ts +87 -0
- package/dist/plain/spec.d.ts +90 -0
- package/dist/plain/stdlib.d.ts +14 -0
- package/dist/question-dialog.d.ts +51 -0
- package/dist/questioning.d.ts +55 -0
- package/dist/quiet.d.ts +34 -0
- package/dist/regenerate/activity.d.ts +207 -0
- package/dist/regenerate/agent-env.d.ts +44 -0
- package/dist/regenerate/agent-shell.d.ts +49 -0
- package/dist/regenerate/arbiter.d.ts +68 -0
- package/dist/regenerate/audit.d.ts +69 -0
- package/dist/regenerate/cases.d.ts +9 -0
- package/dist/regenerate/change-view.d.ts +18 -0
- package/dist/regenerate/choose-conformance.d.ts +32 -0
- package/dist/regenerate/chunk-plan.d.ts +164 -0
- package/dist/regenerate/codebase.d.ts +21 -0
- package/dist/regenerate/command-check.d.ts +40 -0
- package/dist/regenerate/compaction.d.ts +13 -0
- package/dist/regenerate/confine.d.ts +62 -0
- package/dist/regenerate/conform.d.ts +63 -0
- package/dist/regenerate/conformance-agents.d.ts +405 -0
- package/dist/regenerate/conformance.d.ts +189 -0
- package/dist/regenerate/conversation-writes.d.ts +10 -0
- package/dist/regenerate/credentials.d.ts +18 -0
- package/dist/regenerate/debug-log.d.ts +54 -0
- package/dist/regenerate/debugger.d.ts +31 -0
- package/dist/regenerate/delivery.d.ts +6 -0
- package/dist/regenerate/diagnose-job.d.ts +2 -0
- package/dist/regenerate/diagnose.d.ts +46 -0
- package/dist/regenerate/diff-view.d.ts +61 -0
- package/dist/regenerate/drift.d.ts +84 -0
- package/dist/regenerate/engine.d.ts +52 -0
- package/dist/regenerate/environment-error.d.ts +136 -0
- package/dist/regenerate/job-log.d.ts +28 -0
- package/dist/regenerate/job-panel.d.ts +122 -0
- package/dist/regenerate/jobs-tree.d.ts +71 -0
- package/dist/regenerate/jobs.d.ts +186 -0
- package/dist/regenerate/lanes.d.ts +16 -0
- package/dist/regenerate/lineage.d.ts +95 -0
- package/dist/regenerate/list-arguments.d.ts +21 -0
- package/dist/regenerate/loop.d.ts +392 -0
- package/dist/regenerate/masking.d.ts +19 -0
- package/dist/regenerate/notes.d.ts +159 -0
- package/dist/regenerate/os-sandbox.d.ts +89 -0
- package/dist/regenerate/panel-dock.d.ts +23 -0
- package/dist/regenerate/paths.d.ts +92 -0
- package/dist/regenerate/plain-palette.d.ts +34 -0
- package/dist/regenerate/prompt.d.ts +192 -0
- package/dist/regenerate/records.d.ts +88 -0
- package/dist/regenerate/regenerate.d.ts +108 -0
- package/dist/regenerate/regression.d.ts +58 -0
- package/dist/regenerate/release.d.ts +123 -0
- package/dist/regenerate/requires.d.ts +96 -0
- package/dist/regenerate/resources.d.ts +53 -0
- package/dist/regenerate/self-check.d.ts +29 -0
- package/dist/regenerate/services.d.ts +28 -0
- package/dist/regenerate/shell.d.ts +91 -0
- package/dist/regenerate/side-panel.d.ts +57 -0
- package/dist/regenerate/spec-map-view.d.ts +139 -0
- package/dist/regenerate/spec-map.d.ts +138 -0
- package/dist/regenerate/spec-steps.d.ts +137 -0
- package/dist/regenerate/state.d.ts +20 -0
- package/dist/regenerate/steer.d.ts +34 -0
- package/dist/regenerate/steering.d.ts +56 -0
- package/dist/regenerate/stop-report.d.ts +43 -0
- package/dist/regenerate/submit-work.d.ts +42 -0
- package/dist/regenerate/test-kinds.d.ts +42 -0
- package/dist/regenerate/test-scripts.d.ts +221 -0
- package/dist/regenerate/testing.d.ts +141 -0
- package/dist/regenerate/transcript-view.d.ts +21 -0
- package/dist/regenerate/unit-gate.d.ts +27 -0
- package/dist/regenerate/unit-review.d.ts +152 -0
- package/dist/regenerate/web.d.ts +61 -0
- package/dist/regenerate/workspace.d.ts +12 -0
- package/dist/regenerate-cli.d.ts +1 -0
- package/dist/release-agent.d.ts +26 -0
- package/dist/release-cli.d.ts +1 -0
- package/dist/release-tools.d.ts +38 -0
- package/dist/resume-line.d.ts +2 -0
- package/dist/review/live.d.ts +72 -0
- package/dist/rules.d.ts +20 -0
- package/dist/run-report.d.ts +88 -0
- package/dist/screen-padding.d.ts +28 -0
- package/dist/self-invocation.d.ts +25 -0
- package/dist/setup.d.ts +43 -0
- package/dist/skill-progress.d.ts +46 -0
- package/dist/skill.d.ts +98 -0
- package/dist/skills.d.ts +30 -0
- package/dist/spec-diff-cli.d.ts +1 -0
- package/dist/spec-tools.d.ts +36 -0
- package/dist/stack.d.ts +58 -0
- package/dist/stacks.d.ts +12 -0
- package/dist/stdlib.d.ts +27 -0
- package/dist/terminal-images.d.ts +2 -0
- package/dist/tools.d.ts +101 -0
- package/dist/validate-cli.d.ts +1 -0
- package/docs/README.md +2 -0
- package/docs/hosting.md +51 -0
- package/package.json +8 -1
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { type ChunkAgents } from "./chunk-plan.ts";
|
|
2
|
+
import { type SpecGap } from "./notes.ts";
|
|
3
|
+
import { type Job, type JobRegistry } from "./jobs.ts";
|
|
4
|
+
import type { Steering } from "./steer.ts";
|
|
5
|
+
import { type ChainEntry } from "./requires.ts";
|
|
6
|
+
import { type SpecSnapshot } from "./regenerate.ts";
|
|
7
|
+
import { type JobSteering } from "./steering.ts";
|
|
8
|
+
import { type SpecStep } from "./spec-steps.ts";
|
|
9
|
+
import { type JobCases, type TouchedSpec } from "./drift.ts";
|
|
10
|
+
/**
|
|
11
|
+
* The work loop - see docs/regenerating.md.
|
|
12
|
+
*
|
|
13
|
+
* Nothing is queued. For every codebase it has been asked to bring up to its spec, the loop works out
|
|
14
|
+
* what is left to build - from the code record to the spec of the codebase's requires chain, as the
|
|
15
|
+
* .plain files have it now - has the planner cut it into jobs, and runs the first. When a job ends, or
|
|
16
|
+
* the spec changes, it works it out again. A plan is kept only while the spec and the record it was cut
|
|
17
|
+
* from stay as they were.
|
|
18
|
+
*
|
|
19
|
+
* Code accumulates up a requires chain: a module is built on a copy of the code of the one it requires.
|
|
20
|
+
* So the codebase of a chain is its furthest-built module - its tip - and a change to a module below is
|
|
21
|
+
* made there. The codebases below it are left as they were, their records saying what they are built
|
|
22
|
+
* from; one is brought up to its own spec again only when a module not built yet is to start from it.
|
|
23
|
+
*
|
|
24
|
+
* - A module waits while one it is built on has work left, or a job running.
|
|
25
|
+
* - A running job the spec no longer wants - one of its changes is no longer part of the work - is
|
|
26
|
+
* stopped, and what it did rolled back. Otherwise it finishes, and the next plan starts from what it
|
|
27
|
+
* landed.
|
|
28
|
+
* - A job that does not land halts its codebase: nothing more runs there until the spec changes or it is
|
|
29
|
+
* asked for again.
|
|
30
|
+
*/
|
|
31
|
+
/** A planned job: its title, why, its cases, and its step - its diff and the spec it leaves. */
|
|
32
|
+
export interface PlannedJob {
|
|
33
|
+
title: string;
|
|
34
|
+
reason: string;
|
|
35
|
+
cases: JobCases;
|
|
36
|
+
step: SpecStep;
|
|
37
|
+
/** What it builds: the code, or the conformance tests of what the code is built from. */
|
|
38
|
+
track: Track;
|
|
39
|
+
}
|
|
40
|
+
/** The two things a codebase is brought up in: its code, and - on the code as built - its conformance tests. */
|
|
41
|
+
export type Track = "code" | "conformance";
|
|
42
|
+
/** What renders a job. Injectable, so the loop can be tested without a model. */
|
|
43
|
+
export type JobRunner = (job: {
|
|
44
|
+
plainFile: string;
|
|
45
|
+
moduleName: string;
|
|
46
|
+
buildDir: string;
|
|
47
|
+
spec: SpecSnapshot;
|
|
48
|
+
planned: PlannedJob;
|
|
49
|
+
model?: string;
|
|
50
|
+
cwd: string;
|
|
51
|
+
/** A code job's: how the loop steers it when the spec changes inside what it regenerates - and the record it lands. */
|
|
52
|
+
steering?: JobSteering;
|
|
53
|
+
}, onDelta: (delta: string) => void) => Promise<{
|
|
54
|
+
landed: boolean;
|
|
55
|
+
report: string;
|
|
56
|
+
story?: string;
|
|
57
|
+
specGaps?: SpecGap[];
|
|
58
|
+
}>;
|
|
59
|
+
/** A codebase as the loop sees it, for the person. */
|
|
60
|
+
export interface ModuleStatus {
|
|
61
|
+
module: string;
|
|
62
|
+
plainFile: string;
|
|
63
|
+
/** The job running now, if one is. */
|
|
64
|
+
running?: {
|
|
65
|
+
jobId: string;
|
|
66
|
+
title: string;
|
|
67
|
+
steered?: string[];
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* The jobs planned after it, in order: the module's code jobs, then its conformance jobs. A conformance job scheduled
|
|
71
|
+
* for functional specs not all built yet - `waitsFor`, those that are not - comes after the module's last code job.
|
|
72
|
+
* The module's conformance tests, wanted for all of it while its code is still to build - `afterCode` - come last:
|
|
73
|
+
* they are planned into pulses only once the code is built, but are shown, so asking for them is seen to have worked.
|
|
74
|
+
*/
|
|
75
|
+
planned: Array<{
|
|
76
|
+
title: string;
|
|
77
|
+
cases: JobCases;
|
|
78
|
+
track: Track;
|
|
79
|
+
waitsFor?: string[];
|
|
80
|
+
planning?: true;
|
|
81
|
+
afterCode?: true;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* What the plan of its code did not do as asked: the person's wishes its planner did not follow and why, an answer
|
|
85
|
+
* that did not hold, a group split for its size.
|
|
86
|
+
*/
|
|
87
|
+
planNotes?: string[];
|
|
88
|
+
/** Why nothing runs there, when nothing does. */
|
|
89
|
+
why?: string;
|
|
90
|
+
/** What asking for conformance tests changed there, when it changed nothing: they were on for the whole module already. */
|
|
91
|
+
conformanceNote?: string;
|
|
92
|
+
/**
|
|
93
|
+
* It now requires modules its code was not built on - `requires` - and is built only once its code is started
|
|
94
|
+
* over on them: these codebases' code and tests taken out, kept in their history, and built again from the
|
|
95
|
+
* bottom of the chain. Never done unasked: `startOver` does it.
|
|
96
|
+
*/
|
|
97
|
+
startOver?: {
|
|
98
|
+
requires: string[];
|
|
99
|
+
codebases: string[];
|
|
100
|
+
};
|
|
101
|
+
/** The stack it is built with - its config.turri.<stack>.yaml over config.turri.yaml - when one is. */
|
|
102
|
+
stack?: string;
|
|
103
|
+
}
|
|
104
|
+
/** What is left to regenerate in a codebase - see `WorkLoop.drift`. */
|
|
105
|
+
export interface DriftReport {
|
|
106
|
+
module: string;
|
|
107
|
+
plainFile: string;
|
|
108
|
+
/** The code's work, from its record to the spec now: null, none - built from the spec as it is. */
|
|
109
|
+
code: JobCases | null | undefined;
|
|
110
|
+
/** The conformance tests' work: null, none; undefined, none are written here. */
|
|
111
|
+
conformance: JobCases | null | undefined;
|
|
112
|
+
/** Conformance tests scheduled ahead of their code, and which of their functional specs are not built yet. */
|
|
113
|
+
scheduled: Array<{
|
|
114
|
+
frids: string[];
|
|
115
|
+
unbuilt: string[];
|
|
116
|
+
}>;
|
|
117
|
+
running?: {
|
|
118
|
+
jobId: string;
|
|
119
|
+
title: string;
|
|
120
|
+
};
|
|
121
|
+
/** Why nothing is regenerated there: halted, or its spec does not parse. */
|
|
122
|
+
why?: string;
|
|
123
|
+
startOver?: ModuleStatus["startOver"];
|
|
124
|
+
}
|
|
125
|
+
/** What is left to regenerate, as the conversation and the command line read it. */
|
|
126
|
+
export declare function describeDrift(reports: DriftReport[]): string;
|
|
127
|
+
export interface WorkLoop {
|
|
128
|
+
/**
|
|
129
|
+
* Bring a spec's module up to the spec as the .plain files have it now - in the codebases where its
|
|
130
|
+
* code lives, and every module it is built on that has to be built first - planning and starting the
|
|
131
|
+
* first jobs. Asked again, it clears a halt. Also what a spec change is: the loop works out the work
|
|
132
|
+
* again. `specChange`: brought up because its spec was changed, not asked for - a module the person halted stays
|
|
133
|
+
* halted. Says what it planned.
|
|
134
|
+
*/
|
|
135
|
+
bringUp(plainFile: string, options?: {
|
|
136
|
+
model?: string;
|
|
137
|
+
guidance?: string;
|
|
138
|
+
specChange?: boolean;
|
|
139
|
+
}): Promise<ModuleStatus[]>;
|
|
140
|
+
/**
|
|
141
|
+
* Regenerate functional specs of a module again, their spec changed or not: each is marked to regenerate again in
|
|
142
|
+
* the record of every codebase it is built in - committed - and they are brought up to their spec, the marked ones
|
|
143
|
+
* planned as any change is. Their code is there: the jobs that regenerate them are told to regenerate it again, not
|
|
144
|
+
* to build it anew.
|
|
145
|
+
*/
|
|
146
|
+
regenerateAgain(plainFile: string, frids: string | string[], options?: {
|
|
147
|
+
model?: string;
|
|
148
|
+
guidance?: string;
|
|
149
|
+
}): Promise<ModuleStatus[]>;
|
|
150
|
+
/**
|
|
151
|
+
* What is left to regenerate, for a spec's module, in each codebase where its code lives: the code's work from its
|
|
152
|
+
* record to the spec now, and the conformance tests' - planning nothing, starting nothing.
|
|
153
|
+
*/
|
|
154
|
+
drift(plainFile: string): DriftReport[];
|
|
155
|
+
/**
|
|
156
|
+
* Write and run the conformance tests of a spec's module - of the functional specs named, or of every one - on the
|
|
157
|
+
* code as it is built, in the codebases where its code lives: for this session, whatever the config says. Asked
|
|
158
|
+
* again, it clears a halt. Says what it planned.
|
|
159
|
+
*/
|
|
160
|
+
conformance(plainFile: string, options?: {
|
|
161
|
+
frids?: string[];
|
|
162
|
+
model?: string;
|
|
163
|
+
separately?: boolean;
|
|
164
|
+
groups?: string[][];
|
|
165
|
+
}): Promise<ModuleStatus[]>;
|
|
166
|
+
/**
|
|
167
|
+
* Start over the codebases of a spec's module that now require a module their code was not built on (see
|
|
168
|
+
* `ModuleStatus.startOver`): their code and conformance tests taken out - committed, so their history keeps
|
|
169
|
+
* them - and the module brought up, from the bottom of its chain. Destructive: asked for only once the person
|
|
170
|
+
* agreed. Says what it planned.
|
|
171
|
+
*/
|
|
172
|
+
startOver(plainFile: string, options?: {
|
|
173
|
+
model?: string;
|
|
174
|
+
}): Promise<ModuleStatus[]>;
|
|
175
|
+
/**
|
|
176
|
+
* Regenerate a spec's module from scratch: every codebase where its code lives taken back to nothing - its code and
|
|
177
|
+
* conformance tests taken out, committed so its history keeps them - and the module brought up from its spec, planned
|
|
178
|
+
* into pulses as any work is. With `chain`, every codebase of its requires chains too, the base's included: nothing
|
|
179
|
+
* below is copied up, and the whole chain is built again from the bottom - after modules were split or moved, when
|
|
180
|
+
* the code below was laid out for modules that are no more. Destructive: asked for only when the person asked for
|
|
181
|
+
* it. Says what it planned.
|
|
182
|
+
*/
|
|
183
|
+
fromScratch(plainFile: string, options?: {
|
|
184
|
+
model?: string;
|
|
185
|
+
guidance?: string;
|
|
186
|
+
chain?: boolean;
|
|
187
|
+
}): Promise<ModuleStatus[]>;
|
|
188
|
+
/**
|
|
189
|
+
* Halt a module's planned work, as the person asked: `target` is a planned row's id (`planned-<module>-...`) or the
|
|
190
|
+
* module's name. A module's pulses are planned again from its spec each look, so it is the module that is halted, not
|
|
191
|
+
* one row: its pulse running is stopped and rolled back, nothing is planned or started there - nor in the modules built
|
|
192
|
+
* on it, which wait for it - until it is asked for again; a spec change does not start it. A module whose .plain file is
|
|
193
|
+
* gone is forgotten. Says what it did - undefined when the target names no module the loop looks after.
|
|
194
|
+
*/
|
|
195
|
+
halt(target: string, reason?: string): string | undefined;
|
|
196
|
+
/** Every codebase the loop looks after, bottom of each chain first. */
|
|
197
|
+
status(): ModuleStatus[];
|
|
198
|
+
/**
|
|
199
|
+
* The jobs planned after the running ones, as jobs are listed - queued, each after the one before it -
|
|
200
|
+
* for the job panel and pulses. Not started, they are not the registry's: planned again, they change.
|
|
201
|
+
*/
|
|
202
|
+
planned(): Job[];
|
|
203
|
+
/**
|
|
204
|
+
* What the regeneration draws on top of the files: the .plain files asked for, and each codebase's pulses - running and
|
|
205
|
+
* planned, numbered, with the trees each goes between - and why nothing moves there, when nothing does.
|
|
206
|
+
*/
|
|
207
|
+
mapPlan(): MapPlan;
|
|
208
|
+
/** Resolves once nothing runs and nothing more can start. */
|
|
209
|
+
drain(): Promise<void>;
|
|
210
|
+
/** In a dry run: the job each codebase would start, with the spec it would be given. */
|
|
211
|
+
firsts(): Array<{
|
|
212
|
+
module: string;
|
|
213
|
+
plainFile: string;
|
|
214
|
+
buildDir: string;
|
|
215
|
+
spec: SpecSnapshot;
|
|
216
|
+
planned: PlannedJob;
|
|
217
|
+
}>;
|
|
218
|
+
}
|
|
219
|
+
/** A pulse as the regeneration places it: by the items its trees differ in. */
|
|
220
|
+
export interface MapPulse {
|
|
221
|
+
/** Its number among the module's pulses this session - planned ones' provisional. */
|
|
222
|
+
number: number;
|
|
223
|
+
title: string;
|
|
224
|
+
track: Track;
|
|
225
|
+
running: boolean;
|
|
226
|
+
/** Its id in the jobs listed - the running job's, or the planned row's - for the pulse list to go to. */
|
|
227
|
+
rowId: string;
|
|
228
|
+
/** The trees it goes between, serialized. */
|
|
229
|
+
before: string;
|
|
230
|
+
after: string;
|
|
231
|
+
/**
|
|
232
|
+
* A conformance pulse scheduled ahead of its code - not planned, so with no trees: the texts of the functional specs
|
|
233
|
+
* it writes tests for.
|
|
234
|
+
*/
|
|
235
|
+
specs?: string[];
|
|
236
|
+
}
|
|
237
|
+
/** A codebase as the regeneration reads the loop. */
|
|
238
|
+
export interface MapCodebase {
|
|
239
|
+
module: string;
|
|
240
|
+
plainFile: string;
|
|
241
|
+
buildDir: string;
|
|
242
|
+
/** The pulses running and planned, in order. */
|
|
243
|
+
pulses: MapPulse[];
|
|
244
|
+
/** The track the planner is cutting now. */
|
|
245
|
+
planning?: Track;
|
|
246
|
+
/** The module below it that it waits for. */
|
|
247
|
+
waitsFor?: string;
|
|
248
|
+
/** Its conformance tests are on: by the config, or asked for this session. */
|
|
249
|
+
conformance: boolean;
|
|
250
|
+
/** Why nothing runs there, when nothing does. */
|
|
251
|
+
why?: string;
|
|
252
|
+
/** What asking for conformance tests changed there, when it changed nothing: they were on for the whole module already. */
|
|
253
|
+
conformanceNote?: string;
|
|
254
|
+
/**
|
|
255
|
+
* Halted, or the planner found no plan: it needs the person. `pulse`, the pulse that did not land; `cause`, what went
|
|
256
|
+
* wrong in it, in a few words - its tests never passed, the machine lacks a toolchain.
|
|
257
|
+
*/
|
|
258
|
+
stuck?: {
|
|
259
|
+
why: string;
|
|
260
|
+
pulse?: {
|
|
261
|
+
number: number;
|
|
262
|
+
before: string;
|
|
263
|
+
after: string;
|
|
264
|
+
};
|
|
265
|
+
cause?: string;
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
export interface MapPlan {
|
|
269
|
+
/** The .plain files asked for, in the order they were. */
|
|
270
|
+
files: string[];
|
|
271
|
+
codebases: MapCodebase[];
|
|
272
|
+
}
|
|
273
|
+
/** The spec a codebase is built from, as the .plain files have it now: its whole requires chain's. */
|
|
274
|
+
export declare function chainSpec(chain: ChainEntry[]): SpecSnapshot;
|
|
275
|
+
/** How many of a module's functional specs are completed in the codebase a run delivers - see `functionalityCompletion`. */
|
|
276
|
+
export interface ModuleCompletion {
|
|
277
|
+
module: string;
|
|
278
|
+
/** Its own functional specs, as its spec has them now. */
|
|
279
|
+
specified: number;
|
|
280
|
+
/** Of those, the ones the delivered codebase's code record has as the spec has them now. */
|
|
281
|
+
completed: number;
|
|
282
|
+
/** Of the completed ones, those its conformance tests are recorded as written for, as the spec has them now. */
|
|
283
|
+
conformanceTested: number;
|
|
284
|
+
/** Its functional specs not completed, by number. */
|
|
285
|
+
incomplete: string[];
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* The functional specs of a spec's whole requires chain, completed or not, in the codebase each chain delivers: its
|
|
289
|
+
* furthest-built module's code - which holds the code of every module below it. A functional spec is completed when that
|
|
290
|
+
* codebase's code record, as last committed, holds it as the spec has it now - the same text, the linked files it uses
|
|
291
|
+
* holding the same, no definition it uses changed, not marked to regenerate again. A record moves only when a pulse
|
|
292
|
+
* lands, its unit tests passing (and its conformance tests, when they are on), so completed is landed and passing.
|
|
293
|
+
* The modules above the delivered codebase have nothing completed. One entry per chain; planning nothing, calling no model.
|
|
294
|
+
*/
|
|
295
|
+
export declare function functionalityCompletion(plainFile: string): Array<{
|
|
296
|
+
codebase: string;
|
|
297
|
+
modules: ModuleCompletion[];
|
|
298
|
+
}>;
|
|
299
|
+
export declare function createWorkLoop(options: {
|
|
300
|
+
registry: JobRegistry;
|
|
301
|
+
cwd: string;
|
|
302
|
+
/** The model a job renders on, asked when a module is brought up. */
|
|
303
|
+
modelFor?: (plainFile: string) => string | undefined;
|
|
304
|
+
/** The planner's agents. false: none - a functional spec a job. Default: the LLM ones, on `plannerModel`. */
|
|
305
|
+
planner?: ChunkAgents | false;
|
|
306
|
+
/** The planner's model, read afresh each plan - the chat's, in a conversation. */
|
|
307
|
+
plannerModel?: string | (() => string | undefined);
|
|
308
|
+
/** How the person wants the work cut and ordered, for every plan of a spec's module. */
|
|
309
|
+
steering?: (plainFile: string) => Steering[];
|
|
310
|
+
/** Renders a job. Default: a spec diff render that lands on its unit tests. */
|
|
311
|
+
run?: JobRunner;
|
|
312
|
+
/** Writes and runs a conformance job's tests. Default: a spec diff's conformance run, the whole suite with it. */
|
|
313
|
+
runConformance?: JobRunner;
|
|
314
|
+
/** Whether the config has a module's conformance tests on. Default: its `conformance-tests:`, off unless it turns them on. */
|
|
315
|
+
conformanceOn?: (plainFile: string) => boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Whether a module's conformance tests are for the functional specs chosen, not every one: those with acceptance
|
|
318
|
+
* tests, those the conversation asked for, and those tested already. Default: `conformance-tests: chosen`.
|
|
319
|
+
*/
|
|
320
|
+
conformanceChosen?: (plainFile: string) => boolean;
|
|
321
|
+
/**
|
|
322
|
+
* Under `conformance-tests: chosen`, asked what a code job that landed built or changed that no conformance test is
|
|
323
|
+
* for - by whoever chooses without a conversation (`turri regenerate`) - before the job ends: the functional specs it
|
|
324
|
+
* names are scheduled as conform schedules them. The conversation is told in the job's report instead.
|
|
325
|
+
*/
|
|
326
|
+
onChoose?: (plainFile: string, specs: TouchedSpec[], budget: number | undefined, when: "pulse" | "module") => Promise<{
|
|
327
|
+
frids: string[];
|
|
328
|
+
groups?: string[][];
|
|
329
|
+
why?: string;
|
|
330
|
+
} | undefined>;
|
|
331
|
+
/** When the chooser is asked: after each code pulse, once the module is regenerated, or never. Default: `conformance-tests:`. */
|
|
332
|
+
conformanceChoosing?: (plainFile: string) => "pulse" | "module" | undefined;
|
|
333
|
+
/**
|
|
334
|
+
* Under `release-after-pulse: true`, what releases a pulse that landed, as its last stage - before the pulse ends, so
|
|
335
|
+
* the module's next pulse starts on what is released. Its last reply goes in the pulse's report. Not given: nothing is.
|
|
336
|
+
*/
|
|
337
|
+
release?: (input: {
|
|
338
|
+
plainFile: string;
|
|
339
|
+
moduleName: string;
|
|
340
|
+
title: string;
|
|
341
|
+
onDelta: (delta: string) => void;
|
|
342
|
+
}) => Promise<string>;
|
|
343
|
+
/** Plan, and keep the job each codebase would start (`firsts`) - but start none. */
|
|
344
|
+
dryRun?: boolean;
|
|
345
|
+
}): WorkLoop;
|
|
346
|
+
/** Why nothing runs in a codebase whose code - and conformance tests, where they are wanted - is built from its spec as it is. */
|
|
347
|
+
export declare const UP_TO_DATE = "built from the spec as it is";
|
|
348
|
+
/** The codebases the loop looks after, as the person reads them: what runs, what is planned after it, and why nothing does. */
|
|
349
|
+
/**
|
|
350
|
+
* The coding agent's task for a dry run's first job, built as the render builds it - and all it did rolled back. Not for
|
|
351
|
+
* a conformance job: its prompt is built from what the code holds once it is built.
|
|
352
|
+
*/
|
|
353
|
+
export declare function promptOf(first: ReturnType<WorkLoop["firsts"]>[number]): Promise<string | undefined>;
|
|
354
|
+
/** The first job a codebase would start, and the prompt its coding agent would get. */
|
|
355
|
+
export interface JobPreview {
|
|
356
|
+
module: string;
|
|
357
|
+
title: string;
|
|
358
|
+
track: Track;
|
|
359
|
+
cases: JobCases;
|
|
360
|
+
/** The coding agent's task, whole. Not for a conformance job: it is built from what the code holds once it is built. */
|
|
361
|
+
task?: string;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* What bringing a spec's module up would start, in each codebase, and the prompt of each - planned on a loop of its own
|
|
365
|
+
* that starts nothing. A codebase `busy` says is running a job is left out: a dry run starts from its last commit, and
|
|
366
|
+
* what the next job there is given depends on what the running one lands.
|
|
367
|
+
*/
|
|
368
|
+
export declare function previewJobs(options: {
|
|
369
|
+
plainFile: string;
|
|
370
|
+
cwd: string;
|
|
371
|
+
model?: string;
|
|
372
|
+
plannerModel?: string;
|
|
373
|
+
steering?: (plainFile: string) => Steering[];
|
|
374
|
+
/** Whether a codebase, by its module, has a job running. */
|
|
375
|
+
busy?: (module: string) => boolean;
|
|
376
|
+
}): Promise<{
|
|
377
|
+
statuses: ModuleStatus[];
|
|
378
|
+
previews: JobPreview[];
|
|
379
|
+
busy: string[];
|
|
380
|
+
}>;
|
|
381
|
+
/** Nothing runs, is planned or is waiting there, as its code is built from its spec as it is. */
|
|
382
|
+
export declare function isUpToDate(status: ModuleStatus): boolean;
|
|
383
|
+
export declare function describeModules(statuses: ModuleStatus[], options?: {
|
|
384
|
+
for?: "chat" | "command line";
|
|
385
|
+
}): string;
|
|
386
|
+
/** How a code pulse went, for its line in the notes: the rounds it took, its test runs, what the debugger found. */
|
|
387
|
+
export declare function codeStory(result: {
|
|
388
|
+
attempts?: number;
|
|
389
|
+
runs?: unknown[];
|
|
390
|
+
diagnosed?: string[];
|
|
391
|
+
restructured?: boolean;
|
|
392
|
+
}): string | undefined;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
/** Mask these values, by name, from now on. */
|
|
3
|
+
export declare function registerSecrets(values: Record<string, string>): void;
|
|
4
|
+
/** For tests: mask nothing. */
|
|
5
|
+
export declare function forgetSecretsForTests(): void;
|
|
6
|
+
/** `text` with every registered value replaced by its name. */
|
|
7
|
+
export declare function maskSecrets(text: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* A stream that masks what passes through it before `onData` sees it: the end of each chunk is held back - as long as
|
|
10
|
+
* the longest value, less one - until the next shows whether a value runs across them. `end` lets the rest out.
|
|
11
|
+
*/
|
|
12
|
+
export declare function maskingStream(onData: (data: Buffer) => void): {
|
|
13
|
+
write(data: Buffer): void;
|
|
14
|
+
end(): void;
|
|
15
|
+
};
|
|
16
|
+
type AnyTool = ToolDefinition<any, any, any>;
|
|
17
|
+
/** The tools, each result they return - and each error they throw, a refusal - masked before the agent sees it. */
|
|
18
|
+
export declare function maskToolResults<T extends AnyTool>(tools: T[]): T[];
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
/**
|
|
3
|
+
* Working notes: what one agent on a codebase leaves the next.
|
|
4
|
+
*
|
|
5
|
+
* Every agent the harness starts is a fresh session. Without notes, each one spends its first
|
|
6
|
+
* turns finding its bearings - where the entry point is, how the tests run, what was installed,
|
|
7
|
+
* which approach already failed. The notes carry that forward: each agent on a codebase gets
|
|
8
|
+
* them the moment it starts, and updates them - a line added, changed or removed - before it
|
|
9
|
+
* finishes, so they get longer with the codebase instead of being rewritten by whoever came last.
|
|
10
|
+
*
|
|
11
|
+
* Stubborn on the specs, flexible on the assumptions. What the software must do is in the spec,
|
|
12
|
+
* and the notes never repeat or override it. Where the spec is silent, an agent has to assume
|
|
13
|
+
* something, and the assumptions it made are written down - so the next agent builds on the
|
|
14
|
+
* same ones instead of guessing afresh, and changes one the moment the code or the spec shows
|
|
15
|
+
* it to be wrong.
|
|
16
|
+
*
|
|
17
|
+
* Every line says when and where it came from - `[2026-09-24 16:49 · backend 3]` for
|
|
18
|
+
* functionality 3 of backend, `backend 3 conformance`, `backend spec change` - stamped by the
|
|
19
|
+
* harness, not written by the agent, so a line read two modules later can still be traced to the
|
|
20
|
+
* step that wrote it. A line that is changed is stamped again: an assumption one agent revised
|
|
21
|
+
* shows as newer than the ones around it, and where two lines disagree the later one is right. And every line
|
|
22
|
+
* has to say something: "none", "N/A", "nothing new" are refused - a section with nothing to add
|
|
23
|
+
* is left alone.
|
|
24
|
+
*
|
|
25
|
+
* Leaving them is not optional, and neither is how: only update_notes writes the file. The file
|
|
26
|
+
* tools refuse it, a change made any other way - a shell, a script - is undone, and an agent
|
|
27
|
+
* that finishes without calling update_notes is asked again until it does.
|
|
28
|
+
*
|
|
29
|
+
* The notes are disposable: delete the file and nothing breaks, the next agent just explores a
|
|
30
|
+
* little more. They live beside the code, so they travel with it - copied up with it to a module
|
|
31
|
+
* that requires this one, committed with it, and reset with it when a run is interrupted.
|
|
32
|
+
*/
|
|
33
|
+
export declare const NOTES_FILE = ".turri-notes.md";
|
|
34
|
+
/** The sections, in order, and what each is for - shown to the agent as the heading. */
|
|
35
|
+
export declare const SECTIONS: {
|
|
36
|
+
readonly where: "Where things are";
|
|
37
|
+
readonly run: "How to build, run and test";
|
|
38
|
+
readonly assumptions: "Assumptions";
|
|
39
|
+
readonly pitfalls: "Pitfalls";
|
|
40
|
+
readonly pulses: "Pulses";
|
|
41
|
+
};
|
|
42
|
+
/** How many pulses the notes keep: the last ones - the module's history has every one. */
|
|
43
|
+
export declare const PULSES_KEPT = 10;
|
|
44
|
+
export type Section = keyof typeof SECTIONS;
|
|
45
|
+
export type Notes = Record<Section, string[]>;
|
|
46
|
+
export declare function notesPath(buildDir: string): string;
|
|
47
|
+
/** The notes, as lines per section. Lines under no known heading go to pitfalls, not lost. */
|
|
48
|
+
export declare function parseNotes(text: string): Notes;
|
|
49
|
+
export declare function formatNotes(notes: Notes): string;
|
|
50
|
+
export declare function readNotes(buildDir: string): Notes;
|
|
51
|
+
/** A prompt, led by the notes earlier agents left - and told to update them for the next. */
|
|
52
|
+
export declare function withNotes(prompt: string, buildDir: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* What an agent a review sent tests back to is asked to leave: the lesson, not the fix - the kind of
|
|
55
|
+
* test the review found weak or missing, and how to write it instead - so every later agent on the
|
|
56
|
+
* codebase writes it right from its first test, and the first reviews have less to send back.
|
|
57
|
+
*/
|
|
58
|
+
export declare const REVIEW_LESSON: string[];
|
|
59
|
+
/**
|
|
60
|
+
* After an agent worked on what a review found: when it left no new pitfall - no lesson - it is asked
|
|
61
|
+
* once more, so the next agent does not make the same tests the review has to send back again.
|
|
62
|
+
*/
|
|
63
|
+
export declare function reflectOnReview(buildDir: string, pitfallsBefore: string[], send: (prompt: string) => Promise<unknown>): Promise<void>;
|
|
64
|
+
export interface NotesChange {
|
|
65
|
+
section: Section;
|
|
66
|
+
action: "add" | "change" | "remove";
|
|
67
|
+
/** The line to add, or for a change the new line. For a remove, the line to remove. */
|
|
68
|
+
text: string;
|
|
69
|
+
/** For a change: the line it replaces, as it reads now. */
|
|
70
|
+
replaces?: string;
|
|
71
|
+
}
|
|
72
|
+
export declare function isFiller(text: string): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Apply the changes; the notes that result, or what could not be applied. A line added or
|
|
75
|
+
* changed is stamped with `stamp` - when, and which step wrote it.
|
|
76
|
+
*/
|
|
77
|
+
export declare function applyNotesChanges(notes: Notes, changes: NotesChange[], stamp?: string): {
|
|
78
|
+
notes: Notes;
|
|
79
|
+
problems: string[];
|
|
80
|
+
};
|
|
81
|
+
/** `update_notes`: lines added, changed or removed, never the notes rewritten. */
|
|
82
|
+
export declare function createNotesTool(buildDir: string, onWrite: (text: string) => void, before?: () => void, source?: string): import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
83
|
+
changes: Type.TArray<Type.TObject<{
|
|
84
|
+
section: Type.TString;
|
|
85
|
+
action: Type.TUnion<[Type.TLiteral<"add">, Type.TLiteral<"change">, Type.TLiteral<"remove">]>;
|
|
86
|
+
text: Type.TString;
|
|
87
|
+
replaces: Type.TOptional<Type.TString>;
|
|
88
|
+
}>>;
|
|
89
|
+
}>, {
|
|
90
|
+
characters: number;
|
|
91
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|
|
92
|
+
/** The section a name means - its key or its heading, in any case, or the heading's first words. */
|
|
93
|
+
export declare function sectionNamed(name: string): Section | undefined;
|
|
94
|
+
/** How many times an agent that finishes without update_notes is asked to call it. */
|
|
95
|
+
export declare const NOTES_ASKS = 3;
|
|
96
|
+
/** The turn that asks for the notes: update_notes is the only tool it may use - the work it follows is done. */
|
|
97
|
+
export declare const NOTES_TURN: {
|
|
98
|
+
onlyTools: string[];
|
|
99
|
+
};
|
|
100
|
+
/** What the notes turn says first, once the harness's own run of `script` has passed on the work. */
|
|
101
|
+
export declare function passedOutcome(script: string): string;
|
|
102
|
+
/**
|
|
103
|
+
* A line the harness itself writes into the notes - an attempt at a failing conformance run, what
|
|
104
|
+
* was judged wrong and what was done about it - stamped like an agent's, and kept as update_notes
|
|
105
|
+
* would keep it, so no session takes it for a direct write. Never fails the work it records.
|
|
106
|
+
*/
|
|
107
|
+
export declare function recordNote(buildDir: string, section: Section, text: string, source: string): void;
|
|
108
|
+
/**
|
|
109
|
+
* A pulse's line, written by the harness as the pulse ends - landed or not: what it regenerated, how it went, where its
|
|
110
|
+
* log is. The last PULSES_KEPT stay; the module's history has every pulse.
|
|
111
|
+
*/
|
|
112
|
+
export declare function recordPulse(buildDir: string, text: string, source: string): void;
|
|
113
|
+
/** A spec gap an agent met: the question it leaves the person, and what the agent decided meanwhile. */
|
|
114
|
+
export interface SpecGap {
|
|
115
|
+
question: string;
|
|
116
|
+
assumption: string;
|
|
117
|
+
}
|
|
118
|
+
/** Where the spec gaps stand now: what `gapsSince` reads from. */
|
|
119
|
+
export declare function gapMark(): number;
|
|
120
|
+
/** The spec gaps reported in these codebases since `mark`. */
|
|
121
|
+
export declare function gapsSince(mark: number, dirs: string[]): SpecGap[];
|
|
122
|
+
/**
|
|
123
|
+
* `report_spec_gap`: a behaviour the specification leaves open that the person would want to decide, put to them as
|
|
124
|
+
* the pulse ends - never into the notes, which are the next agent's. What the agent decided meanwhile goes into the
|
|
125
|
+
* notes' assumptions, so the code built on it is known for what it is until the specification settles it.
|
|
126
|
+
*/
|
|
127
|
+
export declare function createSpecGapTool(buildDir: string, source?: string): import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
128
|
+
question: Type.TString;
|
|
129
|
+
assumption: Type.TString;
|
|
130
|
+
}>, {
|
|
131
|
+
question: string;
|
|
132
|
+
assumption: string;
|
|
133
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|
|
134
|
+
/** The notes, for an agent that reads them but leaves none - a judge. Empty when there are none. */
|
|
135
|
+
export declare function notesToRead(buildDir: string): string;
|
|
136
|
+
export declare function notesForSession(buildDir: string, source?: string): {
|
|
137
|
+
gapTool: import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
138
|
+
question: Type.TString;
|
|
139
|
+
assumption: Type.TString;
|
|
140
|
+
}>, {
|
|
141
|
+
question: string;
|
|
142
|
+
assumption: string;
|
|
143
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|
|
144
|
+
tool: import("@earendil-works/pi-coding-agent").ToolDefinition<Type.TObject<{
|
|
145
|
+
changes: Type.TArray<Type.TObject<{
|
|
146
|
+
section: Type.TString;
|
|
147
|
+
action: Type.TUnion<[Type.TLiteral<"add">, Type.TLiteral<"change">, Type.TLiteral<"remove">]>;
|
|
148
|
+
text: Type.TString;
|
|
149
|
+
replaces: Type.TOptional<Type.TString>;
|
|
150
|
+
}>>;
|
|
151
|
+
}>, {
|
|
152
|
+
characters: number;
|
|
153
|
+
}, any> & import("@earendil-works/pi-coding-agent").ToolDefinition<any, any, any>;
|
|
154
|
+
/**
|
|
155
|
+
* Ask for the notes until this agent has updated them; whether it has. `outcome`: how the harness's own check of the
|
|
156
|
+
* work went, said first - so the notes tell the next agent the work passed, never that it could not be made to.
|
|
157
|
+
*/
|
|
158
|
+
ensureWritten(ask: (prompt: string) => Promise<unknown>, outcome?: string): Promise<boolean>;
|
|
159
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OS sandbox: the wall under an agent's command where the OS offers one - Seatbelt on macOS, bubblewrap on Linux
|
|
3
|
+
* and WSL2 - driven directly, from the role's fence. It is an extra wall, never where a rule lives: every rule is in the
|
|
4
|
+
* command check and the audit, which run on every platform, and where no sandbox starts they hold alone.
|
|
5
|
+
*
|
|
6
|
+
* What the command can reach, on both: the role's roots - its own read only where the role only reads - the module's
|
|
7
|
+
* home, TMPDIR and the package caches to write, and of the machine only an allow-list to read: the system's folders and
|
|
8
|
+
* the toolchains. The code record is denied. The network is open, as on this machine. Signals and process listings
|
|
9
|
+
* reach only what runs in the same sandbox: bubblewrap's own PID namespace, Seatbelt's same-sandbox target. A cap on
|
|
10
|
+
* processes and on file size is set inside, beside the time limit.
|
|
11
|
+
*/
|
|
12
|
+
export interface SandboxFence {
|
|
13
|
+
/** Where the command starts. */
|
|
14
|
+
cwd: string;
|
|
15
|
+
/** The role's roots it reads and may not write. */
|
|
16
|
+
read: string[];
|
|
17
|
+
/** The role's roots it writes - none for a role that only reads. */
|
|
18
|
+
write: string[];
|
|
19
|
+
/** What else the shell writes: the module's home, its TMPDIR, the package caches. */
|
|
20
|
+
writable: string[];
|
|
21
|
+
/** What of the machine it reads: the system's folders, the toolchains. */
|
|
22
|
+
machine: string[];
|
|
23
|
+
/** What it may not touch at all, inside its roots: the code record. */
|
|
24
|
+
deny: string[];
|
|
25
|
+
}
|
|
26
|
+
export type Wall = {
|
|
27
|
+
kind: "seatbelt";
|
|
28
|
+
} | {
|
|
29
|
+
kind: "bubblewrap";
|
|
30
|
+
proc: "mount" | "bind";
|
|
31
|
+
} | {
|
|
32
|
+
kind: "none";
|
|
33
|
+
why: string;
|
|
34
|
+
fix?: string;
|
|
35
|
+
};
|
|
36
|
+
/** The caps set inside the sandbox before the command runs: processes, and file size in 1024-byte blocks (8 GiB). */
|
|
37
|
+
export declare const PROCESS_CAP = 4096;
|
|
38
|
+
export declare const FILE_SIZE_CAP_BLOCKS: number;
|
|
39
|
+
/** What of macOS a command needs to read beyond the toolchains, besides `/usr`, `/bin`, `/System`: the loader's caches, the time zone, the developer tools. */
|
|
40
|
+
export declare const MACOS_MACHINE: string[];
|
|
41
|
+
/** What of Linux a command needs to read beyond the toolchains. */
|
|
42
|
+
export declare const LINUX_MACHINE: string[];
|
|
43
|
+
/**
|
|
44
|
+
* What of the machine a command reads, from the environment it runs in: the system's folders, every folder on its PATH,
|
|
45
|
+
* the folders its toolchain variables point at, and the project's `toolchains:`. Only the PATH folders themselves, not
|
|
46
|
+
* their parents - `~/.cargo/bin`, not `~/.cargo`, which holds a registry's credentials - but for a version manager's
|
|
47
|
+
* install: a `bin` whose parent is a version, `…/installs/node/24.16.0/bin`, links its tools into the install beside it
|
|
48
|
+
* (`npm` into `lib/node_modules`), and an install holds the toolchain, never a credential.
|
|
49
|
+
*/
|
|
50
|
+
export declare function machineFor(env: Record<string, string | undefined>, toolchainVariables: string[], extra?: string[], platform?: NodeJS.Platform): string[];
|
|
51
|
+
/**
|
|
52
|
+
* The Seatbelt profile for a fence. Everything is allowed but what it names - reading file contents outside the
|
|
53
|
+
* allow-list, writing outside the writable folders, the code record, Unix sockets outside the folders, signals and
|
|
54
|
+
* process information beyond the sandbox - later rules winning over earlier ones. File metadata stays readable, as
|
|
55
|
+
* resolving a path needs.
|
|
56
|
+
*/
|
|
57
|
+
export declare function seatbeltProfile(fence: SandboxFence, userDirs?: {
|
|
58
|
+
temp?: string;
|
|
59
|
+
cache?: string;
|
|
60
|
+
}): string;
|
|
61
|
+
export declare function darwinUserDirs(): {
|
|
62
|
+
temp?: string;
|
|
63
|
+
cache?: string;
|
|
64
|
+
};
|
|
65
|
+
/** The bubblewrap arguments for a fence, up to the command. `proc: "bind"` binds the host's /proc where mounting one is refused. */
|
|
66
|
+
export declare function bubblewrapArgs(fence: SandboxFence, options?: {
|
|
67
|
+
proc: "mount" | "bind";
|
|
68
|
+
}): string[];
|
|
69
|
+
/** How a command is run behind the wall that is up: for the host runner's `wrap`. Where none is, it runs as it is. */
|
|
70
|
+
export declare function sandboxWrap(wall: Wall, fence: SandboxFence): (argv: string[]) => string[];
|
|
71
|
+
/** What bubblewrap's refusal to start says is missing, and how to give it - each failure has a message of its own. */
|
|
72
|
+
export declare function whyBubblewrapFailed(output: string): {
|
|
73
|
+
why: string;
|
|
74
|
+
fix?: string;
|
|
75
|
+
};
|
|
76
|
+
/** For tests: forget what was found, or say what to find. */
|
|
77
|
+
export declare function setSandboxForTests(wall: Wall | undefined): void;
|
|
78
|
+
/**
|
|
79
|
+
* Which wall is up on this machine - tried once, by starting a sandbox that runs `true` - and, when none starts, why
|
|
80
|
+
* and how to give it one.
|
|
81
|
+
*/
|
|
82
|
+
export declare function sandboxAvailable(): Wall;
|
|
83
|
+
/** Whether `path` is one of the fence's roots or under one - for the tests and the audit. */
|
|
84
|
+
export declare function underAny(path: string, roots: string[]): boolean;
|
|
85
|
+
/** Where the agents' commands run, in one line for the person: which walls are up, or that only the shared ones are. */
|
|
86
|
+
export declare function sandboxSummary(wall?: Wall): {
|
|
87
|
+
level: "ok" | "limited";
|
|
88
|
+
text: string;
|
|
89
|
+
};
|