bareloop 0.35.0 → 0.37.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/CHANGELOG.md +50 -0
- package/bareloop.context.md +69 -22
- package/package.json +1 -1
- package/src/authorrun.js +5 -5
- package/src/bundlerun.js +4 -8
- package/src/draftspend.js +114 -1
- package/src/exits.js +3 -0
- package/src/index.js +3 -3
- package/src/legs.js +1 -1
- package/src/movefile.js +22 -0
- package/src/npminstall.js +55 -0
- package/src/panel/authorroutes.js +12 -1
- package/src/panel/authorsession.js +95 -28
- package/src/panel/index.html +317 -76
- package/src/panel/server.js +176 -16
- package/src/panel/settingsroutes.js +52 -2
- package/src/panel/status.js +22 -0
- package/src/planrun.js +10 -7
- package/src/ralph.js +1 -1
- package/src/source.js +55 -4
- package/src/u-patient.js +3 -2
- package/src/userrun.js +56 -10
- package/src/worktree.js +120 -0
- package/types/draftspend.d.ts +88 -0
- package/types/legs.d.ts +1 -1
- package/types/movefile.d.ts +9 -0
- package/types/npminstall.d.ts +30 -0
- package/types/panel/authorroutes.d.ts +4 -1
- package/types/panel/authorsession.d.ts +4 -8
- package/types/panel/server.d.ts +30 -2
- package/types/panel/settingsroutes.d.ts +6 -1
- package/types/panel/status.d.ts +20 -0
- package/types/planrun.d.ts +3 -3
- package/types/ralph.d.ts +19 -0
- package/types/source.d.ts +20 -5
- package/types/userrun.d.ts +10 -0
- package/types/worktree.d.ts +48 -0
package/types/planrun.d.ts
CHANGED
|
@@ -397,10 +397,10 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
|
|
|
397
397
|
* the resume-plan-red option, the fix-loop terminal) say "resume is `run-u`-only
|
|
398
398
|
* in v1" instead of naming a flag that would fail if typed.
|
|
399
399
|
* @param {string|null} [opts.stopFile=null] P5 item 5 — the run's STOP REQUEST file
|
|
400
|
-
* (`stopFilePath(spine)`, src/legs.js). Read at ONE seam, the round boundary of
|
|
401
|
-
* (the `metered` callback, where the money cap binds): present = emit `stop-requested`, consume
|
|
400
|
+
* (`stopFilePath(spine)`, src/legs.js). Read at ONE seam, the round boundary of EVERY worker
|
|
401
|
+
* (scout, plan/replan drafter, step, close-fix: the `metered` callback, where the money cap binds): present = emit `stop-requested`, consume
|
|
402
402
|
* the file, end the Loop after that round, and end the leg `stopped` (a checkpoint outcome, filed
|
|
403
|
-
* the way a mid-step cap-halt is; resume re-enters that step). Nothing is in flight at that
|
|
403
|
+
* the way a mid-step cap-halt is; resume re-enters that step, or continues the phase). Nothing is in flight at that
|
|
404
404
|
* point, so the spend is exact. `null` = no stop surface (the default).
|
|
405
405
|
* @returns {Promise<string>} 'green' | 'already-green' | 'escalated' | 'plan-red' |
|
|
406
406
|
* 'check-red' | 'close-red' | 'close-unsupported' | 'recipe-stale' | 'pricing-red' |
|
package/types/ralph.d.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} cmd
|
|
3
|
+
* @param {string[]} args
|
|
4
|
+
* @param {{env: NodeJS.ProcessEnv, cwd?: string, timeoutMs?: number}} o
|
|
5
|
+
* @returns {Promise<{error: (Error & {code?: string})|null, status: number|null, signal: string|null, stdout: string, stderr: string}>}
|
|
6
|
+
*/
|
|
7
|
+
export function spawnClose(cmd: string, args: string[], { env, cwd, timeoutMs }: {
|
|
8
|
+
env: NodeJS.ProcessEnv;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
error: (Error & {
|
|
13
|
+
code?: string;
|
|
14
|
+
}) | null;
|
|
15
|
+
status: number | null;
|
|
16
|
+
signal: string | null;
|
|
17
|
+
stdout: string;
|
|
18
|
+
stderr: string;
|
|
19
|
+
}>;
|
|
1
20
|
/**
|
|
2
21
|
* Run a close command; its exit code is the verdict (hard green, PRD §4).
|
|
3
22
|
* `expect` → satisfied; any other exit → needs_revision (gap fed back).
|
package/types/source.d.ts
CHANGED
|
@@ -71,19 +71,25 @@ export function looksLikeRepoSource(source: string): boolean;
|
|
|
71
71
|
* as declared, unvalidated by `proveDestination`, and `frontDoorFromManifest`
|
|
72
72
|
* never hands a repo source's destination to `copyOut` — wiring it into
|
|
73
73
|
* `writeScope` is M3/M4's job, not this one.
|
|
74
|
-
*
|
|
74
|
+
* `worktree` (P6 item 1, repo sources ONLY — ignored for every other kind): instead of COPYING the repo, make the
|
|
75
|
+
* run's tree a detached git worktree of the person's own repo at that directory (the shared
|
|
76
|
+
* `src/worktree.js`, the bundle door's own spelling), hide `.bareloop/` from their `git status`, and record the
|
|
77
|
+
* worktree and the repo root in the manifest. `into` then holds only `source.json`; the tree is `worktree`, at the
|
|
78
|
+
* repo's current commit (uncommitted edits are NOT in it). No seed commit is made — the seed IS the repo's HEAD.
|
|
79
|
+
* @param {{source: string, into: string, destination?: string, worktree?: string,
|
|
75
80
|
* fetchTimeoutMs?: number, afterScan?: () => (void|Promise<void>)}} args
|
|
76
81
|
* `fetchTimeoutMs` is test-only — production callers omit it and get
|
|
77
82
|
* `PROVIDER_TIMEOUT_MS`. `afterScan` is a test seam too: called exactly once,
|
|
78
83
|
* after the secret scan finished and before the freeze loop re-reads any
|
|
79
84
|
* file's bytes, so a test can swap a file inside that window
|
|
80
85
|
* deterministically. Production never sets it; absent, behaviour is unchanged.
|
|
81
|
-
* @returns {Promise<{stop: null, into: string, tree: string, manifestPath: string, manifest:
|
|
86
|
+
* @returns {Promise<{stop: null, into: string, tree: string, manifestPath: string, manifest: Record<string, any>}|SourceRefusal>}
|
|
82
87
|
*/
|
|
83
|
-
export function prepareSource({ source, into, destination, fetchTimeoutMs, afterScan }: {
|
|
88
|
+
export function prepareSource({ source, into, destination, worktree, fetchTimeoutMs, afterScan }: {
|
|
84
89
|
source: string;
|
|
85
90
|
into: string;
|
|
86
91
|
destination?: string;
|
|
92
|
+
worktree?: string;
|
|
87
93
|
fetchTimeoutMs?: number;
|
|
88
94
|
afterScan?: () => (void | Promise<void>);
|
|
89
95
|
}): Promise<{
|
|
@@ -91,7 +97,7 @@ export function prepareSource({ source, into, destination, fetchTimeoutMs, after
|
|
|
91
97
|
into: string;
|
|
92
98
|
tree: string;
|
|
93
99
|
manifestPath: string;
|
|
94
|
-
manifest:
|
|
100
|
+
manifest: Record<string, any>;
|
|
95
101
|
} | SourceRefusal>;
|
|
96
102
|
/**
|
|
97
103
|
* THE INSTALL-GAP DETECTOR (PRD item 33 close-out, `docs/product/PRD.md:450-452`,
|
|
@@ -127,13 +133,15 @@ export function prepareSource({ source, into, destination, fetchTimeoutMs, after
|
|
|
127
133
|
* manifest)
|
|
128
134
|
* @param {string} [sourceSubdir] the manifest's own `sourceSubdir` ('' or
|
|
129
135
|
* undefined when Source IS the repo root)
|
|
130
|
-
* @returns {{manager: string, command: string, reason: string}|null} `null`
|
|
136
|
+
* @returns {{dir: string, lockFile: string|null, manager: string, command: string, reason: string}|null} `null`
|
|
131
137
|
* when there is nothing to report: no JS/TS manifest found walking up from
|
|
132
138
|
* `sourceSubdir` to `treeDir`, the nearest one found has no dependencies,
|
|
133
139
|
* `node_modules` is already there, or the manifest cannot even be read as
|
|
134
140
|
* JSON (an invalid `package.json` is "cannot tell", never a false alarm).
|
|
135
141
|
*/
|
|
136
142
|
export function missingDependencies(treeDir: string, sourceSubdir?: string): {
|
|
143
|
+
dir: string;
|
|
144
|
+
lockFile: string | null;
|
|
137
145
|
manager: string;
|
|
138
146
|
command: string;
|
|
139
147
|
reason: string;
|
|
@@ -289,6 +297,13 @@ export function frontDoorFromManifest(read: {
|
|
|
289
297
|
}): {
|
|
290
298
|
destination: string;
|
|
291
299
|
} | null;
|
|
300
|
+
/**
|
|
301
|
+
* The $0 refusal for a non-repo source, worded by the kind the source door recorded (`prep.manifest.kind`) — a single
|
|
302
|
+
* file is not a "folder", and Source must be the repo folder with the file named in Destination (hamr 2026-10-05).
|
|
303
|
+
* @param {string} kind `prep.manifest.kind`: 'file' | 'folder' | 'url' (a 'repo' never reaches this)
|
|
304
|
+
* @returns {string}
|
|
305
|
+
*/
|
|
306
|
+
export function nonRepoSourceMessage(kind: string): string;
|
|
292
307
|
/**
|
|
293
308
|
* a named, non-throwing stop
|
|
294
309
|
*/
|
package/types/userrun.d.ts
CHANGED
|
@@ -129,6 +129,12 @@ export type RunOpts = {
|
|
|
129
129
|
* the spine directory name, beside `workdir`
|
|
130
130
|
*/
|
|
131
131
|
spineName?: string | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* the source door's own directory (`source.json`, and the spine directory beside it).
|
|
134
|
+
* Default `dirname(workdir)` — the copied-tree layout, where the tree is `<into>/tree`. A repo job on a WORKTREE
|
|
135
|
+
* (P6 item 1) has its tree inside the person's repo, so its `into` is passed explicitly.
|
|
136
|
+
*/
|
|
137
|
+
into?: string | undefined;
|
|
132
138
|
/**
|
|
133
139
|
* the raw `--model` tier name (`sonnet`/`haiku`), or null for the default
|
|
134
140
|
*/
|
|
@@ -194,6 +200,10 @@ export type RunCtx = {
|
|
|
194
200
|
workdir: string;
|
|
195
201
|
seed: string;
|
|
196
202
|
spineName: string;
|
|
203
|
+
/**
|
|
204
|
+
* see `RunOpts.into`
|
|
205
|
+
*/
|
|
206
|
+
into?: string | undefined;
|
|
197
207
|
model: string | null;
|
|
198
208
|
readShim: string | null;
|
|
199
209
|
scout: string | null;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** where a run's worktree lives in the person's repo @param {string} repo @param {string} id */
|
|
2
|
+
export function worktreePath(repo: string, id: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* `git worktree add --detach <dir> HEAD` in `repo` (none of the person's hooks run), creating `dir`'s parent first. Throws
|
|
5
|
+
* `Error('git worktree add failed: …')` — a caller decides whether that is a stop or a refusal.
|
|
6
|
+
* @param {string} repo @param {string} dir
|
|
7
|
+
*/
|
|
8
|
+
export function addWorktree(repo: string, dir: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* How many paths `git status --porcelain` lists in `repo` (tracked edits AND untracked files); 0 for a clean
|
|
11
|
+
* tree. A repo git cannot read counts as 0 — this feeds a notice, never a refusal.
|
|
12
|
+
* @param {string} repo @returns {number}
|
|
13
|
+
*/
|
|
14
|
+
export function uncommittedCount(repo: string): number;
|
|
15
|
+
/** the short sha of `repo`'s HEAD, or null @param {string} repo @returns {string|null} */
|
|
16
|
+
export function shortHead(repo: string): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Hide `.bareloop/` and `node_modules/` (packages installed in a worktree must not read as worker writes) from the person's own `git status` through the repo's PRIVATE exclude file
|
|
19
|
+
* (`<common-git-dir>/info/exclude`), never their tracked `.gitignore`. The common dir, not `.git`: in a linked
|
|
20
|
+
* worktree `.git` is a file and the shared `info/exclude` lives in the main repository's git dir. Idempotent —
|
|
21
|
+
* each line is checked separately and never written twice.
|
|
22
|
+
* @param {string} repo
|
|
23
|
+
* @returns {boolean} true when the line was added now
|
|
24
|
+
*/
|
|
25
|
+
export function hideBareloopDir(repo: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Remove a run's worktree folder from `repo` (`git worktree remove --force`: the folder may hold untracked
|
|
28
|
+
* scratch — a `.litectx/` index, the gate-audit file — and what matters is on the branch by now). Never throws.
|
|
29
|
+
* @param {string} repo @param {string} dir
|
|
30
|
+
* @returns {boolean} true when the folder is gone afterwards
|
|
31
|
+
*/
|
|
32
|
+
export function removeWorktree(repo: string, dir: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* The run's final commit, on whatever branch the worktree stands on: everything the run changed except the
|
|
35
|
+
* arbiter's books and `node_modules`. Nothing changed = no commit (a green with nothing to commit is still a green).
|
|
36
|
+
* Throws on a git failure — the caller must not remove a worktree whose work is not safely on the branch.
|
|
37
|
+
* @param {string} dir the worktree
|
|
38
|
+
* @param {string} message
|
|
39
|
+
* @returns {{committed: boolean, sha: string}}
|
|
40
|
+
*/
|
|
41
|
+
export function commitWork(dir: string, message: string): {
|
|
42
|
+
committed: boolean;
|
|
43
|
+
sha: string;
|
|
44
|
+
};
|
|
45
|
+
/** the line that hides bareloop's own folder from the person's `git status` (anchored at the repo root) */
|
|
46
|
+
export const EXCLUDE_LINE: "/.bareloop/";
|
|
47
|
+
/** the line that hides installed packages at any depth */
|
|
48
|
+
export const NODE_MODULES_LINE: "node_modules/";
|