omp-conductor 0.3.24 → 0.4.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/README.md +775 -49
- package/package.json +1 -1
- package/src/approval-surface.ts +36 -1
- package/src/board.ts +30 -6
- package/src/briefs/orchestrator.md +114 -20
- package/src/briefs/policy.md +48 -27
- package/src/briefs/worker.md +82 -31
- package/src/cli.ts +164 -4
- package/src/config.ts +669 -16
- package/src/confinement.ts +506 -25
- package/src/credentials.ts +2029 -0
- package/src/daemon.ts +1213 -78
- package/src/diff-flags.ts +696 -0
- package/src/escalate.ts +136 -9
- package/src/fleet.ts +80 -4
- package/src/omp.ts +471 -15
- package/src/orchestrator-tick.ts +98 -25
- package/src/orchestrator.ts +32 -5
- package/src/plugin.ts +267 -15
- package/src/release-policy.ts +191 -29
- package/src/reports.ts +440 -0
- package/src/session-host.ts +307 -0
- package/src/setup-host.ts +19 -1
- package/src/setup.ts +207 -18
- package/src/store.ts +555 -3
- package/src/tracker/github.ts +45 -0
- package/src/types.ts +863 -10
- package/src/unblock.ts +53 -3
- package/src/usage.ts +726 -0
- package/src/verbs/actions.ts +142 -0
- package/src/verbs/client.ts +207 -0
- package/src/verbs/ledger.ts +77 -0
- package/src/verbs/protocol.ts +465 -0
- package/src/verbs/server.ts +1098 -0
- package/src/verbs/socket.ts +446 -0
- package/src/worker.ts +36 -7
- package/src/worktree.ts +227 -120
- package/systemd/omp-conductor.service.example +96 -8
package/src/unblock.ts
CHANGED
|
@@ -40,6 +40,11 @@ export interface UnblockOutcome {
|
|
|
40
40
|
continuationsUsed: number;
|
|
41
41
|
/** Newest attempt, when the store has one for this issue at all. */
|
|
42
42
|
latest?: RunRecord;
|
|
43
|
+
/** Set when nothing was cleared because the newest attempt's work exists
|
|
44
|
+
* only in its worktree. Carries the salvage failure verbatim. */
|
|
45
|
+
refused?: string;
|
|
46
|
+
/** Set when `--force` recorded an operator's acceptance of that loss. */
|
|
47
|
+
forced?: true;
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
/**
|
|
@@ -81,11 +86,35 @@ export async function unblockIssue(
|
|
|
81
86
|
tracker: Tracker,
|
|
82
87
|
store: Store,
|
|
83
88
|
issue: number,
|
|
89
|
+
opts: { force?: boolean } = {},
|
|
84
90
|
): Promise<UnblockOutcome> {
|
|
85
91
|
// Read before any label is touched: terminality is the whole of the argument
|
|
86
92
|
// for clearing in-progress, so the row that carries it decides the set.
|
|
87
93
|
const latest = store.latestRun(project.name, issue);
|
|
88
94
|
const terminal = latest !== undefined && !LIVE_STATES.includes(latest.state);
|
|
95
|
+
const counts = {
|
|
96
|
+
attemptsUsed: store.attemptsFor(project.name, issue),
|
|
97
|
+
failuresUsed: store.failuresFor(project.name, issue),
|
|
98
|
+
continuationsUsed: store.continuationsFor(project.name, issue),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// The one case where this verb refuses. Clearing the labels here re-queues an
|
|
102
|
+
// issue whose next claim starts by force-removing the worktree that holds the
|
|
103
|
+
// only copy of the last attempt's work (#118) — and unlike every other state
|
|
104
|
+
// this function reasons about, that is unrecoverable. `--force` is the way
|
|
105
|
+
// through, and it is deliberately a separate keystroke rather than a prompt
|
|
106
|
+
// the operator can wave past: it records, on the row, that a human accepted
|
|
107
|
+
// the loss or recovered the tree themselves. Narrowed to the row rather than
|
|
108
|
+
// a boolean so the reason printed and the acknowledgement written are
|
|
109
|
+
// provably about the same run.
|
|
110
|
+
const held =
|
|
111
|
+
latest !== undefined && latest.salvageError !== undefined && latest.salvageAckAt === undefined
|
|
112
|
+
? latest
|
|
113
|
+
: undefined;
|
|
114
|
+
if (held !== undefined && opts.force !== true) {
|
|
115
|
+
return { cleared: [], ...counts, latest: held, refused: held.salvageError };
|
|
116
|
+
}
|
|
117
|
+
if (held !== undefined) store.updateRun(held.id, { salvageAckAt: Date.now() });
|
|
89
118
|
|
|
90
119
|
const cleared: string[] = [];
|
|
91
120
|
for (const label of new Set([
|
|
@@ -99,10 +128,9 @@ export async function unblockIssue(
|
|
|
99
128
|
|
|
100
129
|
return {
|
|
101
130
|
cleared,
|
|
102
|
-
|
|
103
|
-
failuresUsed: store.failuresFor(project.name, issue),
|
|
104
|
-
continuationsUsed: store.continuationsFor(project.name, issue),
|
|
131
|
+
...counts,
|
|
105
132
|
...(latest === undefined ? {} : { latest }),
|
|
133
|
+
...(held === undefined ? {} : { forced: true as const }),
|
|
106
134
|
};
|
|
107
135
|
}
|
|
108
136
|
|
|
@@ -116,6 +144,11 @@ export async function unblockIssue(
|
|
|
116
144
|
* run row at all, where that label may still be sitting there unread. #18 was
|
|
117
145
|
* filed against this function saying `next tick eligible again` in a case where
|
|
118
146
|
* it was not, so the wording is a contract rather than prose.
|
|
147
|
+
*
|
|
148
|
+
* A refusal is the loudest thing this verb prints, and it prints instead of
|
|
149
|
+
* everything else: the operator asked to re-queue an issue whose only copy of
|
|
150
|
+
* real work is a directory, and the next line they read has to be the one that
|
|
151
|
+
* stops them typing the same command again with `--force` on the end.
|
|
119
152
|
*/
|
|
120
153
|
export function formatUnblock(
|
|
121
154
|
issue: number,
|
|
@@ -124,7 +157,24 @@ export function formatUnblock(
|
|
|
124
157
|
caps: Caps,
|
|
125
158
|
): string {
|
|
126
159
|
const latest = o.latest;
|
|
160
|
+
|
|
161
|
+
if (o.refused !== undefined) {
|
|
162
|
+
return [
|
|
163
|
+
`#${issue}: REFUSED — nothing was cleared`,
|
|
164
|
+
` reason attempt ${latest?.attempt ?? "?"} could not commit its work: ${o.refused}`,
|
|
165
|
+
` only copy ${latest?.worktree === undefined || latest.worktree === "" ? "(worktree path not recorded)" : latest.worktree}`,
|
|
166
|
+
" why re-claiming this issue removes that worktree, and the work is not on any ref",
|
|
167
|
+
` recover inspect the tree and commit or copy what matters, then re-run with --force`,
|
|
168
|
+
].join("\n");
|
|
169
|
+
}
|
|
170
|
+
|
|
127
171
|
const lines = [`#${issue}: cleared ${o.cleared.join(", ")}`];
|
|
172
|
+
if (o.forced === true) {
|
|
173
|
+
lines.push(
|
|
174
|
+
` forced the unsalvaged worktree was accepted as lost or already recovered by hand — ` +
|
|
175
|
+
"the next claim removes it",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
128
178
|
|
|
129
179
|
if (latest === undefined) {
|
|
130
180
|
lines.push(" runs none recorded — the terminal labels were cleared anyway; eligibility is read off the tracker");
|