@turri-dev/cli 0.1.6 → 0.1.7-next.eb57c34

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.
Files changed (140) hide show
  1. package/dist/ask.d.ts +83 -0
  2. package/dist/brand.d.ts +13 -0
  3. package/dist/btw.d.ts +67 -0
  4. package/dist/chat-models.d.ts +22 -0
  5. package/dist/chat-skills.d.ts +17 -0
  6. package/dist/cli-options.d.ts +25 -0
  7. package/dist/cli.d.ts +9 -0
  8. package/dist/config-command.d.ts +26 -0
  9. package/dist/config-edit.d.ts +69 -0
  10. package/dist/config.d.ts +321 -0
  11. package/dist/conform-cli.d.ts +1 -0
  12. package/dist/cultivate-cli.d.ts +1 -0
  13. package/dist/drift-cli.d.ts +1 -0
  14. package/dist/environment.d.ts +39 -0
  15. package/dist/extension.d.ts +147 -0
  16. package/dist/extension.js +36 -10
  17. package/dist/genome.d.ts +62 -0
  18. package/dist/graph.d.ts +52 -0
  19. package/dist/host.d.ts +21 -0
  20. package/dist/host.js +25 -0
  21. package/dist/identity.d.ts +2 -0
  22. package/dist/init-config.d.ts +106 -0
  23. package/dist/jellyfish.d.ts +25 -0
  24. package/dist/judge.d.ts +25 -0
  25. package/dist/lineage-cli.d.ts +1 -0
  26. package/dist/loop-cli.d.ts +34 -0
  27. package/dist/loop-tools.d.ts +80 -0
  28. package/dist/mature-tools.d.ts +53 -0
  29. package/dist/model-check.d.ts +42 -0
  30. package/dist/module-report.d.ts +9 -0
  31. package/dist/pi-launch.d.ts +1 -0
  32. package/dist/pi.d.ts +246 -0
  33. package/dist/picture-row.d.ts +10 -0
  34. package/dist/plain/check.d.ts +23 -0
  35. package/dist/plain/concepts.d.ts +11 -0
  36. package/dist/plain/errors.d.ts +22 -0
  37. package/dist/plain/files.d.ts +12 -0
  38. package/dist/plain/highlight.d.ts +42 -0
  39. package/dist/plain/index.d.ts +15 -0
  40. package/dist/plain/liquid.d.ts +22 -0
  41. package/dist/plain/markdown.d.ts +74 -0
  42. package/dist/plain/parser.d.ts +87 -0
  43. package/dist/plain/spec.d.ts +90 -0
  44. package/dist/plain/stdlib.d.ts +14 -0
  45. package/dist/question-dialog.d.ts +51 -0
  46. package/dist/questioning.d.ts +55 -0
  47. package/dist/quiet.d.ts +34 -0
  48. package/dist/regenerate/activity.d.ts +207 -0
  49. package/dist/regenerate/agent-env.d.ts +44 -0
  50. package/dist/regenerate/agent-shell.d.ts +49 -0
  51. package/dist/regenerate/arbiter.d.ts +68 -0
  52. package/dist/regenerate/audit.d.ts +69 -0
  53. package/dist/regenerate/cases.d.ts +9 -0
  54. package/dist/regenerate/change-view.d.ts +18 -0
  55. package/dist/regenerate/choose-conformance.d.ts +32 -0
  56. package/dist/regenerate/chunk-plan.d.ts +164 -0
  57. package/dist/regenerate/codebase.d.ts +21 -0
  58. package/dist/regenerate/command-check.d.ts +40 -0
  59. package/dist/regenerate/compaction.d.ts +13 -0
  60. package/dist/regenerate/confine.d.ts +62 -0
  61. package/dist/regenerate/conform.d.ts +63 -0
  62. package/dist/regenerate/conformance-agents.d.ts +405 -0
  63. package/dist/regenerate/conformance.d.ts +189 -0
  64. package/dist/regenerate/conversation-writes.d.ts +10 -0
  65. package/dist/regenerate/credentials.d.ts +18 -0
  66. package/dist/regenerate/debug-log.d.ts +54 -0
  67. package/dist/regenerate/debugger.d.ts +31 -0
  68. package/dist/regenerate/delivery.d.ts +6 -0
  69. package/dist/regenerate/diagnose-job.d.ts +2 -0
  70. package/dist/regenerate/diagnose.d.ts +46 -0
  71. package/dist/regenerate/diff-view.d.ts +61 -0
  72. package/dist/regenerate/drift.d.ts +84 -0
  73. package/dist/regenerate/engine.d.ts +52 -0
  74. package/dist/regenerate/environment-error.d.ts +136 -0
  75. package/dist/regenerate/job-log.d.ts +28 -0
  76. package/dist/regenerate/job-panel.d.ts +122 -0
  77. package/dist/regenerate/jobs-tree.d.ts +71 -0
  78. package/dist/regenerate/jobs.d.ts +186 -0
  79. package/dist/regenerate/lanes.d.ts +16 -0
  80. package/dist/regenerate/lineage.d.ts +95 -0
  81. package/dist/regenerate/list-arguments.d.ts +21 -0
  82. package/dist/regenerate/loop.d.ts +392 -0
  83. package/dist/regenerate/masking.d.ts +19 -0
  84. package/dist/regenerate/notes.d.ts +159 -0
  85. package/dist/regenerate/os-sandbox.d.ts +89 -0
  86. package/dist/regenerate/panel-dock.d.ts +23 -0
  87. package/dist/regenerate/paths.d.ts +92 -0
  88. package/dist/regenerate/plain-palette.d.ts +34 -0
  89. package/dist/regenerate/prompt.d.ts +192 -0
  90. package/dist/regenerate/records.d.ts +88 -0
  91. package/dist/regenerate/regenerate.d.ts +108 -0
  92. package/dist/regenerate/regression.d.ts +58 -0
  93. package/dist/regenerate/release.d.ts +123 -0
  94. package/dist/regenerate/requires.d.ts +96 -0
  95. package/dist/regenerate/resources.d.ts +53 -0
  96. package/dist/regenerate/self-check.d.ts +29 -0
  97. package/dist/regenerate/services.d.ts +28 -0
  98. package/dist/regenerate/shell.d.ts +91 -0
  99. package/dist/regenerate/side-panel.d.ts +57 -0
  100. package/dist/regenerate/spec-map-view.d.ts +139 -0
  101. package/dist/regenerate/spec-map.d.ts +138 -0
  102. package/dist/regenerate/spec-steps.d.ts +137 -0
  103. package/dist/regenerate/state.d.ts +20 -0
  104. package/dist/regenerate/steer.d.ts +34 -0
  105. package/dist/regenerate/steering.d.ts +56 -0
  106. package/dist/regenerate/stop-report.d.ts +43 -0
  107. package/dist/regenerate/submit-work.d.ts +42 -0
  108. package/dist/regenerate/test-kinds.d.ts +42 -0
  109. package/dist/regenerate/test-scripts.d.ts +221 -0
  110. package/dist/regenerate/testing.d.ts +141 -0
  111. package/dist/regenerate/transcript-view.d.ts +21 -0
  112. package/dist/regenerate/unit-gate.d.ts +27 -0
  113. package/dist/regenerate/unit-review.d.ts +152 -0
  114. package/dist/regenerate/web.d.ts +61 -0
  115. package/dist/regenerate/workspace.d.ts +12 -0
  116. package/dist/regenerate-cli.d.ts +1 -0
  117. package/dist/release-agent.d.ts +26 -0
  118. package/dist/release-cli.d.ts +1 -0
  119. package/dist/release-tools.d.ts +38 -0
  120. package/dist/resume-line.d.ts +2 -0
  121. package/dist/review/live.d.ts +72 -0
  122. package/dist/rules.d.ts +20 -0
  123. package/dist/run-report.d.ts +88 -0
  124. package/dist/screen-padding.d.ts +28 -0
  125. package/dist/self-invocation.d.ts +25 -0
  126. package/dist/setup.d.ts +43 -0
  127. package/dist/skill-progress.d.ts +46 -0
  128. package/dist/skill.d.ts +98 -0
  129. package/dist/skills.d.ts +30 -0
  130. package/dist/spec-diff-cli.d.ts +1 -0
  131. package/dist/spec-tools.d.ts +36 -0
  132. package/dist/stack.d.ts +58 -0
  133. package/dist/stacks.d.ts +12 -0
  134. package/dist/stdlib.d.ts +27 -0
  135. package/dist/terminal-images.d.ts +2 -0
  136. package/dist/tools.d.ts +101 -0
  137. package/dist/validate-cli.d.ts +1 -0
  138. package/docs/README.md +2 -0
  139. package/docs/hosting.md +52 -0
  140. package/package.json +8 -1
@@ -0,0 +1,90 @@
1
+ import type { LinkedResource } from "./markdown.ts";
2
+ /** Port of plain_spec.py. */
3
+ export declare const DEFINITIONS = "definitions";
4
+ export declare const NON_FUNCTIONAL_REQUIREMENTS = "implementation reqs";
5
+ export declare const TEST_REQUIREMENTS = "test reqs";
6
+ export declare const FUNCTIONAL_REQUIREMENTS = "functional specs";
7
+ export declare const ACCEPTANCE_TESTS = "acceptance_tests";
8
+ export declare const ACCEPTANCE_TEST_HEADING = "acceptance tests";
9
+ /**
10
+ * Where a module's tree carries the functional specs it inherits through `requires`: every
11
+ * functional spec of every module it requires, transitively, bottom of the chain first.
12
+ * Kept apart from its own, which are numbered 1, 2, 3 on their own.
13
+ */
14
+ export declare const REQUIRED_FUNCTIONAL_SPECS = "required functional specs";
15
+ export declare const ALLOWED_SPECIFICATION_HEADINGS: string[];
16
+ export declare const ALLOWED_IMPORT_SPECIFICATION_HEADINGS: string[];
17
+ export interface CodeVariable {
18
+ name: string;
19
+ value: string;
20
+ }
21
+ export interface SpecificationItem {
22
+ markdown: string;
23
+ linked_resources?: LinkedResource[];
24
+ code_variables?: CodeVariable[];
25
+ [ACCEPTANCE_TESTS]?: SpecificationItem[];
26
+ }
27
+ /** A functional spec inherited through `requires`, with the module it belongs to and its id there. */
28
+ export interface InheritedSpecificationItem extends SpecificationItem {
29
+ module: string;
30
+ frid: string;
31
+ }
32
+ /**
33
+ * The functional specs a module inherits through `requires`, rendered: each with its
34
+ * module, its id there, and its acceptance tests.
35
+ */
36
+ export declare function getInheritedFunctionalSpecs(tree: MarshalledPlainSource, replaceCodeVariables?: boolean): Array<{
37
+ module: string;
38
+ frid: string;
39
+ spec: string;
40
+ acceptanceTests?: string[];
41
+ }>;
42
+ /**
43
+ * The marshalled tree: heading -> list of items. Flat: functionalities are numbered 1, 2, 3
44
+ * in the order they appear. Nested sections with dotted ids ("2.3") are not supported.
45
+ */
46
+ export interface MarshalledPlainSource {
47
+ [heading: string]: unknown;
48
+ }
49
+ export declare function getSpecificationItems(tree: MarshalledPlainSource, heading: string): SpecificationItem[] | undefined;
50
+ export declare function hasAcceptanceTests(tree: MarshalledPlainSource): boolean;
51
+ export interface CollectedLinkedResource extends LinkedResource {
52
+ sections: string[];
53
+ }
54
+ export declare function collectSpecificationLinkedResources(specification: SpecificationItem, specificationHeading: string, linkedResourcesList: CollectedLinkedResource[]): void;
55
+ export declare function collectLinkedResourcesInSection(section: MarshalledPlainSource, linkedResourcesList: CollectedLinkedResource[], specificationsList: string[] | null, includeAcceptanceTests: boolean, frid: string | null): boolean;
56
+ export declare function collectLinkedResources(tree: MarshalledPlainSource, linkedResourcesList: CollectedLinkedResource[], specificationsList: string[] | null, includeAcceptanceTests: boolean, frid?: string | null): boolean;
57
+ /**
58
+ * The FRID iterator: one functionality ID per functional spec, 1, 2, 3 in order.
59
+ * Everything that walks the spec one functionality at a time - rendering, ranges, context
60
+ * building - is driven by this.
61
+ */
62
+ export declare function getFrids(tree: MarshalledPlainSource): Generator<string>;
63
+ export declare function getFirstFrid(tree: MarshalledPlainSource): string | null;
64
+ export declare function getNextFrid(tree: MarshalledPlainSource, frid: string): string | null;
65
+ export declare function getPreviousFrid(tree: MarshalledPlainSource, frid: string): string | null;
66
+ export declare function getFridsBefore(tree: MarshalledPlainSource, targetFrid: string): string[];
67
+ export declare function getSpecificationItemMarkdown(specificationItem: SpecificationItem, codeVariables: Record<string, string>, replaceCodeVariables: boolean): string;
68
+ export interface Specifications {
69
+ [DEFINITIONS]: string[];
70
+ [NON_FUNCTIONAL_REQUIREMENTS]: string[];
71
+ [TEST_REQUIREMENTS]: string[];
72
+ [FUNCTIONAL_REQUIREMENTS]: string[];
73
+ [ACCEPTANCE_TESTS]?: string[];
74
+ }
75
+ /**
76
+ * Build the rendering context for one functionality: every definition and
77
+ * implementation/test req in scope, the functionalities up to and including this one,
78
+ * and this one's acceptance tests.
79
+ */
80
+ export declare function getSpecificationsForFrid(tree: MarshalledPlainSource, frid: string, replaceCodeVariables?: boolean): [Specifications, Record<string, string> | null];
81
+ /** Iterate every functionality with the context that should be rendered for it. */
82
+ export declare function iterateFunctionalSpecs(tree: MarshalledPlainSource, replaceCodeVariables?: boolean): Generator<{
83
+ frid: string;
84
+ specifications: Specifications;
85
+ codeVariables: Record<string, string> | null;
86
+ }>;
87
+ export declare function hashText(text: string): string;
88
+ export declare function getHashValue(specifications: unknown): string;
89
+ export declare function getRenderRange(renderRange: string, tree: MarshalledPlainSource): string[];
90
+ export declare function getRenderRangeFrom(start: string, tree: MarshalledPlainSource): string[];
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The ***plain standard library's names. `stdlib/` is a reserved prefix: `stdlib/backend/python-fastapi`
3
+ * is always turri's own template, in its `stdlib/` folder - never a module of the project's. A
4
+ * project that has a module at such a path gets an error, not a quiet choice between the two: which one
5
+ * a spec builds on must never depend on what happens to be on disk beside it.
6
+ *
7
+ * This is turri's, not the reference parser's: the Python parser has no standard library.
8
+ */
9
+ export declare const STDLIB_PREFIX = "stdlib/";
10
+ /** The folder `stdlib/` is in: turri's own. */
11
+ export declare const STDLIB_ROOT: string;
12
+ export declare function isStdlibModule(moduleName: string): boolean;
13
+ /** A standard library module's text - refused when a folder the spec is resolved from has a module of that name too. */
14
+ export declare function readStdlibModule(moduleName: string, templateDirs: string[]): string;
@@ -0,0 +1,51 @@
1
+ import { type Component, type Focusable, type TuiMouseEvent, type TuiMouseEventResult } from "@earendil-works/pi-tui";
2
+ /**
3
+ * The dialog a question is put to the person in, in the TUI: what they must read to answer - a brief to confirm, a plan
4
+ * to approve - above the question, and the options, or a line to type the answer on.
5
+ *
6
+ * pi's own select puts all of it in its title, so a long brief pushes the options off the screen: the person answers a
7
+ * question they cannot see the choices of. Here the brief scrolls in a window of its own, sized to the terminal, and
8
+ * the question and its options always show below it - PgUp/PgDn or Shift+Up/Down scroll it, and the mouse wheel.
9
+ */
10
+ export interface DialogStyle {
11
+ accent(text: string): string;
12
+ muted(text: string): string;
13
+ bold(text: string): string;
14
+ }
15
+ export interface QuestionDialogOptions {
16
+ /** What to read to answer: shown above the question, scrolling when it is long. Markdown's **bold** and `code` shown as such. */
17
+ context?: string;
18
+ question: string;
19
+ /** The choices. Without them, a line to type the answer on. */
20
+ options?: string[];
21
+ /** The choice the cursor starts on. */
22
+ selected?: number;
23
+ /** The terminal's height, for the window the brief scrolls in. */
24
+ rows: () => number;
25
+ style: DialogStyle;
26
+ /** The answer - an option, or what was typed - or undefined, dismissed. */
27
+ done: (answer: string | undefined) => void;
28
+ /** Draw again: a key changed what shows. */
29
+ requestRender: () => void;
30
+ }
31
+ export declare class QuestionDialog implements Component, Focusable {
32
+ private readonly options;
33
+ private readonly input;
34
+ private selected;
35
+ /** The brief's first line in its window. */
36
+ private scroll;
37
+ /** How far the brief scrolls, and its window's height - as last drawn. */
38
+ private maxScroll;
39
+ private window;
40
+ private answered;
41
+ private focusedNow;
42
+ constructor(options: QuestionDialogOptions);
43
+ get focused(): boolean;
44
+ set focused(value: boolean);
45
+ private finish;
46
+ private scrollBy;
47
+ render(width: number): string[];
48
+ handleInput(data: string): void;
49
+ handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
50
+ invalidate(): void;
51
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * How many questions an interview may put to the person in each phase it caps, and how broad each is - the
3
+ * questioning level, the first thing a skill with `metadata.questioning` asks. Light, medium and thorough cap each such
4
+ * phase at 3, 5 and 10 questions; best judgement leaves it to the agent, which says when it has asked enough. Every
5
+ * level covers the same ground: fewer questions are broader ones, and what they leave open the agent decides itself.
6
+ * The level limits the questions, never the spec changes. The phase's closing confirmation, asked with
7
+ * `confirms_phase`, is never counted.
8
+ */
9
+ export interface QuestioningLevel {
10
+ name: string;
11
+ /** Questions a capped phase may ask; none for best judgement. */
12
+ cap?: number;
13
+ /** As the person is offered it. */
14
+ option: string;
15
+ /** How broad each question is, as the agent is told. */
16
+ breadth: string;
17
+ }
18
+ export declare const QUESTIONING_LEVELS: QuestioningLevel[];
19
+ /** The level an answer picks: by its name, wherever it is in the answer; anything else is best judgement. */
20
+ export declare function levelOf(answer: string): QuestioningLevel;
21
+ /** The question the harness puts first, and what the person reads above it. */
22
+ export declare function questioningQuestion(phases: string[]): {
23
+ question: string;
24
+ options: string[];
25
+ context: string;
26
+ };
27
+ /** What a resumed run picks up: the level, and how far each phase's questions went. */
28
+ export interface QuestioningState {
29
+ level: string;
30
+ asked: Record<string, number>;
31
+ /** Phases whose questions are over. */
32
+ over: string[];
33
+ }
34
+ export interface Questioning {
35
+ level: QuestioningLevel;
36
+ /** The phase now running. */
37
+ enter(phase: string): void;
38
+ /** Why a question may not be asked now, or undefined when it may. */
39
+ refusal(confirmsPhase: boolean): string | undefined;
40
+ /** A question was answered. */
41
+ answered(confirmsPhase: boolean): void;
42
+ /** The agent ends this phase's questions itself; what to tell it. */
43
+ end(): string;
44
+ /** What the agent is told of the level as a phase starts. */
45
+ note(phase: string, first: boolean): string | undefined;
46
+ state(): QuestioningState;
47
+ }
48
+ export declare function createQuestioning(options: {
49
+ level: QuestioningLevel;
50
+ /** The phases the level caps. */
51
+ phases: string[];
52
+ from?: QuestioningState;
53
+ /** Called whenever the state changes, to keep it for a resume. */
54
+ onChange?: (state: QuestioningState) => void;
55
+ }): Questioning;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Keeps library chatter out of the terminal while a tool runs.
3
+ *
4
+ * A skill run spawns many nested agent sessions - an executor, two judges per gate, a fix
5
+ * agent, each queued render - and libraries underneath them write to the console. In the
6
+ * TUI every one of those writes interrupts the differential renderer, which abandons the
7
+ * current frame and leaves it stranded in scrollback. Dozens of "Working" lines pile up.
8
+ *
9
+ * Only the `console` methods are intercepted, never `process.stdout.write` itself: that is
10
+ * how pi draws the TUI, and silencing it would blank the screen. Library noise goes
11
+ * through `console`; pi's rendering does not.
12
+ */
13
+ /** Drop the NOISE warnings for good, from here on - captured or not. Safe to call more than once. */
14
+ export declare function dropNoise(): void;
15
+ export interface Captured<T> {
16
+ result: T;
17
+ /** Whatever the libraries tried to print, in order. */
18
+ output: string[];
19
+ }
20
+ /** Run `fn` with console output collected instead of printed. */
21
+ export declare function captureConsole<T>(fn: () => Promise<T>): Promise<Captured<T>>;
22
+ /**
23
+ * Capture that spans something other than one promise - a whole agent turn, say.
24
+ *
25
+ * `captureConsole` covers work it can wrap. A conversation's own model calls happen inside
26
+ * pi's agent loop, where there is nothing to wrap, so those are bracketed by hand instead.
27
+ * `end` is safe to call twice and safe to skip: an unbalanced `begin` leaves the console
28
+ * patched, so callers must end it from a handler that always runs.
29
+ */
30
+ export declare function beginCapture(): {
31
+ end: () => string[];
32
+ };
33
+ /** One line noting what was swallowed, or nothing when it was quiet. */
34
+ export declare function describeCaptured(output: string[]): string | null;
@@ -0,0 +1,207 @@
1
+ /**
2
+ * What a background job is doing right now.
3
+ *
4
+ * A render is minutes of agents working with nothing on screen. The work is several layers
5
+ * deep - a chain, a module, a functionality, an agent session, its tool calls - and
6
+ * threading a callback through all of them would touch every signature on the way. Instead
7
+ * each job runs inside its own async context, and anything underneath it reports into
8
+ * whichever job it is running for: the render steps say which stage they are at, and every
9
+ * agent session reports its tool calls. Outside a job, reporting is a no-op.
10
+ */
11
+ export interface ActivitySink {
12
+ /** Which stage of the work this is, e.g. "writing code and unit tests". */
13
+ stage(label: string): void;
14
+ /** One thing that just happened, e.g. "✎ write greeter.py". */
15
+ activity(line: string): void;
16
+ /** A line about the machinery under the work - which walls are up, what a command changed that was put back - kept in the job's log too. */
17
+ note?(line: string): void;
18
+ /**
19
+ * What is happening at this moment, e.g. "thinking", or undefined when nothing is.
20
+ * `keepSince` updates the words without restarting the clock on it.
21
+ */
22
+ now(label: string | undefined, options?: {
23
+ keepSince?: boolean;
24
+ }): void;
25
+ /** What one model response cost. */
26
+ usage(usage: UsageReport): void;
27
+ /** One agent's share of the work: a turn it took, a compaction, what a model call of it cost. */
28
+ agent?(tally: AgentReport): void;
29
+ /** One piece of the full conversation, for reading it back while it happens. */
30
+ transcript(entry: TranscriptEntry): void;
31
+ /** Aborted when the job is asked to stop. */
32
+ signal?: AbortSignal;
33
+ /** Which job this is, for what records it - a debug log's header. */
34
+ job?: {
35
+ id: string;
36
+ kind: string;
37
+ summary: string;
38
+ };
39
+ /** The spec was found to contradict itself - for the person to decide. */
40
+ specConflict?(conflict: SpecConflict): void;
41
+ /** The functional spec being built now, or nothing when none is. */
42
+ spec?(spec: BuildingSpec | undefined): void;
43
+ }
44
+ /** A functional spec as it is being built: where it sits, and its text as the spec has it. */
45
+ export interface BuildingSpec {
46
+ /** E.g. "rt_tuples functionality 2 of 5". */
47
+ label: string;
48
+ text: string;
49
+ /**
50
+ * When work on it began - set by the job, and kept while the same one goes on to its next stage
51
+ * (its conformance tests, the whole suite), so its time is the whole of it.
52
+ */
53
+ since?: number;
54
+ }
55
+ /** Say which functional spec is being built now - shown with the job, and in its transcript. */
56
+ export declare function reportSpec(spec: BuildingSpec | undefined): void;
57
+ /**
58
+ * Two functional specs that cannot both hold, as a conformance run's judge found them - the times
59
+ * it takes to count. Nothing in the code or the tests can fix it: the person decides which is meant.
60
+ */
61
+ export interface SpecConflict {
62
+ /** The module whose conformance run found it, and its .plain file. */
63
+ moduleName: string;
64
+ plainFile: string;
65
+ /**
66
+ * The two functionalities - in that module, or in one it requires - each with its module, its
67
+ * id there, the .plain file it is in, and its functional spec as that file has it.
68
+ */
69
+ specs: Array<{
70
+ module: string;
71
+ frid: string;
72
+ plainFile: string;
73
+ text: string;
74
+ }>;
75
+ /** What the judge said each time it raised it, oldest first. */
76
+ reasons: string[];
77
+ }
78
+ /** Say the spec contradicts itself, to the job this runs for. */
79
+ export declare function reportSpecConflict(conflict: SpecConflict): void;
80
+ /** Raised inside a job that was asked to stop, so the work unwinds instead of carrying on. */
81
+ export declare class JobStoppedError extends Error {
82
+ constructor();
83
+ }
84
+ /** The stop signal of the job this code is running for, if it is running for one. */
85
+ export declare function currentStopSignal(): AbortSignal | undefined;
86
+ /** The job this code is running for, if it is running for one. */
87
+ export declare function currentJob(): {
88
+ id: string;
89
+ kind: string;
90
+ summary: string;
91
+ } | undefined;
92
+ /**
93
+ * The conversation an agent is having, as it happens: what it was asked, what it wrote and
94
+ * thought, what it called and what came back. Text and thinking arrive as deltas and are
95
+ * joined to the entry before them of the same kind.
96
+ */
97
+ export interface TranscriptEntry {
98
+ /** `diff`: a spec change the job is about to render, as a git diff. */
99
+ kind: "stage" | "spec" | "diff" | "prompt" | "text" | "thinking" | "tool" | "result";
100
+ text: string;
101
+ /** For a result: whether the tool failed. */
102
+ error?: boolean;
103
+ /** The whole of it, where `text` is clipped for the screen - a tool call's arguments, its result. */
104
+ full?: string;
105
+ /** Which agent it is from, e.g. "app 1 judge", and what it runs on - for a prompt, a reply, a thought, a tool call, a result. */
106
+ agent?: {
107
+ label: string;
108
+ model?: string;
109
+ };
110
+ }
111
+ export declare function reportTranscript(entry: TranscriptEntry): void;
112
+ /** The part of a model response's usage a job adds up. */
113
+ export interface UsageReport {
114
+ input: number;
115
+ output: number;
116
+ cacheRead: number;
117
+ cacheWrite: number;
118
+ cost: number;
119
+ }
120
+ /**
121
+ * What a stage is about, said so the person knows what the name is: "module backend", or "module
122
+ * backend, functionality 2". A stage leads with it: `${unitOf(moduleName, frid)}: running the tests`.
123
+ */
124
+ export declare function unitOf(moduleName: string, frid?: string): string;
125
+ export declare function reportUsage(usage: UsageReport): void;
126
+ /** What one agent of a job did, added to what it did before: counted by its label. */
127
+ export interface AgentReport {
128
+ label: string;
129
+ model?: string;
130
+ turns?: number;
131
+ compactions?: number;
132
+ usage?: UsageReport;
133
+ }
134
+ /** Each agent of a job, as the job adds it up: how many turns it took, how often its work was compacted, what it cost. */
135
+ export interface AgentTally {
136
+ label: string;
137
+ model?: string;
138
+ turns: number;
139
+ compactions: number;
140
+ usage: UsageReport;
141
+ }
142
+ export declare function reportAgent(report: AgentReport): void;
143
+ /** Add one agent report to a job's tally, by label - its first report starts its row. */
144
+ export declare function addAgentReport(tallies: AgentTally[], report: AgentReport): void;
145
+ /** A job's agents, a line each: "app 1 reviewer · 3 turns · 1 compaction · 210.4k tok · $0.41". */
146
+ export declare function describeAgents(tallies: AgentTally[]): string[];
147
+ /** "1.2k tok · $0.03", or "" when nothing has been spent yet. */
148
+ export declare function describeUsage(usage: UsageReport | undefined): string;
149
+ /**
150
+ * Something an agent did with its model, wherever it ran - in a pulse or not, the planner and the chooser too: what a
151
+ * headless run's report adds up (run-report.ts). A call is one model response; a turn, one request of the harness's
152
+ * to an agent, as many calls as it takes; a compaction, its work summed up - a call of its own. A provider retry is a
153
+ * request the provider failed for a moment, waited out and tried again - by pi, or by turri after pi gave up; a provider
154
+ * stall, a request the provider has sent nothing back on for a long while; a stop, a turn turri itself ended - the
155
+ * agent going round in a circle, or its time up - after which the harness carries on as after any turn.
156
+ */
157
+ export interface ModelEvent {
158
+ kind: "call" | "turn" | "compaction" | "provider_retry" | "provider_stall" | "stopped";
159
+ /** For a provider retry: what the provider said, the try this is and how many there may be, and the wait before it. For a stall, waitMs is how long it has been silent. */
160
+ error?: string;
161
+ attempt?: number;
162
+ of?: number;
163
+ waitMs?: number;
164
+ /** For a stop: why turri ended the turn. */
165
+ reason?: string;
166
+ /** "provider/model-id:thinking", when known. */
167
+ model?: string;
168
+ role?: string;
169
+ label?: string;
170
+ /** The job it was made for: none outside a pulse. */
171
+ job?: string;
172
+ usage?: UsageReport;
173
+ /** For a call: how long the model took to answer it, in milliseconds. */
174
+ ms?: number;
175
+ }
176
+ /** Hear of every model call, turn and compaction from now on. Returns what stops it. */
177
+ export declare function onModelEvent(listener: (event: ModelEvent) => void): () => void;
178
+ /**
179
+ * The model provider failing or stalling, in a line for the person: the chat's notification, a headless run's console.
180
+ * A turn turri stopped itself is the work going its normal course - kept in the activity, the pulse's log and the run
181
+ * report, not said.
182
+ */
183
+ export declare function describeTurnIncident(event: ModelEvent): string | undefined;
184
+ export declare function reportModelEvent(event: Omit<ModelEvent, "job">): void;
185
+ export declare function withActivity<T>(sink: ActivitySink, run: () => Promise<T>): Promise<T>;
186
+ export declare function reportStage(label: string): void;
187
+ export declare function reportActivity(line: string): void;
188
+ /** Say something about the machinery under the work: shown as activity, and kept in the job's log, which the activity is not. */
189
+ export declare function reportNote(line: string): void;
190
+ /** Say something for the job's log alone: the machinery, not what its agents are doing. */
191
+ export declare function reportLogNote(line: string): void;
192
+ export declare function reportNow(label: string | undefined, options?: {
193
+ keepSince?: boolean;
194
+ }): void;
195
+ /**
196
+ * Paths as they are inside `plain_modules`: everything up to and including it left out, wherever
197
+ * a path to it appears - `/Users/…/project/plain_modules/app/code/main.py` is `app/code/main.py`.
198
+ * The rest of the path is the same for every line, and is what pushes the part that differs off
199
+ * the end of it.
200
+ */
201
+ export declare function withinModules(text: string): string;
202
+ /** A tool's name as the person is shown it. */
203
+ export declare function shownName(name: string): string;
204
+ /** A tool call as one short line. Unknown tools still show up, by name. */
205
+ export declare function describeToolCall(name: string, args: Record<string, unknown> | undefined): string;
206
+ /** The outcome of a test run, or nothing for tools whose outcome is not worth a line. */
207
+ export declare function describeToolResult(name: string, result: unknown, isError: boolean): string | undefined;
@@ -0,0 +1,44 @@
1
+ /** The variables that locate a toolchain - their folders are what the OS sandbox lets a command read of the person's. */
2
+ export declare const TOOLCHAIN_VARIABLES: string[];
3
+ /** Where package managers keep their caches: in the project's scratch area, so a dependency downloads once. */
4
+ export declare function packageCacheDir(dir: string): string;
5
+ /** Every package manager's cache, pointed into `cache`. */
6
+ export declare function cacheEnv(cache: string): Record<string, string>;
7
+ /** A credential `agent-env:` names that is not there. */
8
+ export interface MissingCredential {
9
+ /** The file or the variable. */
10
+ name: string;
11
+ why: string;
12
+ }
13
+ export interface AgentEnvironment {
14
+ /** The whole environment of an agent's command. */
15
+ env: Record<string, string>;
16
+ /** The names of what `agent-env:` passed, sorted - for the prompt, never the values. */
17
+ passed: string[];
18
+ /** The values `agent-env:` passed, by name - what is masked wherever turri shows or writes output. */
19
+ values: Record<string, string>;
20
+ /** What `agent-env:` names that is not there. */
21
+ missing: MissingCredential[];
22
+ }
23
+ /**
24
+ * The environment of a command an agent runs in `moduleDir` - `plain_modules/<module>`. `hostEnv`: the environment
25
+ * turri was started in; `home`: the person's home folder.
26
+ */
27
+ export declare function agentEnvironment(moduleDir: string, options?: {
28
+ hostEnv?: NodeJS.ProcessEnv;
29
+ home?: string;
30
+ }): AgentEnvironment;
31
+ /**
32
+ * On macOS, what a program asks the system for as the per-user temporary folder - not TMPDIR - is that folder with this
33
+ * suffix added: a folder of the module's own inside it. The JVM keeps its attach sockets there (`.java_pid<pid>`), which
34
+ * Mockito's inline mocks, jcmd and jstack attach through; the sandbox reaches this folder alone, never the person's
35
+ * JVMs' sockets beside it.
36
+ */
37
+ export declare const DARWIN_TEMP_SUFFIX = "DIRHELPER_USER_DIR_SUFFIX";
38
+ /** What `agent-env:` - the project's, with the chosen stack's added - passes, and what of it is not there. Reads only. */
39
+ export declare function passedCredentials(module: string, hostEnv: NodeJS.ProcessEnv): {
40
+ values: Record<string, string>;
41
+ missing: MissingCredential[];
42
+ };
43
+ /** A dotenv file's variables: `KEY=value`, `export KEY=value`, quoted or not; comments and blank lines skipped. */
44
+ export declare function parseDotenv(text: string): Record<string, string>;
@@ -0,0 +1,49 @@
1
+ import { type CheckResult } from "./command-check.ts";
2
+ import { type Wall } from "./os-sandbox.ts";
3
+ import { type RunResult } from "./shell.ts";
4
+ /**
5
+ * An agent's command on this machine, behind every wall at once: the command check before it, the module's scrubbed
6
+ * environment and the OS sandbox around it - where one is up - and the audit after it. Built once per agent from its
7
+ * role's fence, the same as its file tools': what it may read and write.
8
+ */
9
+ export interface ShellRole {
10
+ /** Where its commands start - the agent's folder. */
11
+ workdir: string;
12
+ /** The folders it may read; its workdir when not given. */
13
+ read?: string[];
14
+ /** The folders it may write; its workdir when not given, none for a role that only reads. */
15
+ write?: string[];
16
+ }
17
+ export interface AgentShell {
18
+ /** The wall under the check and the audit. */
19
+ readonly wall: Wall;
20
+ /** The environment its commands get. */
21
+ readonly env: Record<string, string>;
22
+ /** One line for the job log: which walls are up. */
23
+ readonly description: string;
24
+ /** The check alone: whether a command would be run. */
25
+ check(command: string): CheckResult;
26
+ /** How a command is run behind the wall. */
27
+ wrap(argv: string[]): string[];
28
+ /** Run a command behind every wall; refused, it is not run and says why (exit 126). */
29
+ run(command: string, options?: {
30
+ timeoutMs?: number;
31
+ signal?: AbortSignal;
32
+ onData?: (data: Buffer) => void;
33
+ timeoutNote?: (ms: number) => string;
34
+ }): Promise<RunResult>;
35
+ /** Run `work` - something that starts a command another way - under the audit; what it puts back, for the agent. */
36
+ audited<T>(work: () => Promise<T>): Promise<{
37
+ value: T;
38
+ note?: string;
39
+ }>;
40
+ }
41
+ /**
42
+ * What a module's shell writes beside its roots: its home, its TMPDIR, the package caches - and on macOS its own folder
43
+ * in the per-user temporary folder, where its JVMs keep the attach sockets Mockito's inline mocks and jcmd go through.
44
+ */
45
+ export declare function writableFor(env: Record<string, string>, moduleDir: string): string[];
46
+ export declare function agentShell(role: ShellRole, options?: {
47
+ wall?: Wall;
48
+ busy?: (moduleDir: string) => boolean;
49
+ }): AgentShell;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The arbiter: the third voice in a review. The coding agent writes the tests; the reviewer - exacting,
3
+ * opinionated, hard to satisfy - sends them back with everything it finds; after the first review that sends
4
+ * them back, the arbiter weighs what each one found before any of it goes back. It is the distinguished engineer
5
+ * who balances the trade-offs: the tests have to be good, and time lost chasing perfect ones is lost too. It
6
+ * upholds a problem when the reviewer is right - a behaviour the spec states is untested, or a test cannot
7
+ * fail - and dismisses it when it is out of scope or a nitpick. Only what it upholds goes back; when it upholds
8
+ * nothing, the tests are approved as they are. Read-only, like the reviewer.
9
+ */
10
+ /**
11
+ * How many reviews that send the work back go to the agent as they are: every one after them the arbiter weighs
12
+ * first, and only what it upholds goes back.
13
+ */
14
+ export declare const ARBITER_AFTER = 1;
15
+ /**
16
+ * How many reviews at most. What the last one sends back - weighed by the arbiter - goes to the agent once more, and
17
+ * then the work goes on without another review, once its tests pass.
18
+ */
19
+ export declare const REVIEW_LIMIT = 2;
20
+ /** A problem a review raised: in the unit tests or the conformance tests alike. */
21
+ export interface ReviewedProblem {
22
+ file: string;
23
+ test?: string;
24
+ /** "wrong" is the code's: it does not do what the spec says. The unit review raises it; the conformance review does not. */
25
+ kind: "missing" | "bad" | "wrong";
26
+ what: string;
27
+ blocking?: boolean;
28
+ }
29
+ /** What the arbiter ruled: the problems it upholds, and those it lets go, each with why. */
30
+ export interface ArbiterRuling<P extends ReviewedProblem = ReviewedProblem> {
31
+ upheld: Array<{
32
+ problem: P;
33
+ why: string;
34
+ }>;
35
+ dismissed: Array<{
36
+ problem: P;
37
+ why: string;
38
+ }>;
39
+ }
40
+ export interface ArbiterOptions<P extends ReviewedProblem> {
41
+ /** "the unit tests of functionality 3", "the conformance tests of the spec change". */
42
+ subject: string;
43
+ /** Where it works, and what it may read: the tests and the code. */
44
+ workdir: string;
45
+ read: string[];
46
+ /** When a problem is upheld: what the tests must do for this kind of review. */
47
+ uphold: string[];
48
+ /** The test files the work added or changed. */
49
+ changed: string[];
50
+ /** The specification the work built, as the reviewer had it - shown as it is given. */
51
+ spec: string;
52
+ /** What the work wrote: the diff of its folder from where it started (`workDiff`). */
53
+ code?: string;
54
+ /** The problems the latest review raised. */
55
+ problems: P[];
56
+ /** What each review before sent back, oldest first. */
57
+ history: P[][];
58
+ label: string;
59
+ model?: string;
60
+ onDelta?: (delta: string) => void;
61
+ }
62
+ export declare function problemLine(problem: ReviewedProblem): string;
63
+ /** The arbiter's prompt: the spec, the reviews so far, and the latest one's problems, numbered. */
64
+ export declare function arbiterPrompt<P extends ReviewedProblem>(options: Omit<ArbiterOptions<P>, "label" | "model" | "onDelta">): string;
65
+ /** The arbiter's ruling on the latest review - or nothing, when it gave none: the review then stands. */
66
+ export declare function arbitrateReview<P extends ReviewedProblem>(options: ArbiterOptions<P>): Promise<ArbiterRuling<P> | undefined>;
67
+ /** What the arbiter let go, for the working notes' pitfalls. */
68
+ export declare function dismissedNote(ruling: ArbiterRuling, what: string): string;