omp-conductor 0.3.1 → 0.3.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 +24 -17
- package/package.json +1 -1
- package/src/daemon.ts +15 -3
package/README.md
CHANGED
|
@@ -769,23 +769,30 @@ prompt was never consumed, and the extension:
|
|
|
769
769
|
Both escapes deliberately leave the session, because a loop that cannot drain
|
|
770
770
|
its queue cannot report on itself — that is the whole failure.
|
|
771
771
|
|
|
772
|
-
**
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
772
|
+
**The daemon reads it.** A marker nobody consumes is an artifact, not an alert,
|
|
773
|
+
so the dispatch daemon checks it on its own five-minute tick — and *before* its
|
|
774
|
+
pause check. The orchestrator is a different process and can be wedged while
|
|
775
|
+
the fleet is deliberately paused, which is precisely the state the dogfood
|
|
776
|
+
fleet was in when this happened. One tier-2 page per stall, keyed on the
|
|
777
|
+
marker's own timestamp so a second wedge the same day is not swallowed as a
|
|
778
|
+
repeat, re-armed when the marker clears, and latched only once the page is
|
|
779
|
+
confirmed delivered — an escalation channel that fails on the one tick that
|
|
780
|
+
noticed must not buy permanent silence.
|
|
781
|
+
|
|
782
|
+
It restarts nothing. A wedge lands mid-turn, and no other process can tell a
|
|
783
|
+
half-applied edit from an idle loop; the operator attaches, looks, and decides.
|
|
784
|
+
|
|
785
|
+
**herdr-conductor deliberately does not read it**, though its liveness test
|
|
786
|
+
(agent listed AND a non-shell foreground process) passes straight through a
|
|
787
|
+
wedge. That plugin only runs on `startup`, `pane.exited` and
|
|
788
|
+
`pane.agent_detected`, and a session that stays alive and stops working emits
|
|
789
|
+
none of them — so the check could never fire during the wedge itself. What it
|
|
790
|
+
*would* catch is the recovery afterwards: the marker survives a restart until
|
|
791
|
+
the new session consumes a tick, so every operator SIGTERM-and-resume would
|
|
792
|
+
page about the healthy session they just fixed. Telling those apart needs the
|
|
793
|
+
process start time against the marker's, and herdr's `pane process-info`
|
|
794
|
+
reports pids, not start times. The daemon gives up at most one tick of
|
|
795
|
+
coverage and never cries wolf.
|
|
789
796
|
|
|
790
797
|
The first tick that actually sends clears the counter and deletes the marker,
|
|
791
798
|
and it deletes one it did not write: recovery normally arrives as a fresh
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omp-conductor",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.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/daemon.ts
CHANGED
|
@@ -151,10 +151,13 @@ async function watchOrchestrator(d: Deps): Promise<void> {
|
|
|
151
151
|
tier: 2,
|
|
152
152
|
project: d.project.name,
|
|
153
153
|
issue: NO_ISSUE,
|
|
154
|
-
//
|
|
155
|
-
//
|
|
154
|
+
// Keyed on the marker's own timestamp, not the date. The dedup ledger keys
|
|
155
|
+
// on this summary, and two wedges in one day is not a hypothetical — the
|
|
156
|
+
// failure mode is a session that gets stuck, gets restarted, and gets stuck
|
|
157
|
+
// again on the same cause an hour later. A day-keyed summary would report
|
|
158
|
+
// the first and silently swallow every one after it.
|
|
156
159
|
summary:
|
|
157
|
-
`Orchestrator session wedged
|
|
160
|
+
`Orchestrator session wedged (${verdict.since ?? `marker at ${marker}`}) — ` +
|
|
158
161
|
`it has stopped reading its queue (${d.project.name})`,
|
|
159
162
|
detail: [
|
|
160
163
|
verdict.since ?? "Marker present with no readable timestamp.",
|
|
@@ -731,6 +734,15 @@ async function tick(d: Deps): Promise<void> {
|
|
|
731
734
|
// attributable. A legitimate deploy never trips it, because installing a new
|
|
732
735
|
// build and restarting the unit re-records the baseline from the new files;
|
|
733
736
|
// only an edit *underneath* a live daemon diverges from it.
|
|
737
|
+
//
|
|
738
|
+
// Below the pause gate on purpose, unlike the stall watch above. The property
|
|
739
|
+
// being defended is that no work is dispatched under a package the operator
|
|
740
|
+
// did not install — and a paused fleet dispatches nothing, so nothing needs
|
|
741
|
+
// attributing yet. Tampering during a pause is not missed, only deferred: the
|
|
742
|
+
// baseline is boot's, so the first tick after `resume` compares against it and
|
|
743
|
+
// pauses again before claiming anything. Checking above the gate instead would
|
|
744
|
+
// page on every legitimate build an operator deploys into a parked fleet,
|
|
745
|
+
// which is exactly when they deploy them.
|
|
734
746
|
const integrity = checkIntegrity(d.integrity, packageManifest());
|
|
735
747
|
if (integrity.pause) {
|
|
736
748
|
const shown = integrity.diff.slice(0, INTEGRITY_SAMPLE);
|