owlrunkit 0.13.0 → 0.14.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/CHANGELOG.md +14 -0
- package/README.md +22 -4
- package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_2.md +79 -0
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +101 -2
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +1 -1
- package/package.json +1 -1
- package/packages/attest/distribution-manifest-v1.json +5 -0
- package/packages/attest/src/quick.mjs +5 -0
- package/registry-release-policy-v1.json +1 -1
- package/sbom.spdx.json +5 -5
- package/scripts/runkit-contract/core-contract.mjs +6 -1
- package/scripts/runkit-contract/onboarding-doctor.mjs +607 -0
- package/scripts/runkit-contract/profile-onboarding.mjs +332 -0
- package/scripts/runkit-contract/registry-adoption-gate.mjs +10 -7
- package/scripts/runkit-contract/registry-adoption.mjs +197 -0
- package/scripts/runkit-contract/resume-execution.mjs +8 -2
- package/scripts/runkit-contract/runkit-cli.mjs +174 -6
- package/scripts/runkit-contract/schemas/adoption-evidence-v1.schema.json +63 -0
|
@@ -66,6 +66,80 @@ import {
|
|
|
66
66
|
exportOfflineReceipt,
|
|
67
67
|
importOfflineReceipt,
|
|
68
68
|
} from "./offline-store.mjs";
|
|
69
|
+
import {
|
|
70
|
+
detectProfiles,
|
|
71
|
+
resolveProfilesImpact,
|
|
72
|
+
validateProfiles,
|
|
73
|
+
} from "./profile-onboarding.mjs";
|
|
74
|
+
import {
|
|
75
|
+
formatDoctorHuman,
|
|
76
|
+
runDoctor,
|
|
77
|
+
} from "./onboarding-doctor.mjs";
|
|
78
|
+
import {
|
|
79
|
+
formatAdoptionHuman,
|
|
80
|
+
runRegistryAdoption,
|
|
81
|
+
} from "./registry-adoption.mjs";
|
|
82
|
+
import { OFFICIAL_NPM_REGISTRY } from "./registry-adoption-gate.mjs";
|
|
83
|
+
|
|
84
|
+
const TOP_LEVEL_HELP = `OwlRunKit 0.14.0
|
|
85
|
+
|
|
86
|
+
Usage:
|
|
87
|
+
owlrunkit <command> [options]
|
|
88
|
+
|
|
89
|
+
Start here:
|
|
90
|
+
owlrunkit doctor --workspace .
|
|
91
|
+
owlrunkit profiles detect --workspace . --dry-run
|
|
92
|
+
owlrunkit adopt --workspace . --exact owlrunkit@0.14.0
|
|
93
|
+
|
|
94
|
+
Quick Verification
|
|
95
|
+
owlrunkit quick-verify --workspace . -- <command> [args...]
|
|
96
|
+
Low-risk, source-bound reusable evidence without writer leases or acceptance.
|
|
97
|
+
|
|
98
|
+
Formal Delivery
|
|
99
|
+
owlrunkit start --workspace . --run-id <id> --goal <file> \\
|
|
100
|
+
--work-item <id> --owned-path <path>
|
|
101
|
+
Use for multi-writer, long-running, migration, integration, release, funds,
|
|
102
|
+
production, or formal acceptance work.
|
|
103
|
+
|
|
104
|
+
Other onboarding commands:
|
|
105
|
+
owlrunkit profiles validate --workspace .
|
|
106
|
+
owlrunkit profiles impact --workspace . --changed <path>
|
|
107
|
+
owlrunkit inspect --workspace . --json
|
|
108
|
+
|
|
109
|
+
Quick receipts cannot become Formal acceptance.
|
|
110
|
+
Formal accepted does not grant Git or release authority.
|
|
111
|
+
Those always require separate explicit authorization.
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
function withHumanOutput(result, humanOutput) {
|
|
115
|
+
Object.defineProperty(result, "humanOutput", {
|
|
116
|
+
configurable: false,
|
|
117
|
+
enumerable: false,
|
|
118
|
+
value: humanOutput,
|
|
119
|
+
writable: false,
|
|
120
|
+
});
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function onboardingProjection() {
|
|
125
|
+
return {
|
|
126
|
+
nextAllowedAction: "run_onboarding_diagnostics",
|
|
127
|
+
steps: [
|
|
128
|
+
{
|
|
129
|
+
id: "doctor",
|
|
130
|
+
command: "owlrunkit doctor --workspace .",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "profiles_detect",
|
|
134
|
+
command: "owlrunkit profiles detect --workspace . --dry-run",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: "adopt_or_start",
|
|
138
|
+
command: "owlrunkit adopt --workspace . --exact owlrunkit@0.14.0 or owlrunkit start",
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
69
143
|
|
|
70
144
|
function parseOptions(values, { multi = [], boolean = [] } = {}) {
|
|
71
145
|
const options = {};
|
|
@@ -592,7 +666,25 @@ function closeoutGateRejected(runId, decision, issues) {
|
|
|
592
666
|
}
|
|
593
667
|
|
|
594
668
|
async function initialize(options) {
|
|
595
|
-
|
|
669
|
+
const initialized = await initializeProjectRunKit({ workspaceRoot: workspace(options) });
|
|
670
|
+
const result = {
|
|
671
|
+
...initialized,
|
|
672
|
+
onboarding: onboardingProjection(),
|
|
673
|
+
nextAllowedAction: "run_onboarding_diagnostics",
|
|
674
|
+
};
|
|
675
|
+
if (options.json === true) return result;
|
|
676
|
+
return withHumanOutput(
|
|
677
|
+
result,
|
|
678
|
+
[
|
|
679
|
+
`Initialized OwlRunKit ${result.core.coreVersion} in ${result.runtimeRoot}`,
|
|
680
|
+
"",
|
|
681
|
+
"Next:",
|
|
682
|
+
"1. owlrunkit doctor --workspace .",
|
|
683
|
+
"2. owlrunkit profiles detect --workspace . --dry-run",
|
|
684
|
+
"3. owlrunkit adopt --workspace . --exact owlrunkit@0.14.0 or owlrunkit start",
|
|
685
|
+
"",
|
|
686
|
+
].join("\n"),
|
|
687
|
+
);
|
|
596
688
|
}
|
|
597
689
|
|
|
598
690
|
function plan(options) {
|
|
@@ -844,7 +936,7 @@ function inspect(options) {
|
|
|
844
936
|
execution: executions.find(execution => execution.runId === requestedRunId),
|
|
845
937
|
}
|
|
846
938
|
: { mode: "summary" };
|
|
847
|
-
return { ...result, summary, view };
|
|
939
|
+
return { ...result, summary, view, onboarding: onboardingProjection() };
|
|
848
940
|
}
|
|
849
941
|
|
|
850
942
|
function closeout(options) {
|
|
@@ -1025,29 +1117,95 @@ function requestCommand(options, handler) {
|
|
|
1025
1117
|
export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
1026
1118
|
try {
|
|
1027
1119
|
const [command, ...rest] = argv;
|
|
1120
|
+
if (command === "--help" || command === "-h") {
|
|
1121
|
+
return withHumanOutput({
|
|
1122
|
+
status: "help",
|
|
1123
|
+
exitCode: 0,
|
|
1124
|
+
authorizationGranted: false,
|
|
1125
|
+
}, TOP_LEVEL_HELP);
|
|
1126
|
+
}
|
|
1127
|
+
if (command === "--version" || command === "-v") {
|
|
1128
|
+
return withHumanOutput({
|
|
1129
|
+
status: "version",
|
|
1130
|
+
exitCode: 0,
|
|
1131
|
+
version: "0.14.0",
|
|
1132
|
+
authorizationGranted: false,
|
|
1133
|
+
}, "owlrunkit 0.14.0\n");
|
|
1134
|
+
}
|
|
1028
1135
|
const separatorIndex = rest.indexOf("--");
|
|
1029
1136
|
if (separatorIndex >= 0 && command !== "verify" && command !== "quick-verify") {
|
|
1030
1137
|
throw new Error("Only runkit verify accepts an exact command after --.");
|
|
1031
1138
|
}
|
|
1032
1139
|
const optionValues = separatorIndex >= 0 ? rest.slice(0, separatorIndex) : rest;
|
|
1033
1140
|
const commandArgv = separatorIndex >= 0 ? rest.slice(separatorIndex + 1) : [];
|
|
1034
|
-
const nested = new Set(["lease", "delivery"]).has(command);
|
|
1141
|
+
const nested = new Set(["lease", "delivery", "profiles"]).has(command);
|
|
1035
1142
|
const [action, ...nestedOptions] = nested ? optionValues : [null, ...optionValues];
|
|
1036
1143
|
const options = parseOptions(nested ? nestedOptions : optionValues, {
|
|
1037
|
-
multi:
|
|
1144
|
+
multi: command === "profiles" && action === "impact"
|
|
1145
|
+
? ["changed"]
|
|
1146
|
+
: (command === "lease" && action === "acquire") || command === "start"
|
|
1147
|
+
? ["owned-path"]
|
|
1148
|
+
: [],
|
|
1038
1149
|
boolean: command === "inspect"
|
|
1039
1150
|
? ["json", "verbose", "history"]
|
|
1151
|
+
: command === "init"
|
|
1152
|
+
? ["json"]
|
|
1153
|
+
: command === "doctor" || command === "adopt"
|
|
1154
|
+
? ["json"]
|
|
1155
|
+
: command === "profiles"
|
|
1156
|
+
? ["json", "dry-run"]
|
|
1040
1157
|
: new Set(["quick-verify", "quick-attest", "quick-metrics"]).has(command)
|
|
1041
1158
|
? ["json", "local"]
|
|
1042
1159
|
: [],
|
|
1043
1160
|
});
|
|
1044
1161
|
if (command === "init") return await initialize(options);
|
|
1162
|
+
if (command === "doctor") {
|
|
1163
|
+
const timeoutMs = options["timeout-ms"] === undefined
|
|
1164
|
+
? 1_500
|
|
1165
|
+
: Number.parseInt(options["timeout-ms"], 10);
|
|
1166
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 25 || timeoutMs > 10_000) {
|
|
1167
|
+
throw new Error("--timeout-ms must be an integer from 25 to 10000.");
|
|
1168
|
+
}
|
|
1169
|
+
const report = await runDoctor({
|
|
1170
|
+
workspaceRoot: requireOption(options, "workspace"),
|
|
1171
|
+
registryUrl: options.registry ?? OFFICIAL_NPM_REGISTRY,
|
|
1172
|
+
timeoutMs,
|
|
1173
|
+
});
|
|
1174
|
+
report.exitCode = report.status === "ready" ? 0 : 2;
|
|
1175
|
+
return options.json === true
|
|
1176
|
+
? report
|
|
1177
|
+
: withHumanOutput(report, formatDoctorHuman(report));
|
|
1178
|
+
}
|
|
1179
|
+
if (command === "adopt") {
|
|
1180
|
+
const result = await runRegistryAdoption({
|
|
1181
|
+
workspaceRoot: requireOption(options, "workspace"),
|
|
1182
|
+
exactSpec: requireOption(options, "exact"),
|
|
1183
|
+
});
|
|
1184
|
+
result.exitCode = result.status === "adopted" ? 0 : 2;
|
|
1185
|
+
return options.json === true
|
|
1186
|
+
? result
|
|
1187
|
+
: withHumanOutput(result, formatAdoptionHuman(result));
|
|
1188
|
+
}
|
|
1045
1189
|
if (command === "start") return startExecution(options);
|
|
1046
1190
|
if (command === "plan") {
|
|
1047
1191
|
const root = workspace(options);
|
|
1048
1192
|
return withControlTransaction(root, () => plan(options));
|
|
1049
1193
|
}
|
|
1050
1194
|
if (command === "inspect") return inspect(options);
|
|
1195
|
+
if (command === "profiles") {
|
|
1196
|
+
const root = requireOption(options, "workspace");
|
|
1197
|
+
if (action === "detect") {
|
|
1198
|
+
if (options["dry-run"] !== true) throw new Error("profiles detect requires --dry-run.");
|
|
1199
|
+
return detectProfiles({ workspaceRoot: root });
|
|
1200
|
+
}
|
|
1201
|
+
if (action === "validate") return validateProfiles({ workspaceRoot: root });
|
|
1202
|
+
if (action === "impact") {
|
|
1203
|
+
const changedPaths = options.changed ?? [];
|
|
1204
|
+
if (changedPaths.length === 0) throw new Error("profiles impact requires --changed.");
|
|
1205
|
+
return resolveProfilesImpact({ workspaceRoot: root, changedPaths });
|
|
1206
|
+
}
|
|
1207
|
+
throw new Error("Usage: owlrunkit profiles <detect|validate|impact> [options]");
|
|
1208
|
+
}
|
|
1051
1209
|
if (command === "lease") {
|
|
1052
1210
|
const root = workspace(options);
|
|
1053
1211
|
const runId = safeRunId(requireOption(options, "run-id"));
|
|
@@ -1184,7 +1342,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
1184
1342
|
return withControlTransaction(root, () => closeout(options));
|
|
1185
1343
|
}
|
|
1186
1344
|
if (command === "finish") return finishExecution(options);
|
|
1187
|
-
throw new Error("Usage:
|
|
1345
|
+
throw new Error("Usage: owlrunkit <init|doctor|adopt|profiles|start|verify|repair|offline-export|offline-import|quick-verify|quick-attest|quick-metrics|finish|plan|inspect|lease|delivery|coverage-adopt|resume|verify-plan|resource-preflight|snapshot|visual-smoke|finalize|ready-for-commit|closeout> [options]");
|
|
1188
1346
|
} catch (error) {
|
|
1189
1347
|
return {
|
|
1190
1348
|
status: "invalid_input",
|
|
@@ -1209,6 +1367,16 @@ if (isDirectExecution(import.meta.url)) {
|
|
|
1209
1367
|
? parseOptions(argv.slice(1), { boolean: ["json", "verbose", "history"] })
|
|
1210
1368
|
: null;
|
|
1211
1369
|
const humanInspect = inspectOptions !== null && inspectOptions.json !== true;
|
|
1212
|
-
|
|
1370
|
+
const onboardingHumanCommand = new Set(["init", "doctor", "adopt", "profiles"]).has(argv[0]);
|
|
1371
|
+
const interactiveOnboarding = onboardingHumanCommand
|
|
1372
|
+
&& !argv.includes("--json")
|
|
1373
|
+
&& process.stdout.isTTY === true;
|
|
1374
|
+
process.stdout.write(
|
|
1375
|
+
typeof result.humanOutput === "string" && (!onboardingHumanCommand || interactiveOnboarding)
|
|
1376
|
+
? result.humanOutput
|
|
1377
|
+
: humanInspect
|
|
1378
|
+
? formatInspectHuman(result)
|
|
1379
|
+
: `${JSON.stringify(result)}\n`,
|
|
1380
|
+
);
|
|
1213
1381
|
process.exitCode = result.exitCode;
|
|
1214
1382
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://owlcoda.dev/schemas/runkit/registry-adoption-evidence-v1.json",
|
|
4
|
+
"title": "OwlCoda RunKit Registry Adoption Evidence V1",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"schemaVersion",
|
|
9
|
+
"status",
|
|
10
|
+
"decision",
|
|
11
|
+
"packageName",
|
|
12
|
+
"version",
|
|
13
|
+
"exactSpec",
|
|
14
|
+
"registryRelease",
|
|
15
|
+
"installedBinding",
|
|
16
|
+
"authority",
|
|
17
|
+
"authorizationGranted"
|
|
18
|
+
],
|
|
19
|
+
"properties": {
|
|
20
|
+
"schemaVersion": { "const": "OwlCodaRunKitRegistryAdoptionEvidenceV1" },
|
|
21
|
+
"status": { "const": "adopted" },
|
|
22
|
+
"decision": { "const": "ELIGIBLE" },
|
|
23
|
+
"packageName": { "const": "owlrunkit" },
|
|
24
|
+
"version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
|
|
25
|
+
"exactSpec": { "type": "string", "pattern": "^owlrunkit@[0-9]+\\.[0-9]+\\.[0-9]+$" },
|
|
26
|
+
"registryRelease": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"additionalProperties": false,
|
|
29
|
+
"required": ["registry", "packageName", "version", "shasum", "integrity", "tarballUrl"],
|
|
30
|
+
"properties": {
|
|
31
|
+
"registry": { "const": "https://registry.npmjs.org" },
|
|
32
|
+
"packageName": { "const": "owlrunkit" },
|
|
33
|
+
"version": { "type": "string" },
|
|
34
|
+
"shasum": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
|
|
35
|
+
"integrity": { "type": "string", "pattern": "^sha512-" },
|
|
36
|
+
"tarballUrl": { "type": "string", "pattern": "^https://registry\\.npmjs\\.org/owlrunkit/-/owlrunkit-[0-9]+\\.[0-9]+\\.[0-9]+\\.tgz$" }
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"installedBinding": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": false,
|
|
42
|
+
"required": ["requestedSpec", "packageName", "version", "resolved", "integrity"],
|
|
43
|
+
"properties": {
|
|
44
|
+
"requestedSpec": { "type": "string" },
|
|
45
|
+
"packageName": { "const": "owlrunkit" },
|
|
46
|
+
"version": { "type": "string" },
|
|
47
|
+
"resolved": { "type": "string" },
|
|
48
|
+
"integrity": { "type": "string" }
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"authority": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"required": ["git", "release", "foreignProjectWrite"],
|
|
55
|
+
"properties": {
|
|
56
|
+
"git": { "const": false },
|
|
57
|
+
"release": { "const": false },
|
|
58
|
+
"foreignProjectWrite": { "const": false }
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"authorizationGranted": { "const": false }
|
|
62
|
+
}
|
|
63
|
+
}
|