looply-cli 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.src-hash +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +91 -85
- package/dist/bin.js.map +1 -1
- package/dist/connect-node.d.ts +8 -0
- package/dist/connect-node.d.ts.map +1 -0
- package/dist/connect-node.js +110 -0
- package/dist/connect-node.js.map +1 -0
- package/dist/connect.d.ts +135 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +329 -0
- package/dist/connect.js.map +1 -0
- package/dist/daemon-cmd.d.ts +11 -2
- package/dist/daemon-cmd.d.ts.map +1 -1
- package/dist/daemon-cmd.js +20 -6
- package/dist/daemon-cmd.js.map +1 -1
- package/dist/goal-compile.d.ts.map +1 -1
- package/dist/goal-compile.js +4 -1
- package/dist/goal-compile.js.map +1 -1
- package/dist/mcp-main.js +10 -0
- package/dist/mcp-main.js.map +1 -1
- package/dist/mcp-server.d.ts +14 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +35 -5
- package/dist/mcp-server.js.map +1 -1
- package/dist/model-transport.d.ts +7 -0
- package/dist/model-transport.d.ts.map +1 -1
- package/dist/model-transport.js +4 -1
- package/dist/model-transport.js.map +1 -1
- package/dist/packet-for-goal.d.ts +4 -2
- package/dist/packet-for-goal.d.ts.map +1 -1
- package/dist/packet-for-goal.js +4 -2
- package/dist/packet-for-goal.js.map +1 -1
- package/dist/repo-init.d.ts +36 -0
- package/dist/repo-init.d.ts.map +1 -0
- package/dist/repo-init.js +61 -0
- package/dist/repo-init.js.map +1 -0
- package/dist/repo-origin.d.ts +15 -0
- package/dist/repo-origin.d.ts.map +1 -0
- package/dist/repo-origin.js +28 -0
- package/dist/repo-origin.js.map +1 -0
- package/dist/repo-requests.d.ts +79 -0
- package/dist/repo-requests.d.ts.map +1 -0
- package/dist/repo-requests.js +180 -0
- package/dist/repo-requests.js.map +1 -0
- package/dist/repo-scan.d.ts +47 -0
- package/dist/repo-scan.d.ts.map +1 -0
- package/dist/repo-scan.js +84 -0
- package/dist/repo-scan.js.map +1 -0
- package/dist/run-cmd.d.ts +16 -1
- package/dist/run-cmd.d.ts.map +1 -1
- package/dist/run-cmd.js +68 -9
- package/dist/run-cmd.js.map +1 -1
- package/dist/serve-cmd.d.ts +17 -0
- package/dist/serve-cmd.d.ts.map +1 -1
- package/dist/serve-cmd.js +29 -2
- package/dist/serve-cmd.js.map +1 -1
- package/dist/serve-tasks.d.ts +17 -0
- package/dist/serve-tasks.d.ts.map +1 -0
- package/dist/serve-tasks.js +124 -0
- package/dist/serve-tasks.js.map +1 -0
- package/dist/serve.d.ts +36 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +89 -12
- package/dist/serve.js.map +1 -1
- package/dist/server-client.d.ts +37 -0
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +21 -0
- package/dist/server-client.js.map +1 -1
- package/dist/sibling-repos.d.ts +101 -0
- package/dist/sibling-repos.d.ts.map +1 -0
- package/dist/sibling-repos.js +160 -0
- package/dist/sibling-repos.js.map +1 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +3 -1
- package/dist/sync.js.map +1 -1
- package/dist/tool-bridge.d.ts +51 -1
- package/dist/tool-bridge.d.ts.map +1 -1
- package/dist/tool-bridge.js +62 -6
- package/dist/tool-bridge.js.map +1 -1
- package/dist/tool-protocol.d.ts +21 -3
- package/dist/tool-protocol.d.ts.map +1 -1
- package/dist/tool-protocol.js.map +1 -1
- package/dist/tool-worker.d.ts +13 -1
- package/dist/tool-worker.d.ts.map +1 -1
- package/dist/tool-worker.js +9 -2
- package/dist/tool-worker.js.map +1 -1
- package/package.json +2 -2
package/dist/.src-hash
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5d1be87f831ce39b9f1f2f1c05ba77ec38bea063b77a89727a0c1c240c8b7bdf
|
package/dist/bin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AA6wFA,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqE1D"}
|
package/dist/bin.js
CHANGED
|
@@ -26,7 +26,6 @@ const model_transport_1 = require("./model-transport");
|
|
|
26
26
|
const provider_state_1 = require("./provider-state");
|
|
27
27
|
const providers_1 = require("./providers");
|
|
28
28
|
const provider_preflight_1 = require("./provider-preflight");
|
|
29
|
-
const init_detect_1 = require("./init-detect");
|
|
30
29
|
const report_cmd_1 = require("./report-cmd");
|
|
31
30
|
const tool_call_record_1 = require("./tool-call-record");
|
|
32
31
|
const token_window_1 = require("./token-window");
|
|
@@ -46,6 +45,9 @@ const ledger_store_1 = require("./ledger-store");
|
|
|
46
45
|
const git_driver_1 = require("./git-driver");
|
|
47
46
|
const repos_cmd_1 = require("./repos-cmd");
|
|
48
47
|
const serve_cmd_1 = require("./serve-cmd");
|
|
48
|
+
const connect_1 = require("./connect");
|
|
49
|
+
const connect_node_1 = require("./connect-node");
|
|
50
|
+
const repo_init_1 = require("./repo-init");
|
|
49
51
|
const core_1 = require("@looply/core");
|
|
50
52
|
const sessions_cmd_1 = require("./sessions-cmd");
|
|
51
53
|
const session_observe_runtime_1 = require("./session-observe-runtime");
|
|
@@ -75,64 +77,67 @@ const integration_1 = require("./integration");
|
|
|
75
77
|
* "not implemented yet" is worse than one that does not exist, because it looks
|
|
76
78
|
* like a broken feature rather than an unbuilt one.
|
|
77
79
|
*/
|
|
78
|
-
const USAGE = `looply — an autonomous build loop you drive from your phone
|
|
79
|
-
|
|
80
|
-
usage:
|
|
81
|
-
looply
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
looply
|
|
85
|
-
looply
|
|
86
|
-
looply serve
|
|
87
|
-
looply serve
|
|
88
|
-
looply
|
|
89
|
-
looply
|
|
90
|
-
|
|
91
|
-
looply
|
|
92
|
-
looply
|
|
93
|
-
|
|
94
|
-
looply
|
|
95
|
-
looply
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
looply
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
looply source
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
looply source
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
looply
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
looply
|
|
125
|
-
looply
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
looply
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
looply
|
|
134
|
-
|
|
135
|
-
|
|
80
|
+
const USAGE = `looply — an autonomous build loop you drive from your phone
|
|
81
|
+
|
|
82
|
+
usage:
|
|
83
|
+
looply connect [--root <dir>]... [--yes] [--no-start]
|
|
84
|
+
once per machine: pair it (if needed), then set up and serve every git
|
|
85
|
+
repository under each root; new ones there, and clones you ask for, follow
|
|
86
|
+
looply pair [--server <url>] pair this machine with your phone
|
|
87
|
+
looply daemon [--once] [--yes] stay connected: presence, and ship the ledger
|
|
88
|
+
looply serve add [path] serve this repository (or <path>) from one machine-wide supervisor
|
|
89
|
+
looply serve remove <path> stop serving a repository
|
|
90
|
+
looply serve list the served repositories, and whether each still has .looply/config.yaml
|
|
91
|
+
looply serve run the supervisor: one daemon per served repository, restarted if it stops
|
|
92
|
+
looply serve install | uninstall start the supervisor at login (Windows); prints a service template elsewhere
|
|
93
|
+
looply init profile the repo and draft .looply/config.yaml
|
|
94
|
+
looply doctor [--config <path>] [--provider]
|
|
95
|
+
validate the config and run one full gate pass; --provider also asks the model to answer once
|
|
96
|
+
looply scan [--lens a,b] [--dry-run] read the code through several lenses and fill the queue
|
|
97
|
+
looply verify [--max N] check unverified items against the code, so a run can pick them
|
|
98
|
+
looply queue [--all] everything waiting, and why
|
|
99
|
+
looply integrate --init <ref> create looply/integration from a base you name
|
|
100
|
+
looply integrate --branch <name> [--goal <id>]
|
|
101
|
+
offer one finished branch to the integration queue:
|
|
102
|
+
fast-forward or nothing, checked at the commit that
|
|
103
|
+
would actually be published (needs run.integration)
|
|
104
|
+
looply runs [--reap] what this project is running; --reap retires proven-dead leftovers
|
|
105
|
+
looply runs --release <runId|slot-N|claim-lock>
|
|
106
|
+
clear a leftover a recycled pid makes look alive
|
|
107
|
+
looply source add <file> [--name <n>]
|
|
108
|
+
hand a Markdown (.md) or plain-text (.txt) document to
|
|
109
|
+
this project, verbatim, from the machine that holds it
|
|
110
|
+
looply source list what this project has been given
|
|
111
|
+
looply source show <id> one source: its statements, what each IS, where each came from,
|
|
112
|
+
and where each requirement stands against this repository
|
|
113
|
+
looply source reconcile <id> measure where each requirement stands against this repository
|
|
114
|
+
(HEAD's tree, by name — a place to look, never "implemented"), and record it
|
|
115
|
+
looply source coverage <id> which requirements no goal serves, which are served, and which a person
|
|
116
|
+
evidenced — a finished queue is not coverage
|
|
117
|
+
looply stop finish the round in flight, then stop
|
|
118
|
+
looply pause | looply resume hold between rounds, and let it go again
|
|
119
|
+
looply run [--hours N] [--dry-run] [--in <workspace> | --new-workspace]
|
|
120
|
+
start a run: pick, implement, gate, prove, keep or discard
|
|
121
|
+
--in runs it in another checkout of this repository, so two
|
|
122
|
+
runs can work at once without sharing a tree
|
|
123
|
+
--try-once-more spends a stopped goal's ONE retry (never
|
|
124
|
+
turns the brake off; the next failure stops it again)
|
|
125
|
+
looply status one-screen snapshot from .looply/state/status.json
|
|
126
|
+
looply report run report from the local ledger, alerts first
|
|
127
|
+
looply goal <id> one goal from this machine's records: the grant and the lane's answer,
|
|
128
|
+
compiles, proposals, the lane's attempts, each run's rounds — read-only
|
|
129
|
+
looply goals every mirrored goal, one line each, with its grant's standing
|
|
130
|
+
looply repos [--accept] [--published <repo>]
|
|
131
|
+
the other repositories this programme spans: where each one is,
|
|
132
|
+
and whether the revisions somebody accepted together still hold
|
|
133
|
+
looply evidence what this project has accumulated, and what the retention
|
|
134
|
+
policy would do with it. It deletes nothing.
|
|
135
|
+
looply sessions [--offer <file>] [--ack <id>]
|
|
136
|
+
sessions this machine did not start, asking to be managed;
|
|
137
|
+
observe-only — authorizing control is the server's to give
|
|
138
|
+
looply version
|
|
139
|
+
|
|
140
|
+
not built yet: item
|
|
136
141
|
`;
|
|
137
142
|
function loadConfig(path) {
|
|
138
143
|
const full = (0, path_1.resolve)(path);
|
|
@@ -159,16 +164,15 @@ async function init(argv) {
|
|
|
159
164
|
process.stderr.write(`init: ${target} already exists — move it aside first for a fresh draft\n`);
|
|
160
165
|
return 1;
|
|
161
166
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}, (0, path_1.basename)(process.cwd()));
|
|
167
|
+
// The same reading `connect` and the supervisor take of a repository they set up (`repo-init.ts`).
|
|
168
|
+
const profile = (0, repo_init_1.profileOf)(process.cwd(), (p) => {
|
|
169
|
+
try {
|
|
170
|
+
return (0, fs_1.readFileSync)(p, 'utf8');
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
172
176
|
// What detection found, before anything is asked — so the questions arrive
|
|
173
177
|
// with context rather than out of nowhere.
|
|
174
178
|
process.stdout.write((0, ui_1.box)((0, ui_1.fields)([
|
|
@@ -1501,7 +1505,7 @@ async function runs(argv) {
|
|
|
1501
1505
|
'claim lock',
|
|
1502
1506
|
`held by ${who} ${(0, ui_1.dim)(lock.liveness === 'dead' ? 'the next start will break it' : '`looply runs --release claim-lock` clears it')}`,
|
|
1503
1507
|
],
|
|
1504
|
-
]), { title: 'starting' })}
|
|
1508
|
+
]), { title: 'starting' })}
|
|
1505
1509
|
`);
|
|
1506
1510
|
}
|
|
1507
1511
|
if (slots.length > 0) {
|
|
@@ -1561,9 +1565,9 @@ async function runs(argv) {
|
|
|
1561
1565
|
];
|
|
1562
1566
|
}),
|
|
1563
1567
|
];
|
|
1564
|
-
process.stdout.write(`${(0, ui_1.box)((0, ui_1.fields)(rows), { title: 'workspaces' })}
|
|
1568
|
+
process.stdout.write(`${(0, ui_1.box)((0, ui_1.fields)(rows), { title: 'workspaces' })}
|
|
1565
1569
|
`);
|
|
1566
|
-
process.stdout.write(` ${(0, ui_1.dim)(`… = ${wsRootShown}`)}
|
|
1570
|
+
process.stdout.write(` ${(0, ui_1.dim)(`… = ${wsRootShown}`)}
|
|
1567
1571
|
`);
|
|
1568
1572
|
}
|
|
1569
1573
|
/**
|
|
@@ -1605,16 +1609,16 @@ async function runs(argv) {
|
|
|
1605
1609
|
if (lock !== null && lock.liveness !== 'dead') {
|
|
1606
1610
|
const how = lock.liveness === 'alive' ? 'answers' : 'cannot be judged';
|
|
1607
1611
|
process.stdout.write(` ${(0, ui_1.warn)('note')} — pid ${lock.pid ?? '?'} ${how}. If that is a start still deciding, ` +
|
|
1608
|
-
`clearing this lets another one decide alongside it.
|
|
1612
|
+
`clearing this lets another one decide alongside it.
|
|
1609
1613
|
`);
|
|
1610
1614
|
}
|
|
1611
1615
|
const cleared = registry.forgetClaimLock();
|
|
1612
1616
|
process.stdout.write(cleared
|
|
1613
|
-
? ` claim-lock: cleared — the next start decides for itself
|
|
1614
|
-
|
|
1617
|
+
? ` claim-lock: cleared — the next start decides for itself
|
|
1618
|
+
|
|
1615
1619
|
`
|
|
1616
|
-
: ` claim-lock: nothing to clear
|
|
1617
|
-
|
|
1620
|
+
: ` claim-lock: nothing to clear
|
|
1621
|
+
|
|
1618
1622
|
`);
|
|
1619
1623
|
return cleared ? 0 : 2;
|
|
1620
1624
|
}
|
|
@@ -1632,7 +1636,7 @@ async function runs(argv) {
|
|
|
1632
1636
|
const holder = slots.find((sl) => sl.slot === n)?.record ?? null;
|
|
1633
1637
|
if (holder !== null && (0, workspace_1.nodeProbe)(holder.pid) !== 'dead') {
|
|
1634
1638
|
process.stdout.write(` ${(0, ui_1.warn)('note')} — slot-${n} names ${holder.runId}, pid ${holder.pid}, which answers. ` +
|
|
1635
|
-
`Clearing it lets another execution start alongside it.
|
|
1639
|
+
`Clearing it lets another execution start alongside it.
|
|
1636
1640
|
`);
|
|
1637
1641
|
}
|
|
1638
1642
|
const cleared = registry.forgetSlot(n);
|
|
@@ -1770,7 +1774,7 @@ async function runs(argv) {
|
|
|
1770
1774
|
: ` ${(0, ui_1.dim)(`${orphans.length} orphaned, none in a checkout looply made — looply runs --release <runId>`)}\n`);
|
|
1771
1775
|
}
|
|
1772
1776
|
if (abandoned.length > 0) {
|
|
1773
|
-
process.stdout.write(` ${(0, ui_1.dim)(`${abandoned.length} checkout(s) nothing accounts for — \`looply runs --reap\` retires those it can`)}
|
|
1777
|
+
process.stdout.write(` ${(0, ui_1.dim)(`${abandoned.length} checkout(s) nothing accounts for — \`looply runs --reap\` retires those it can`)}
|
|
1774
1778
|
`);
|
|
1775
1779
|
}
|
|
1776
1780
|
/**
|
|
@@ -1807,9 +1811,9 @@ async function runs(argv) {
|
|
|
1807
1811
|
for (const w of abandoned) {
|
|
1808
1812
|
const out = await (0, workspace_1.reapAbandoned)(git, process.cwd(), w, undefined, undefined, undefined, carried);
|
|
1809
1813
|
process.stdout.write(out.reaped
|
|
1810
|
-
? ` ${(0, path_1.basename)(w)}: retired — no execution accounted for it
|
|
1814
|
+
? ` ${(0, path_1.basename)(w)}: retired — no execution accounted for it
|
|
1811
1815
|
`
|
|
1812
|
-
: ` ${(0, path_1.basename)(w)}: ${(0, ui_1.warn)('kept')} — ${out.because ?? 'unknown'}
|
|
1816
|
+
: ` ${(0, path_1.basename)(w)}: ${(0, ui_1.warn)('kept')} — ${out.because ?? 'unknown'}
|
|
1813
1817
|
`);
|
|
1814
1818
|
}
|
|
1815
1819
|
for (const e of entries) {
|
|
@@ -1947,12 +1951,12 @@ async function stop(argv, kind = 'stop') {
|
|
|
1947
1951
|
* the one place a person looks to check the brake reached everything.
|
|
1948
1952
|
*/
|
|
1949
1953
|
const told = kind === 'resume' ? 'were told to carry on' : `were told to ${kind}`;
|
|
1950
|
-
process.stdout.write(`
|
|
1951
|
-
${(0, ui_1.dim)(`${addressed.length} of ${running.length} running executions ${told}.`)}
|
|
1954
|
+
process.stdout.write(`
|
|
1955
|
+
${(0, ui_1.dim)(`${addressed.length} of ${running.length} running executions ${told}.`)}
|
|
1952
1956
|
`);
|
|
1953
1957
|
}
|
|
1954
1958
|
if (unreachable.length > 0) {
|
|
1955
|
-
process.stdout.write(` ${(0, ui_1.warn)('could not reach')} ${unreachable.join(', ')} — their state directories could not be written
|
|
1959
|
+
process.stdout.write(` ${(0, ui_1.warn)('could not reach')} ${unreachable.join(', ')} — their state directories could not be written
|
|
1956
1960
|
`);
|
|
1957
1961
|
}
|
|
1958
1962
|
process.stdout.write('\n ' + (0, queue_view_1.stopMessage)(live, kind) + '\n');
|
|
@@ -2479,7 +2483,7 @@ async function run(argv) {
|
|
|
2479
2483
|
// the daemon that spawned this cannot, because it spawns with
|
|
2480
2484
|
// `stdio: 'ignore'` on a detached child, so the words go nowhere. Both are
|
|
2481
2485
|
// told, by the channel each can actually hear.
|
|
2482
|
-
process.stderr.write(`${e.message}
|
|
2486
|
+
process.stderr.write(`${e.message}
|
|
2483
2487
|
`);
|
|
2484
2488
|
// Only when something asked. A hand-typed `looply run` has no request to
|
|
2485
2489
|
// answer, and writing a mark nobody will ever look up would make this file
|
|
@@ -2662,6 +2666,8 @@ async function main(argv) {
|
|
|
2662
2666
|
return daemon(rest);
|
|
2663
2667
|
case 'serve':
|
|
2664
2668
|
return (0, serve_cmd_1.serveCommand)(rest, (0, serve_cmd_1.nodeServeDeps)());
|
|
2669
|
+
case 'connect':
|
|
2670
|
+
return (0, connect_1.connectCommand)(rest, (0, connect_node_1.nodeConnectDeps)(DEFAULT_SERVER));
|
|
2665
2671
|
case 'scan':
|
|
2666
2672
|
return scan(rest);
|
|
2667
2673
|
case 'verify':
|