omp-conductor 0.5.1 → 0.5.2
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 +2 -1
- package/package.json +1 -1
- package/src/failure-class.ts +49 -17
- package/src/store.ts +22 -8
package/README.md
CHANGED
|
@@ -167,7 +167,8 @@ Also required on the host:
|
|
|
167
167
|
account is invisible to the service. A unit running `User=fleet` cannot see
|
|
168
168
|
`root`'s login, and workers then die at turn 0 with `No model selected`. Such a
|
|
169
169
|
run is classified `env-start-failure` and charges **neither** the failure budget
|
|
170
|
-
nor a continuation — an environment fault is not a failed implementation
|
|
170
|
+
nor a continuation — an environment fault is not a failed implementation, and a
|
|
171
|
+
run that recorded no turn, no commit and no error did not attempt anything — but
|
|
171
172
|
nothing dispatches successfully until the credential is reachable.
|
|
172
173
|
- `gh`, already authenticated: every tracker operation shells out to it, so the
|
|
173
174
|
daemon never handles a GitHub token itself.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omp-conductor",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A 24/7 dispatcher that takes ready GitHub issues to green, mergeable PRs using omp coding sessions, with tiered escalation first to an orchestrator session and then to a human.",
|
package/src/failure-class.ts
CHANGED
|
@@ -65,10 +65,11 @@ function normalise(state: string): string {
|
|
|
65
65
|
/**
|
|
66
66
|
* Harness start failures, matched on the text it prints.
|
|
67
67
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
68
|
+
* A small closed list rather than "any error at turn 0": a run that ended at
|
|
69
|
+
* turn 0 with an error nobody has named is exactly what `unknown` is for, and
|
|
70
|
+
* declaring that an environment fault would waive an attempt that may have been
|
|
71
|
+
* genuinely spent. A mirror fetch that failed is not a session that never
|
|
72
|
+
* started.
|
|
72
73
|
*/
|
|
73
74
|
const START_FAILURE_SIGNATURES = [
|
|
74
75
|
"no model selected",
|
|
@@ -90,6 +91,42 @@ export function startFailure(lastError: string | undefined): string | undefined
|
|
|
90
91
|
return hit === undefined ? undefined : lastError.split("\n")[0]?.trim();
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Evidence that this run never started, or `undefined` when something did happen.
|
|
96
|
+
*
|
|
97
|
+
* Two shapes, and the second is the one the reference fleet actually produced.
|
|
98
|
+
*
|
|
99
|
+
* 1. Turn zero with a recognised harness start error — the session said why.
|
|
100
|
+
* 2. Turn zero, **no artifacts and no error text at all**. The row records
|
|
101
|
+
* nothing: no turn, no head, no salvage, not even a message. On the reference
|
|
102
|
+
* fleet every worker died at turn 0 with `No model selected`, and that string
|
|
103
|
+
* went into the tier-1 escalation rather than into `lastError` — so the rows
|
|
104
|
+
* for issues 373, 359, 343 and 319 carry no error whatsoever and were logged
|
|
105
|
+
* `unknown`, each charging an implementation attempt (#152).
|
|
106
|
+
*
|
|
107
|
+
* Shape 2 is a deliberate judgement, not a loosening. There is no evidence an
|
|
108
|
+
* attempt was spent, so charging one is charging for a run whose only trace is
|
|
109
|
+
* that it existed; and the two ways of being wrong are not symmetric — being
|
|
110
|
+
* generous grants an issue one more attempt a human will see, while being strict
|
|
111
|
+
* leaves it permanently undispatchable for a fault that was never in its code.
|
|
112
|
+
* A turn-0 run carrying an *unrecognised* error still reads `unknown`, because
|
|
113
|
+
* there the row does say something happened.
|
|
114
|
+
*
|
|
115
|
+
* Shared with the store's one-time repair so history and future agree.
|
|
116
|
+
*/
|
|
117
|
+
export function neverStarted(
|
|
118
|
+
run: Pick<RunRecord, "turns" | "lastError" | "prUrl" | "headSha" | "salvageSha">,
|
|
119
|
+
): string | undefined {
|
|
120
|
+
if (run.turns !== 0) return undefined;
|
|
121
|
+
const detail = startFailure(run.lastError);
|
|
122
|
+
if (detail !== undefined) return `the session never started: ${detail}`;
|
|
123
|
+
const produced = run.prUrl !== undefined || run.headSha !== undefined || run.salvageSha !== undefined;
|
|
124
|
+
if (!produced && run.lastError === undefined) {
|
|
125
|
+
return "the session never started: no turns, no commit and no error were recorded";
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
93
130
|
export function classifyRun(run: RunRecord, facts: ClassifyFacts): Classification {
|
|
94
131
|
const hasArtifacts = run.prUrl !== undefined || run.headSha !== undefined || run.salvageSha !== undefined;
|
|
95
132
|
|
|
@@ -113,19 +150,14 @@ export function classifyRun(run: RunRecord, facts: ClassifyFacts): Classificatio
|
|
|
113
150
|
};
|
|
114
151
|
}
|
|
115
152
|
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
cls: "env-start-failure",
|
|
126
|
-
recovery: "escalate",
|
|
127
|
-
evidence: `the session never started: ${detail}`,
|
|
128
|
-
};
|
|
153
|
+
// A run that never started is the most classifiable failure there is, and the
|
|
154
|
+
// least deserving of an implementation attempt: the session did not get as far
|
|
155
|
+
// as reading the issue. See {@link neverStarted} for the two shapes and why the
|
|
156
|
+
// second one counts.
|
|
157
|
+
if (run.state === "failed" || run.state === "killed") {
|
|
158
|
+
const evidence = neverStarted(run);
|
|
159
|
+
if (evidence !== undefined) {
|
|
160
|
+
return { cls: "env-start-failure", recovery: "escalate", evidence };
|
|
129
161
|
}
|
|
130
162
|
}
|
|
131
163
|
|
package/src/store.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { dirname, join } from "node:path";
|
|
|
15
15
|
|
|
16
16
|
import { stateDir } from "./config.ts";
|
|
17
17
|
import { DECISION_TTL_MS, DEFAULT_CAPS } from "./types.ts";
|
|
18
|
-
import {
|
|
18
|
+
import { neverStarted } from "./failure-class.ts";
|
|
19
19
|
import type {
|
|
20
20
|
DecisionDraft,
|
|
21
21
|
FailureClass,
|
|
@@ -693,18 +693,32 @@ export function openStore(dbPath: string): Store {
|
|
|
693
693
|
// charged, and an issue sitting at its cap for a fault that was never in its
|
|
694
694
|
// code stays undispatchable forever.
|
|
695
695
|
//
|
|
696
|
-
// Narrow by construction
|
|
697
|
-
//
|
|
696
|
+
// Narrow by construction, and narrow through the CLASSIFIER's own predicate
|
|
697
|
+
// rather than a second copy of the rule: {@link neverStarted}. A class of
|
|
698
698
|
// exactly `unknown` — a row a human or a later release classified as anything
|
|
699
|
-
// else is left alone
|
|
700
|
-
//
|
|
699
|
+
// else is left alone — plus zero turns and either a recognised start error or
|
|
700
|
+
// nothing recorded at all. A turn-0 row carrying an unrecognised error (a
|
|
701
|
+
// failed mirror fetch, say) is untouched. Idempotent for free: afterwards these
|
|
702
|
+
// rows read `env-start-failure`, which the WHERE no longer matches.
|
|
701
703
|
const misread = db
|
|
702
704
|
.query<
|
|
703
|
-
{ id: string; lastError: string | null },
|
|
705
|
+
{ id: string; lastError: string | null; prUrl: string | null; headSha: string | null; salvageSha: string | null },
|
|
704
706
|
[]
|
|
705
|
-
>(
|
|
707
|
+
>(
|
|
708
|
+
`SELECT id, lastError, prUrl, headSha, salvageSha FROM runs
|
|
709
|
+
WHERE failureClass = 'unknown' AND turns = 0`,
|
|
710
|
+
)
|
|
706
711
|
.all()
|
|
707
|
-
.filter(
|
|
712
|
+
.filter(
|
|
713
|
+
(row) =>
|
|
714
|
+
neverStarted({
|
|
715
|
+
turns: 0,
|
|
716
|
+
...(row.lastError === null ? {} : { lastError: row.lastError }),
|
|
717
|
+
...(row.prUrl === null ? {} : { prUrl: row.prUrl }),
|
|
718
|
+
...(row.headSha === null ? {} : { headSha: row.headSha }),
|
|
719
|
+
...(row.salvageSha === null ? {} : { salvageSha: row.salvageSha }),
|
|
720
|
+
}) !== undefined,
|
|
721
|
+
);
|
|
708
722
|
if (misread.length > 0) {
|
|
709
723
|
const reclassify = db.query<unknown, [string]>(
|
|
710
724
|
`UPDATE runs SET failureClass = 'env-start-failure' WHERE id = ?`,
|