owlrunkit 0.20.0 → 0.21.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 +48 -0
- package/README.md +63 -10
- package/docs/architecture/OWLCODA_RUNKIT_0201_RELEASE_TRUTH_AND_PROFILE_NORMALIZATION_PATCH_DECISION_20260813.md +95 -0
- package/docs/architecture/OWLCODA_RUNKIT_021_TEAM_DELIVERY_PHASE2_PRODUCT_DECISION_20260813.md +249 -0
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +92 -12
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
- package/package.json +1 -1
- package/packages/attest/README.md +7 -1
- package/packages/attest/consumer-surface-v3.json +275 -0
- package/packages/attest/distribution-manifest-v1.json +14 -0
- package/packages/attest/schemas/canonical-candidate-identity-v1.schema.json +112 -0
- package/packages/attest/schemas/foreign-workspace-filesystem-identity-v1.schema.json +32 -0
- package/packages/attest/schemas/quick-verification-receipt-v4.schema.json +226 -0
- package/packages/attest/src/candidate-identity.mjs +454 -0
- package/packages/attest/src/index.mjs +11 -0
- package/packages/attest/src/quick-receipt-contract.mjs +126 -5
- package/packages/attest/src/quick.mjs +43 -8
- package/{registry-release-policy-v1.json → registry-release-policy-v2.json} +8 -9
- package/sbom.spdx.json +4 -4
- package/scripts/runkit-contract/core-contract.mjs +14 -1
- package/scripts/runkit-contract/fleet-skill-plan.mjs +223 -0
- package/scripts/runkit-contract/formal-workflow.mjs +3 -1
- package/scripts/runkit-contract/inspect-presentation.mjs +56 -0
- package/scripts/runkit-contract/install-codex-skill.mjs +1 -0
- package/scripts/runkit-contract/onboarding-bootstrap.mjs +15 -0
- package/scripts/runkit-contract/onboarding-doctor.mjs +201 -7
- package/scripts/runkit-contract/profile-onboarding.mjs +6 -0
- package/scripts/runkit-contract/project-cli-resolver.mjs +9 -1
- package/scripts/runkit-contract/quick-metrics.mjs +9 -5
- package/scripts/runkit-contract/quick-verify.mjs +108 -24
- package/scripts/runkit-contract/registry-adoption-gate.mjs +12 -3
- package/scripts/runkit-contract/registry-adoption.mjs +10 -5
- package/scripts/runkit-contract/runkit-cli.mjs +289 -19
- package/scripts/runkit-contract/schemas/delivery-lifecycle-v1.schema.json +91 -0
- package/scripts/runkit-contract/schemas/external-gate-v1.schema.json +68 -0
- package/scripts/runkit-contract/schemas/fleet-skill-upgrade-plan-v1.schema.json +140 -0
- package/scripts/runkit-contract/schemas/inspect-compact-v1.schema.json +93 -0
- package/scripts/runkit-contract/schemas/team-delivery-status-v2.schema.json +219 -0
- package/scripts/runkit-contract/schemas/team-project-event-v6.schema.json +82 -0
- package/scripts/runkit-contract/schemas/team-project-event-v7.schema.json +80 -0
- package/scripts/runkit-contract/schemas/team-project-status-v4.schema.json +208 -0
- package/scripts/runkit-contract/sync-release-identity.mjs +87 -0
- package/scripts/runkit-contract/team-delivery.mjs +128 -3
- package/scripts/runkit-contract/team-project.mjs +970 -9
|
@@ -176,6 +176,62 @@ export function buildInspectSummary(
|
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
function compactWarningSummary(projectDriver) {
|
|
180
|
+
const byCode = new Map();
|
|
181
|
+
for (const warning of projectDriver?.warnings ?? []) {
|
|
182
|
+
const current = byCode.get(warning.code) ?? {
|
|
183
|
+
code: warning.code,
|
|
184
|
+
count: 0,
|
|
185
|
+
blocking: warning.blocking === true,
|
|
186
|
+
};
|
|
187
|
+
current.count += 1;
|
|
188
|
+
current.blocking ||= warning.blocking === true;
|
|
189
|
+
byCode.set(warning.code, current);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
count: [...byCode.values()].reduce((total, group) => total + group.count, 0),
|
|
193
|
+
groups: [...byCode.values()].sort((left, right) => compareCodeUnits(left.code, right.code)),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function buildInspectCompactV1(inspected) {
|
|
198
|
+
const projectDriver = inspected.projectDriver ?? null;
|
|
199
|
+
const summary = inspected.summary;
|
|
200
|
+
return {
|
|
201
|
+
schemaVersion: "OwlCodaRunKitInspectCompactV1",
|
|
202
|
+
status: "inspected_compact",
|
|
203
|
+
exitCode: inspected.exitCode,
|
|
204
|
+
projectTruthHash: projectDriver?.projectTruthHash ?? null,
|
|
205
|
+
progress: {
|
|
206
|
+
overall: projectDriver?.overall ?? null,
|
|
207
|
+
completedWorkItems: projectDriver?.counts?.completed ?? null,
|
|
208
|
+
totalWorkItems: projectDriver?.counts?.total ?? null,
|
|
209
|
+
},
|
|
210
|
+
dominantGap: {
|
|
211
|
+
code: summary.dominantGap.code,
|
|
212
|
+
reason: summary.dominantGap.reasons[0] ?? null,
|
|
213
|
+
},
|
|
214
|
+
ownerAgentId: projectDriver?.nextActorId
|
|
215
|
+
?? projectDriver?.dominantGap?.agentId
|
|
216
|
+
?? null,
|
|
217
|
+
nextAction: summary.recommendedNextAction ?? summary.nextAllowedAction,
|
|
218
|
+
warningSummary: compactWarningSummary(projectDriver),
|
|
219
|
+
execution: {
|
|
220
|
+
state: summary.currentExecution.state,
|
|
221
|
+
openCount: summary.currentExecution.openCount,
|
|
222
|
+
activeLeaseCount: summary.leases.activeCount,
|
|
223
|
+
},
|
|
224
|
+
authorityBoundary: {
|
|
225
|
+
git: false,
|
|
226
|
+
release: false,
|
|
227
|
+
deployment: false,
|
|
228
|
+
production: false,
|
|
229
|
+
business: false,
|
|
230
|
+
},
|
|
231
|
+
authorizationGranted: false,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
179
235
|
function value(value) {
|
|
180
236
|
if (value === null || value === undefined || value === "") return "none";
|
|
181
237
|
return String(value);
|
|
@@ -786,6 +786,7 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
786
786
|
workspaceRoots: options.workspace ?? null,
|
|
787
787
|
fleetManifestPath: options["fleet-manifest"] ?? null,
|
|
788
788
|
fleetRoots: options["fleet-root"] ?? null,
|
|
789
|
+
fleetRegistryPath: options.registry ?? null,
|
|
789
790
|
});
|
|
790
791
|
return { exitCode: 0, ...output };
|
|
791
792
|
}
|
|
@@ -46,6 +46,16 @@ const TRANSACTION_PATHS = Object.freeze([
|
|
|
46
46
|
"adoption",
|
|
47
47
|
]);
|
|
48
48
|
|
|
49
|
+
function shellQuote(value) {
|
|
50
|
+
return `'${String(value).replaceAll("'", `'"'"'`)}'`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function requestedSuccessorSpec(value) {
|
|
54
|
+
return /^owlrunkit@[0-9]+\.[0-9]+\.[0-9]+$/u.test(value ?? "")
|
|
55
|
+
? value
|
|
56
|
+
: null;
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
function pathEntryExists(filePath) {
|
|
50
60
|
try {
|
|
51
61
|
lstatSync(filePath);
|
|
@@ -301,6 +311,7 @@ export async function planOnboardingBootstrapV1({
|
|
|
301
311
|
} = {}) {
|
|
302
312
|
const root = resolveBoundedWorkspaceRoot(workspaceRoot);
|
|
303
313
|
const issueCodes = [];
|
|
314
|
+
const requestedSuccessor = requestedSuccessorSpec(exactSpec);
|
|
304
315
|
if (exactSpec !== EXACT_SPEC) issueCodes.push("bootstrap_exact_spec_required");
|
|
305
316
|
const local = readLocalInstallBinding({ workspaceRoot: root });
|
|
306
317
|
if (local.status !== "bound") {
|
|
@@ -385,6 +396,8 @@ export async function planOnboardingBootstrapV1({
|
|
|
385
396
|
issueCodes: [...new Set(issueCodes)].sort(),
|
|
386
397
|
nextCommand: issueCodes.length === 0
|
|
387
398
|
? `npx --no-install owlrunkit bootstrap --workspace ${JSON.stringify(root)} --exact ${EXACT_SPEC} --apply`
|
|
399
|
+
: issueCodes.includes("bootstrap_exact_spec_required") && requestedSuccessor !== null
|
|
400
|
+
? `cd ${shellQuote(root)} && npm install --save-exact ${requestedSuccessor} && npx --no-install owlrunkit bootstrap --workspace ${shellQuote(root)} --exact ${requestedSuccessor} --dry-run`
|
|
388
401
|
: "repair bootstrap preflight issues and rerun --dry-run",
|
|
389
402
|
authorizationGranted: false,
|
|
390
403
|
};
|
|
@@ -573,6 +586,7 @@ export async function applyOnboardingBootstrapV1({
|
|
|
573
586
|
"doctor",
|
|
574
587
|
() => runDoctor({
|
|
575
588
|
workspaceRoot: root,
|
|
589
|
+
discoverSharedSkill: true,
|
|
576
590
|
registryUrl: OFFICIAL_NPM_REGISTRY,
|
|
577
591
|
registryClient,
|
|
578
592
|
}),
|
|
@@ -677,6 +691,7 @@ export function formatOnboardingBootstrapHumanV1(result) {
|
|
|
677
691
|
const issues = result.issueCodes?.join(", ") || "unknown issue";
|
|
678
692
|
return [
|
|
679
693
|
`Bootstrap blocked: ${issues}`,
|
|
694
|
+
...(result.nextCommand ? [`Repair: ${result.nextCommand}`] : []),
|
|
680
695
|
`Rollback: ${result.rollbackOutcome ?? "not_required"}.`,
|
|
681
696
|
...(result.receiptPath ? [`Receipt: ${result.receiptPath}`] : []),
|
|
682
697
|
"No Git, release, deployment, production, or business authority was granted.",
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
closeSync,
|
|
3
|
+
existsSync,
|
|
3
4
|
fstatSync,
|
|
4
5
|
lstatSync,
|
|
5
6
|
openSync,
|
|
6
7
|
readSync,
|
|
7
8
|
realpathSync,
|
|
8
9
|
} from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
9
11
|
import path from "node:path";
|
|
12
|
+
import { userInfo } from "node:os";
|
|
10
13
|
|
|
11
14
|
import {
|
|
12
15
|
CORE_VERSION,
|
|
@@ -20,12 +23,19 @@ import {
|
|
|
20
23
|
} from "./registry-adoption-gate.mjs";
|
|
21
24
|
import { resolveProjectCli } from "./project-cli-resolver.mjs";
|
|
22
25
|
import { inspectProjectControlState } from "./project-control-state.mjs";
|
|
26
|
+
import {
|
|
27
|
+
inspectFleetForSkillChange,
|
|
28
|
+
inspectInstalledSkillCompatibility,
|
|
29
|
+
} from "./install-codex-skill.mjs";
|
|
23
30
|
|
|
24
31
|
const PACKAGE_NAME = "owlrunkit";
|
|
25
32
|
const EXPECTED_VERSION = CORE_VERSION;
|
|
26
33
|
const MAX_JSON_BYTES = 1_048_576;
|
|
27
34
|
const MAX_JSON_DEPTH = 64;
|
|
28
35
|
const MAX_JSON_NODES = 50_000;
|
|
36
|
+
const PACKAGE_SKILL_RELATIVE = path.join(
|
|
37
|
+
"integrations", "codex", "skills", "owlcoda-runkit",
|
|
38
|
+
);
|
|
29
39
|
|
|
30
40
|
class StrictJsonParser {
|
|
31
41
|
constructor(text, { maxDepth = MAX_JSON_DEPTH, maxNodes = MAX_JSON_NODES } = {}) {
|
|
@@ -286,6 +296,81 @@ export function readWorkspaceJsonBounded(root, relativePath, options) {
|
|
|
286
296
|
return text === null ? null : parseJsonStrict(text, options);
|
|
287
297
|
}
|
|
288
298
|
|
|
299
|
+
function parsedSkillRoot(requestedRoot) {
|
|
300
|
+
if (typeof requestedRoot !== "string" || requestedRoot.length === 0) return null;
|
|
301
|
+
try {
|
|
302
|
+
const root = realpathSync(requestedRoot);
|
|
303
|
+
const skillText = readWorkspaceFileBounded(root, "SKILL.md");
|
|
304
|
+
const config = readWorkspaceJsonBounded(
|
|
305
|
+
root,
|
|
306
|
+
path.join("assets", "templates", "config.json"),
|
|
307
|
+
);
|
|
308
|
+
const version = skillText.match(/standalone `owlrunkit@(\d+\.\d+\.\d+)`/u)?.[1] ?? null;
|
|
309
|
+
const configCoreVersion = config?.core?.coreVersion ?? null;
|
|
310
|
+
return {
|
|
311
|
+
root,
|
|
312
|
+
skillPath: path.join(root, "SKILL.md"),
|
|
313
|
+
version,
|
|
314
|
+
configCoreVersion,
|
|
315
|
+
status: version !== null && configCoreVersion === version ? "readable" : "invalid",
|
|
316
|
+
};
|
|
317
|
+
} catch {
|
|
318
|
+
return {
|
|
319
|
+
root: path.resolve(requestedRoot),
|
|
320
|
+
skillPath: path.resolve(requestedRoot, "SKILL.md"),
|
|
321
|
+
version: null,
|
|
322
|
+
configCoreVersion: null,
|
|
323
|
+
status: "invalid",
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function discoveredSharedSkillRoot() {
|
|
329
|
+
const requested = process.env.OWLCODA_RUNKIT_PROCESS_SKILL_ROOT;
|
|
330
|
+
if (typeof requested === "string" && requested.length > 0) return requested;
|
|
331
|
+
const candidates = [
|
|
332
|
+
path.join(homedir(), ".agents", "skills", "owlcoda-runkit"),
|
|
333
|
+
path.join(homedir(), ".codex", "skills", "owlcoda-runkit"),
|
|
334
|
+
];
|
|
335
|
+
return candidates.find(candidate => existsSync(candidate)) ?? null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function inspectDoctorSkillStateV1({ packageRoot, sharedSkillRoot } = {}) {
|
|
339
|
+
const packageSkill = typeof packageRoot === "string"
|
|
340
|
+
? parsedSkillRoot(path.join(packageRoot, PACKAGE_SKILL_RELATIVE))
|
|
341
|
+
: null;
|
|
342
|
+
const selectedSharedRoot = sharedSkillRoot ?? discoveredSharedSkillRoot();
|
|
343
|
+
const sharedSkill = selectedSharedRoot === null ? null : parsedSkillRoot(selectedSharedRoot);
|
|
344
|
+
const warningCodes = [];
|
|
345
|
+
if (sharedSkill === null) warningCodes.push("shared_skill_not_found");
|
|
346
|
+
else if (sharedSkill.status !== "readable") warningCodes.push("shared_skill_invalid");
|
|
347
|
+
else if (packageSkill?.status === "readable" && sharedSkill.version !== packageSkill.version) {
|
|
348
|
+
warningCodes.push("shared_skill_version_drift");
|
|
349
|
+
}
|
|
350
|
+
const packageIssueCodes = [];
|
|
351
|
+
if (packageSkill?.status !== "readable") warningCodes.push("package_skill_unavailable");
|
|
352
|
+
const skillDrift = warningCodes.includes("shared_skill_version_drift");
|
|
353
|
+
return {
|
|
354
|
+
schemaVersion: "OwlCodaRunKitDoctorSkillStateV1",
|
|
355
|
+
packageVersion: packageSkill?.version ?? null,
|
|
356
|
+
configCoreVersion: packageSkill?.configCoreVersion ?? null,
|
|
357
|
+
packageSkillVersion: packageSkill?.version ?? null,
|
|
358
|
+
packageSkillPath: packageSkill?.skillPath ?? null,
|
|
359
|
+
processSkillVersion: sharedSkill?.version ?? null,
|
|
360
|
+
processSkillPath: sharedSkill?.skillPath ?? null,
|
|
361
|
+
loadedSkillVersion: "unknown",
|
|
362
|
+
skillDrift,
|
|
363
|
+
blocking: false,
|
|
364
|
+
issueCodes: packageIssueCodes,
|
|
365
|
+
warningCodes,
|
|
366
|
+
recommendedAction: skillDrift
|
|
367
|
+
? `Start a new Agent session and load the package-bound Skill at ${packageSkill.skillPath}.`
|
|
368
|
+
: warningCodes.length > 0
|
|
369
|
+
? `Use the package-bound Skill at ${packageSkill?.skillPath ?? "the installed package"}.`
|
|
370
|
+
: "none",
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
289
374
|
async function readResponseJsonBounded(response) {
|
|
290
375
|
if (!response.body) throw new Error("registry response body is missing");
|
|
291
376
|
const reader = response.body.getReader();
|
|
@@ -577,7 +662,13 @@ function configCheck(root) {
|
|
|
577
662
|
);
|
|
578
663
|
if (config === null) return { status: "missing" };
|
|
579
664
|
const gate = validateProjectConfigV2(config);
|
|
580
|
-
return gate.valid
|
|
665
|
+
return gate.valid
|
|
666
|
+
? {
|
|
667
|
+
status: "ok",
|
|
668
|
+
coreVersion: config.core.coreVersion,
|
|
669
|
+
coreManifestSha256: config.core.coreManifestSha256,
|
|
670
|
+
}
|
|
671
|
+
: { status: "invalid", issues: gate.issues };
|
|
581
672
|
} catch {
|
|
582
673
|
return { status: "invalid" };
|
|
583
674
|
}
|
|
@@ -689,11 +780,17 @@ export function readAdoptionReadiness({ workspaceRoot } = {}) {
|
|
|
689
780
|
return adoptionCheck(root);
|
|
690
781
|
}
|
|
691
782
|
|
|
692
|
-
|
|
783
|
+
async function buildDoctorReport({
|
|
693
784
|
workspaceRoot,
|
|
785
|
+
sharedSkillRoot,
|
|
786
|
+
discoverSharedSkill = false,
|
|
694
787
|
registryUrl,
|
|
695
788
|
timeoutMs = 1_500,
|
|
696
789
|
registryClient,
|
|
790
|
+
includeSharedSkill = false,
|
|
791
|
+
skillRoot = path.join(userInfo().homedir, ".agents", "skills", "owlcoda-runkit"),
|
|
792
|
+
skillInspector = inspectInstalledSkillCompatibility,
|
|
793
|
+
skillFleetInspector = inspectFleetForSkillChange,
|
|
697
794
|
} = {}) {
|
|
698
795
|
const root = resolveBoundedWorkspaceRoot(workspaceRoot);
|
|
699
796
|
const core = currentCoreIdentity();
|
|
@@ -715,6 +812,72 @@ export async function runDoctor({
|
|
|
715
812
|
const profiles = await doctorProfilesCheck(root);
|
|
716
813
|
const adoption = adoptionCheck(root, installed);
|
|
717
814
|
const runtimeIsolation = runtimeIsolationCheck(root);
|
|
815
|
+
const skill = includeSharedSkill && (sharedSkillRoot !== undefined || discoverSharedSkill)
|
|
816
|
+
? {
|
|
817
|
+
...inspectDoctorSkillStateV1({
|
|
818
|
+
packageRoot: installed.status === "bound" ? installed.packageRoot : undefined,
|
|
819
|
+
sharedSkillRoot,
|
|
820
|
+
}),
|
|
821
|
+
packageVersion: installed.status === "bound" ? installed.version : null,
|
|
822
|
+
configCoreVersion: config.status === "ok" ? config.coreVersion : null,
|
|
823
|
+
}
|
|
824
|
+
: includeSharedSkill
|
|
825
|
+
? {
|
|
826
|
+
schemaVersion: "OwlCodaRunKitDoctorSkillStateV1",
|
|
827
|
+
packageVersion: installed.status === "bound" ? installed.version : null,
|
|
828
|
+
configCoreVersion: core.coreVersion,
|
|
829
|
+
packageSkillVersion: null,
|
|
830
|
+
packageSkillPath: null,
|
|
831
|
+
processSkillVersion: null,
|
|
832
|
+
processSkillPath: null,
|
|
833
|
+
loadedSkillVersion: "unknown",
|
|
834
|
+
skillDrift: false,
|
|
835
|
+
blocking: false,
|
|
836
|
+
issueCodes: [],
|
|
837
|
+
warningCodes: [],
|
|
838
|
+
recommendedAction: "none",
|
|
839
|
+
}
|
|
840
|
+
: null;
|
|
841
|
+
let sharedSkill = null;
|
|
842
|
+
if (includeSharedSkill) {
|
|
843
|
+
let inspectedSkill;
|
|
844
|
+
try {
|
|
845
|
+
inspectedSkill = await skillInspector({ targetRoot: skillRoot });
|
|
846
|
+
} catch (error) {
|
|
847
|
+
inspectedSkill = {
|
|
848
|
+
status: "invalid",
|
|
849
|
+
installedSkillVersion: null,
|
|
850
|
+
issues: [error instanceof Error ? error.message : String(error)],
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
let activationBlockedReason = null;
|
|
854
|
+
if (inspectedSkill.status !== "valid") {
|
|
855
|
+
try {
|
|
856
|
+
await skillFleetInspector();
|
|
857
|
+
} catch (error) {
|
|
858
|
+
activationBlockedReason = error instanceof Error ? error.message : String(error);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
const sharedSkillDrift = inspectedSkill.status === "version_mismatch";
|
|
862
|
+
sharedSkill = {
|
|
863
|
+
status: inspectedSkill.status === "valid"
|
|
864
|
+
? "valid"
|
|
865
|
+
: sharedSkillDrift
|
|
866
|
+
? "expected_nonblocking_drift"
|
|
867
|
+
: "unavailable_nonblocking",
|
|
868
|
+
blocking: false,
|
|
869
|
+
projectCliVersion: installed.version ?? null,
|
|
870
|
+
projectCoreVersion: core.coreVersion,
|
|
871
|
+
sharedSkillVersion: inspectedSkill.installedSkillVersion ?? null,
|
|
872
|
+
issueCodes: [...new Set(inspectedSkill.issues ?? [])].sort(),
|
|
873
|
+
activationBlockedReason,
|
|
874
|
+
recommendedAction: inspectedSkill.status === "valid"
|
|
875
|
+
? null
|
|
876
|
+
: activationBlockedReason?.startsWith("skill_update_blocked_active_execution:")
|
|
877
|
+
? "wait_for_active_execution_or_lease_then_refresh_shared_skill"
|
|
878
|
+
: "run_fleet_safe_shared_skill_refresh",
|
|
879
|
+
};
|
|
880
|
+
}
|
|
718
881
|
const checks = {
|
|
719
882
|
node: {
|
|
720
883
|
status: nodeOk ? "ok" : "unsupported",
|
|
@@ -744,6 +907,8 @@ export async function runDoctor({
|
|
|
744
907
|
detected: readProjectScripts(root),
|
|
745
908
|
},
|
|
746
909
|
runtimeIsolation,
|
|
910
|
+
...(skill === null ? {} : { skill }),
|
|
911
|
+
...(sharedSkill === null ? {} : { sharedSkill }),
|
|
747
912
|
lifecycle: {
|
|
748
913
|
status: lifecycle.status,
|
|
749
914
|
activeRunIds: lifecycle.activeRunIds,
|
|
@@ -762,6 +927,7 @@ export async function runDoctor({
|
|
|
762
927
|
if (installed.status !== "bound") {
|
|
763
928
|
issueCodes.push(...(installed.issueCodes ?? ["registry_install_binding_mismatch"]));
|
|
764
929
|
}
|
|
930
|
+
issueCodes.push(...(skill?.issueCodes ?? []));
|
|
765
931
|
if (
|
|
766
932
|
registry.status === "registry_verified"
|
|
767
933
|
&& (
|
|
@@ -779,11 +945,14 @@ export async function runDoctor({
|
|
|
779
945
|
...runtimeIsolation.affectedScripts
|
|
780
946
|
.map(({ script, tool }) => `runkit_runtime_collection_risk:${tool}:${script}`),
|
|
781
947
|
...(profileLauncherWarningCount > 0 ? ["profile_launcher_warnings"] : []),
|
|
948
|
+
...(skill?.warningCodes ?? []),
|
|
782
949
|
].sort();
|
|
783
950
|
const lifecycleNextAction = lifecycle.recovery.nextAllowedAction;
|
|
784
|
-
const maintenanceNextAction =
|
|
785
|
-
? "
|
|
786
|
-
:
|
|
951
|
+
const maintenanceNextAction = skill?.skillDrift
|
|
952
|
+
? "reload_package_bound_skill"
|
|
953
|
+
: profileLauncherWarningCount > 0
|
|
954
|
+
? "review_profile_launchers"
|
|
955
|
+
: null;
|
|
787
956
|
const nextAllowedAction = uniqueIssues.length === 0
|
|
788
957
|
? lifecycleNextAction !== "plan_new_execution"
|
|
789
958
|
? lifecycleNextAction
|
|
@@ -802,7 +971,9 @@ export async function runDoctor({
|
|
|
802
971
|
? "repair_execution_artifacts"
|
|
803
972
|
: "repair_registry_binding";
|
|
804
973
|
return {
|
|
805
|
-
schemaVersion:
|
|
974
|
+
schemaVersion: includeSharedSkill
|
|
975
|
+
? "OwlCodaRunKitDoctorReportV2"
|
|
976
|
+
: "OwlCodaRunKitDoctorReportV1",
|
|
806
977
|
status: uniqueIssues.length === 0 ? "ready" : "issues_found",
|
|
807
978
|
checks,
|
|
808
979
|
issueCodes: uniqueIssues,
|
|
@@ -810,7 +981,9 @@ export async function runDoctor({
|
|
|
810
981
|
profileLauncherWarnings: {
|
|
811
982
|
count: profileLauncherWarningCount,
|
|
812
983
|
blocking: false,
|
|
813
|
-
recommendedAction:
|
|
984
|
+
recommendedAction: profileLauncherWarningCount > 0
|
|
985
|
+
? "review_profile_launchers"
|
|
986
|
+
: null,
|
|
814
987
|
},
|
|
815
988
|
lifecycleNextAction,
|
|
816
989
|
maintenanceNextAction,
|
|
@@ -819,6 +992,14 @@ export async function runDoctor({
|
|
|
819
992
|
};
|
|
820
993
|
}
|
|
821
994
|
|
|
995
|
+
export async function runDoctor(options = {}) {
|
|
996
|
+
return buildDoctorReport({ ...options, includeSharedSkill: false });
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
export async function runDoctorV2(options = {}) {
|
|
1000
|
+
return buildDoctorReport({ ...options, includeSharedSkill: true });
|
|
1001
|
+
}
|
|
1002
|
+
|
|
822
1003
|
export function formatDoctorHuman(report) {
|
|
823
1004
|
const otherWarnings = report.warningCodes.filter(
|
|
824
1005
|
(code) => code !== "profile_launcher_warnings",
|
|
@@ -828,9 +1009,22 @@ export function formatDoctorHuman(report) {
|
|
|
828
1009
|
`Node: ${report.checks.node.status} (${report.checks.node.version})`,
|
|
829
1010
|
`Core: ${report.checks.core.status} (${report.checks.core.version})`,
|
|
830
1011
|
`Installed package: ${report.checks.installedPackage.status}`,
|
|
1012
|
+
...(report.checks.skill
|
|
1013
|
+
? [
|
|
1014
|
+
`Skill: package ${report.checks.skill.packageSkillVersion ?? "unknown"}; process ${report.checks.skill.processSkillVersion ?? "unknown"}${report.checks.skill.skillDrift ? " (drift, non-blocking)" : ""}; loaded ${report.checks.skill.loadedSkillVersion}.`,
|
|
1015
|
+
`Package-bound Skill: ${report.checks.skill.packageSkillPath ?? "unavailable"}`,
|
|
1016
|
+
`Process-wide Skill: ${report.checks.skill.processSkillPath ?? "unavailable"}`,
|
|
1017
|
+
]
|
|
1018
|
+
: []),
|
|
831
1019
|
`Registry: ${report.checks.registry.status}`,
|
|
832
1020
|
`Profiles: ${report.checks.profiles.status}`,
|
|
833
1021
|
`Adoption: ${report.checks.adoption.status}`,
|
|
1022
|
+
...(report.checks.sharedSkill
|
|
1023
|
+
? [`Shared Skill: ${report.checks.sharedSkill.status} (${report.checks.sharedSkill.sharedSkillVersion ?? "missing"}; project Core ${report.checks.sharedSkill.projectCoreVersion})`]
|
|
1024
|
+
: []),
|
|
1025
|
+
...(report.checks.sharedSkill?.activationBlockedReason
|
|
1026
|
+
? [`Shared Skill activation: ${report.checks.sharedSkill.activationBlockedReason}`]
|
|
1027
|
+
: []),
|
|
834
1028
|
`Lifecycle: ${report.checks.lifecycle.status}`,
|
|
835
1029
|
...(report.issueCodes.length > 0 ? [`Issues: ${report.issueCodes.join(", ")}`] : []),
|
|
836
1030
|
...(report.profileLauncherWarnings.count > 0
|
|
@@ -1826,6 +1826,12 @@ export function reconcileProfilesV2({
|
|
|
1826
1826
|
authorizationGranted: false,
|
|
1827
1827
|
};
|
|
1828
1828
|
if (!apply || proposedProfilesSha256 === currentProfilesSha256) return plan;
|
|
1829
|
+
if (normalizationOnly) {
|
|
1830
|
+
return {
|
|
1831
|
+
...plan,
|
|
1832
|
+
status: "profiles_already_current",
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1829
1835
|
|
|
1830
1836
|
let runtimeRoot;
|
|
1831
1837
|
let receiptRoot;
|
|
@@ -15,10 +15,18 @@ const MAX_CORE_TOTAL_BYTES = 67_108_864;
|
|
|
15
15
|
const PACKAGE_NAME = "owlrunkit";
|
|
16
16
|
const OFFICIAL_CLI_ENTRYPOINT =
|
|
17
17
|
"scripts/runkit-contract/runkit-bootstrap.mjs";
|
|
18
|
-
const SELF_NORMALIZED_QUICK_CORE_VERSIONS = new Set([
|
|
18
|
+
const SELF_NORMALIZED_QUICK_CORE_VERSIONS = new Set([
|
|
19
|
+
"0.19.2",
|
|
20
|
+
"0.20.0",
|
|
21
|
+
"0.20.1",
|
|
22
|
+
"0.21.0",
|
|
23
|
+
]);
|
|
19
24
|
const EXACT_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/;
|
|
20
25
|
const SHA256_REF = /^sha256:[a-f0-9]{64}$/;
|
|
21
26
|
const TRUSTED_PRIOR_CORE_IDENTITIES = new Map([
|
|
27
|
+
["0.20.0", new Set([
|
|
28
|
+
"sha256:30098aa9344c17c1ed0b5ed45ef1c590b3214b824402f584029c1ecb38ca7a70",
|
|
29
|
+
])],
|
|
22
30
|
["0.19.2", new Set([
|
|
23
31
|
"sha256:c46ae9d8ed0572e5636ab5725f922f8db3ee5bf0f966b200bce7b2287c9267c8",
|
|
24
32
|
])],
|
|
@@ -22,12 +22,13 @@ const INVALID_ATTESTATION_ISSUES = new Set([
|
|
|
22
22
|
"attestation_material_missing",
|
|
23
23
|
"receipt_material_hash_mismatch",
|
|
24
24
|
]);
|
|
25
|
-
const
|
|
25
|
+
const SUCCESSOR_MUTATION_ISSUES = new Set([
|
|
26
26
|
"source_mutated_during_verification",
|
|
27
27
|
"bound_ignored_path_mutated_during_verification",
|
|
28
28
|
"dependency_environment_mutated_during_verification",
|
|
29
29
|
"consumer_source_mutated_during_verification",
|
|
30
30
|
"quick_isolation_cleanup_failed",
|
|
31
|
+
"foreign_workspace_mutated_during_verification",
|
|
31
32
|
]);
|
|
32
33
|
|
|
33
34
|
function readHistoricalReceipt(receiptPath) {
|
|
@@ -38,11 +39,14 @@ function readHistoricalReceipt(receiptPath) {
|
|
|
38
39
|
&& quickSnapshotFingerprintValid(receipt.workspaceAfter);
|
|
39
40
|
const sourceChanged = receipt.workspaceBefore.sourceFingerprint
|
|
40
41
|
!== receipt.workspaceAfter.sourceFingerprint;
|
|
41
|
-
const
|
|
42
|
+
const successorReceipt = [
|
|
43
|
+
"OwlCodaQuickVerificationReceiptV3",
|
|
44
|
+
"OwlCodaQuickVerificationReceiptV4",
|
|
45
|
+
].includes(receipt.schemaVersion);
|
|
42
46
|
const mutationBindingValid = receipt.mutationDecision === "source_unchanged"
|
|
43
|
-
? !sourceChanged && !receipt.issueCodes.some(issue =>
|
|
44
|
-
:
|
|
45
|
-
? receipt.issueCodes.some(issue =>
|
|
47
|
+
? !sourceChanged && !receipt.issueCodes.some(issue => SUCCESSOR_MUTATION_ISSUES.has(issue))
|
|
48
|
+
: successorReceipt
|
|
49
|
+
? receipt.issueCodes.some(issue => SUCCESSOR_MUTATION_ISSUES.has(issue))
|
|
46
50
|
: sourceChanged && receipt.issueCodes.includes("source_mutated_during_verification");
|
|
47
51
|
if (!snapshotsValid || !mutationBindingValid) {
|
|
48
52
|
throw new Error("quick_receipt_source_binding_invalid");
|