omp-conductor 0.8.0 → 0.9.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 +45 -21
- package/package.json +1 -1
- package/src/backups.ts +46 -0
- package/src/board.ts +254 -38
- package/src/brief-upgrade.ts +1 -30
- package/src/cli.ts +17 -5
- package/src/config.ts +13 -0
- package/src/daemon.ts +238 -123
- package/src/diff-flags.ts +35 -6
- package/src/fleet.ts +28 -2
- package/src/label-projection.ts +93 -0
- package/src/routing.ts +20 -0
- package/src/store.ts +254 -2
- package/src/tracker/github.ts +266 -18
- package/src/types.ts +75 -3
- package/src/unblock.ts +70 -19
- package/src/upgrade.ts +28 -4
package/src/cli.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { closeSync, openSync, readFileSync, readSync, statSync } from "node:fs";
|
|
9
9
|
import { userInfo } from "node:os";
|
|
10
10
|
import { dirname, join } from "node:path";
|
|
11
|
-
import { runBoard } from "./board.ts";
|
|
11
|
+
import { boardJson, boardSnapshotOnce, runBoard } from "./board.ts";
|
|
12
12
|
import {
|
|
13
13
|
applyRetrofit,
|
|
14
14
|
formatBriefReport,
|
|
@@ -92,7 +92,7 @@ usage:
|
|
|
92
92
|
omp-conductor stop
|
|
93
93
|
omp-conductor restart [--now] [--timeout SECONDS] [--port N] [--project NAME]
|
|
94
94
|
omp-conductor upgrade [--to VERSION] [--project NAME]
|
|
95
|
-
omp-conductor board [--project NAME]
|
|
95
|
+
omp-conductor board [--project NAME] [--json]
|
|
96
96
|
omp-conductor status [--project NAME]
|
|
97
97
|
omp-conductor ledger [--issue N] [--limit N] [--project NAME]
|
|
98
98
|
omp-conductor hold [--project NAME]
|
|
@@ -141,7 +141,9 @@ usage:
|
|
|
141
141
|
and active runs.
|
|
142
142
|
board open the live keyboard-driven fleet board. It renders queue holds,
|
|
143
143
|
every run lifecycle stage, recent merges, spend and health; Enter
|
|
144
|
-
follows a selected transcript without leaving the board.
|
|
144
|
+
follows a selected transcript without leaving the board. --json (or
|
|
145
|
+
a non-interactive stdin/stdout) prints a one-shot JSON snapshot of
|
|
146
|
+
the same lanes instead.
|
|
145
147
|
ledger every conductor-verb call and how the daemon decided it: the verb,
|
|
146
148
|
the arguments, allow or refuse, the named refusal reason, and the
|
|
147
149
|
resulting sha. Sessions cannot push, open, merge, label or release
|
|
@@ -650,9 +652,19 @@ try {
|
|
|
650
652
|
break;
|
|
651
653
|
}
|
|
652
654
|
|
|
653
|
-
case "board":
|
|
654
|
-
|
|
655
|
+
case "board": {
|
|
656
|
+
const project = flag(argv, "project");
|
|
657
|
+
// Headless one-shot mode: `--json` asks for it explicitly, and a
|
|
658
|
+
// non-interactive stdin or stdout (pipe, redirect, cron, script) cannot
|
|
659
|
+
// host the key-driven board anyway. The TTY throw inside runBoard stays
|
|
660
|
+
// as a backstop for direct callers.
|
|
661
|
+
if (argv.includes("--json") || !process.stdout.isTTY || !process.stdin.isTTY) {
|
|
662
|
+
process.stdout.write(`${boardJson(await boardSnapshotOnce(project))}\n`);
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
await runBoard(project);
|
|
655
666
|
break;
|
|
667
|
+
}
|
|
656
668
|
|
|
657
669
|
case "hold": {
|
|
658
670
|
const r = hold(flag(argv, "project"));
|
package/src/config.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
17
|
import { dirname, isAbsolute, join } from "node:path";
|
|
18
|
+
import { backupTimestamp, copyToUniqueBackup } from "./backups.ts";
|
|
18
19
|
import {
|
|
19
20
|
AUTHORITY_HOLDERS,
|
|
20
21
|
BASE_FRESHNESS,
|
|
@@ -103,6 +104,11 @@ export function stateDir(): string {
|
|
|
103
104
|
return dirname(configPath());
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
/** State-root directory for durable copies of every pre-write config.json. */
|
|
108
|
+
export function configBackupDir(): string {
|
|
109
|
+
return join(stateDir(), "backups", "config");
|
|
110
|
+
}
|
|
111
|
+
|
|
106
112
|
/**
|
|
107
113
|
* Where per-run worktrees and bare mirrors live when a project names neither.
|
|
108
114
|
*
|
|
@@ -188,6 +194,13 @@ export function writeConfigRaw(text: string): void {
|
|
|
188
194
|
if (created !== undefined) chmodSync(dir, 0o700);
|
|
189
195
|
|
|
190
196
|
const target = configPath();
|
|
197
|
+
// A durable pre-write copy under state keeps the previous bytes recoverable
|
|
198
|
+
// even when the process dies between this moment and the rename, or when a
|
|
199
|
+
// later caller discovers it needs the old file back. Retention is unbounded,
|
|
200
|
+
// matching the brief backups.
|
|
201
|
+
if (existsSync(target)) {
|
|
202
|
+
copyToUniqueBackup(target, configBackupDir(), `config.json.bak-${backupTimestamp()}`);
|
|
203
|
+
}
|
|
191
204
|
const tmp = join(dir, `.config.json.${process.pid.toString(36)}.${Date.now().toString(36)}.tmp`);
|
|
192
205
|
try {
|
|
193
206
|
writeFileSync(tmp, text, { mode: 0o600 });
|