omp-conductor 0.15.10 → 0.15.12
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 +273 -2544
- package/REFERENCE.md +2680 -0
- package/package.json +3 -2
- package/schema/config.schema.json +11 -23
- package/src/arm-challenge.ts +112 -0
- package/src/ask.ts +434 -0
- package/src/board.ts +81 -15
- package/src/brief-upgrade.ts +114 -8
- package/src/briefs/orchestrator.md +113 -34
- package/src/briefs/policy.md +33 -8
- package/src/briefs/worker.md +18 -9
- package/src/chain-check.ts +1 -1
- package/src/check-trailing-newlines.ts +82 -0
- package/src/cli.ts +225 -1406
- package/src/commands/arm.ts +21 -0
- package/src/commands/board.ts +23 -0
- package/src/commands/brief-upgrade.ts +186 -0
- package/src/commands/context.ts +150 -0
- package/src/commands/daemon.ts +71 -0
- package/src/commands/dashboard.ts +74 -0
- package/src/commands/decision.ts +103 -0
- package/src/commands/disarm.ts +21 -0
- package/src/commands/doctor.ts +100 -0
- package/src/commands/event.ts +62 -0
- package/src/commands/extend.ts +64 -0
- package/src/commands/friction.ts +56 -0
- package/src/commands/help.ts +9 -0
- package/src/commands/hold.ts +26 -0
- package/src/commands/intake.ts +155 -0
- package/src/commands/ledger.ts +69 -0
- package/src/commands/message.ts +96 -0
- package/src/commands/report.ts +206 -0
- package/src/commands/restart.ts +76 -0
- package/src/commands/resume.ts +58 -0
- package/src/commands/setup.ts +143 -0
- package/src/commands/start.ts +23 -0
- package/src/commands/stats.ts +131 -0
- package/src/commands/status.ts +48 -0
- package/src/commands/stop.ts +51 -0
- package/src/commands/tail.ts +109 -0
- package/src/commands/unblock.ts +39 -0
- package/src/commands/upgrade-install.ts +31 -0
- package/src/commands/upgrade-rollback.ts +32 -0
- package/src/commands/upgrade.ts +25 -0
- package/src/commands/verb.ts +83 -0
- package/src/commands/version.ts +30 -0
- package/src/commands/worker.ts +100 -0
- package/src/config-schema.ts +47 -1
- package/src/config.ts +45 -4
- package/src/daemon.ts +972 -101
- package/src/dashboard/app.js +459 -0
- package/src/dashboard/index.html +61 -0
- package/src/dashboard/server.ts +481 -0
- package/src/dashboard/style.css +348 -0
- package/src/decisions.ts +39 -14
- package/src/diff-flags.ts +131 -241
- package/src/doctor.ts +932 -0
- package/src/escalate.ts +2 -2
- package/src/failure-class.ts +66 -3
- package/src/fleet.ts +58 -1
- package/src/gitops.ts +157 -0
- package/src/graph-health.ts +1 -1
- package/src/label-projection.ts +1 -1
- package/src/lifecycle.ts +198 -2
- package/src/model-fallback.ts +177 -0
- package/src/notices.ts +9 -0
- package/src/omp.ts +93 -13
- package/src/orchestrator-tick.ts +414 -20
- package/src/orchestrator.ts +4 -4
- package/src/privileged.ts +10 -0
- package/src/release-policy.ts +342 -30
- package/src/reports.ts +19 -5
- package/src/session-host.ts +11 -5
- package/src/setup-host.ts +663 -25
- package/src/setup-install.ts +292 -28
- package/src/setup-wizard.ts +255 -74
- package/src/setup.ts +156 -35
- package/src/stats.ts +331 -0
- package/src/store.ts +219 -22
- package/src/tracker/github.ts +74 -4
- package/src/types.ts +215 -31
- package/src/unblock.ts +55 -11
- package/src/upgrade-journal.ts +220 -0
- package/src/upgrade-verify.ts +506 -0
- package/src/upgrade.ts +385 -58
- package/src/verbs/actions.ts +73 -1
- package/src/verbs/protocol.ts +29 -4
- package/src/verbs/server.ts +183 -20
- package/src/worker.ts +3 -3
- package/systemd/omp-conductor-recover.sh +433 -0
- package/systemd/omp-conductor.service.example +14 -3
- package/systemd/recover-unit-test.sh +428 -0
package/src/config.ts
CHANGED
|
@@ -355,8 +355,11 @@ export function findProject(c: ConductorConfig, name?: string): ProjectConfig {
|
|
|
355
355
|
if (name === undefined) {
|
|
356
356
|
const only = c.projects[0];
|
|
357
357
|
if (c.projects.length !== 1 || only === undefined) {
|
|
358
|
+
// #514: every operator hitting this has to guess the spelling of the
|
|
359
|
+
// flag that names a project — say it outright. Doctor's project finding
|
|
360
|
+
// quotes this text, so keep the "name one explicitly" phrase.
|
|
358
361
|
throw new Error(
|
|
359
|
-
`Ambiguous project: config has ${c.projects.length} projects (${names.join(", ") || "none"}) — name one explicitly.`,
|
|
362
|
+
`Ambiguous project: config has ${c.projects.length} projects (${names.join(", ") || "none"}) — name one explicitly with --project NAME.`,
|
|
360
363
|
);
|
|
361
364
|
}
|
|
362
365
|
return only;
|
|
@@ -558,13 +561,17 @@ function checkDigest(d: Raw, label: string, problems: string[]): void {
|
|
|
558
561
|
function checkAuthority(a: Raw, label: string, problems: string[]): void {
|
|
559
562
|
const merge = a["merge"];
|
|
560
563
|
const release = a["release"];
|
|
564
|
+
const promotion = a["promotion"];
|
|
561
565
|
if (merge !== undefined && typeof merge === "string" && !(AUTHORITY_HOLDERS as readonly string[]).includes(merge)) {
|
|
562
566
|
problems.push(`${label}: authority.merge must be ${AUTHORITY_HOLDER_LIST}, found ${JSON.stringify(merge)}`);
|
|
563
567
|
}
|
|
564
568
|
if (release !== undefined && typeof release === "string" && !(AUTHORITY_HOLDERS as readonly string[]).includes(release)) {
|
|
565
569
|
problems.push(`${label}: authority.release must be ${AUTHORITY_HOLDER_LIST}, found ${JSON.stringify(release)}`);
|
|
566
570
|
}
|
|
567
|
-
|
|
571
|
+
if (promotion !== undefined && typeof promotion === "string" && !(AUTHORITY_HOLDERS as readonly string[]).includes(promotion)) {
|
|
572
|
+
problems.push(`${label}: authority.promotion must be ${AUTHORITY_HOLDER_LIST}, found ${JSON.stringify(promotion)}`);
|
|
573
|
+
}
|
|
574
|
+
const unknown = Object.keys(a).filter((k) => k !== "merge" && k !== "release" && k !== "promotion");
|
|
568
575
|
if (unknown.length > 0) problems.push(`${label}: authority has unknown key(s): ${unknown.join(", ")}`);
|
|
569
576
|
}
|
|
570
577
|
|
|
@@ -817,7 +824,7 @@ function clauseFor(rel: readonly PropertyKey[], issue: {
|
|
|
817
824
|
}
|
|
818
825
|
if (rel.length === 1 && relStr === "escalation") return `escalation must be an object`;
|
|
819
826
|
if (rel.length === 1 && relStr === "authority") {
|
|
820
|
-
return `authority must be an object with "merge" and "
|
|
827
|
+
return `authority must be an object with "merge", "release" and "promotion" of ${AUTHORITY_HOLDER_LIST}`;
|
|
821
828
|
}
|
|
822
829
|
if (rel.length === 1 && relStr === "policy") {
|
|
823
830
|
return `policy must be an object with "merge" and "release" sections`;
|
|
@@ -909,7 +916,7 @@ function clauseFor(rel: readonly PropertyKey[], issue: {
|
|
|
909
916
|
}
|
|
910
917
|
if (pathStr === "reporting.digest.cadence") return `${pathStr} must be ${DIGEST_CADENCE_LIST}, found ${found()}`;
|
|
911
918
|
if (pathStr === "escalation.orchestrator") return `${pathStr} must be ${ORCHESTRATOR_MODE_LIST}, found ${found()}`;
|
|
912
|
-
if (pathStr === "authority.merge" || pathStr === "authority.release") {
|
|
919
|
+
if (pathStr === "authority.merge" || pathStr === "authority.release" || pathStr === "authority.promotion") {
|
|
913
920
|
return `${pathStr} must be ${AUTHORITY_HOLDER_LIST}, found ${found()}`;
|
|
914
921
|
}
|
|
915
922
|
if (pathStr === "policy.merge.baseFreshness") return `${pathStr} must be ${BASE_FRESHNESS_LIST}, found ${found()}`;
|
|
@@ -1076,6 +1083,34 @@ function finalizeProject(
|
|
|
1076
1083
|
const workerModel =
|
|
1077
1084
|
typeof rawWorkerModel === "string" && rawWorkerModel.trim() !== "" ? rawWorkerModel : undefined;
|
|
1078
1085
|
|
|
1086
|
+
// The failover chain is a hint like workerModel, not a ceiling: an unusable
|
|
1087
|
+
// entry or a malformed threshold is dropped rather than failing the load,
|
|
1088
|
+
// and absent/empty `modelFallbacks` keeps today's dispatch byte for byte.
|
|
1089
|
+
const rawFallbacks = p["modelFallbacks"];
|
|
1090
|
+
const modelFallbacks = Array.isArray(rawFallbacks)
|
|
1091
|
+
? rawFallbacks
|
|
1092
|
+
.filter((entry): entry is string => typeof entry === "string")
|
|
1093
|
+
.map((entry) => entry.trim())
|
|
1094
|
+
.filter((entry) => entry !== "")
|
|
1095
|
+
: [];
|
|
1096
|
+
const rawThreshold = p["modelFallbackThreshold"];
|
|
1097
|
+
const modelFallbackThreshold =
|
|
1098
|
+
typeof rawThreshold === "number" && Number.isInteger(rawThreshold) && rawThreshold >= 1
|
|
1099
|
+
? rawThreshold
|
|
1100
|
+
: undefined;
|
|
1101
|
+
|
|
1102
|
+
// Marked critical-base/safety markers (commit SHAs or refs). A continuation
|
|
1103
|
+
// branch must contain every one before the dispatcher may reattach it;
|
|
1104
|
+
// unusable entries are dropped like `modelFallbacks` and an absent or empty
|
|
1105
|
+
// list keeps today's behaviour byte for byte.
|
|
1106
|
+
const rawCriticalBase = p["criticalBase"];
|
|
1107
|
+
const criticalBase = Array.isArray(rawCriticalBase)
|
|
1108
|
+
? rawCriticalBase
|
|
1109
|
+
.filter((entry): entry is string => typeof entry === "string")
|
|
1110
|
+
.map((entry) => entry.trim())
|
|
1111
|
+
.filter((entry) => entry !== "")
|
|
1112
|
+
: [];
|
|
1113
|
+
|
|
1079
1114
|
if (problems.length > before) return undefined;
|
|
1080
1115
|
|
|
1081
1116
|
return {
|
|
@@ -1091,12 +1126,15 @@ function finalizeProject(
|
|
|
1091
1126
|
routing: { labelPrefix, repos },
|
|
1092
1127
|
caps,
|
|
1093
1128
|
...(workerModel === undefined ? {} : { workerModel }),
|
|
1129
|
+
...(modelFallbacks.length === 0 ? {} : { modelFallbacks }),
|
|
1130
|
+
...(modelFallbackThreshold === undefined ? {} : { modelFallbackThreshold }),
|
|
1094
1131
|
escalation,
|
|
1095
1132
|
authority,
|
|
1096
1133
|
releasePolicy,
|
|
1097
1134
|
policy,
|
|
1098
1135
|
...(recoveryMerges === undefined ? {} : { recoveryMerges }),
|
|
1099
1136
|
reporting,
|
|
1137
|
+
...(criticalBase.length === 0 ? {} : { criticalBase }),
|
|
1100
1138
|
workspaceRoot: expandHome(pickString(p["workspaceRoot"], defaultWorkspaceRoot())),
|
|
1101
1139
|
mirrorRoot: expandHome(pickString(p["mirrorRoot"], defaultMirrorRoot())),
|
|
1102
1140
|
};
|
|
@@ -1136,6 +1174,9 @@ function finalizeAuthority(parsed: Raw | undefined): ProjectConfig["authority"]
|
|
|
1136
1174
|
return {
|
|
1137
1175
|
merge: (parsed["merge"] as ProjectConfig["authority"]["merge"]) ?? DEFAULT_AUTHORITY.merge,
|
|
1138
1176
|
release: (parsed["release"] as ProjectConfig["authority"]["release"]) ?? DEFAULT_AUTHORITY.release,
|
|
1177
|
+
// Unstated defaults to the human: a config written before promotion was a
|
|
1178
|
+
// key must load as operator-owned, never as a silent delegation.
|
|
1179
|
+
promotion: (parsed["promotion"] as ProjectConfig["authority"]["promotion"] | undefined) ?? DEFAULT_AUTHORITY.promotion,
|
|
1139
1180
|
};
|
|
1140
1181
|
}
|
|
1141
1182
|
|