owlrunkit 0.16.0 → 0.16.1

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.
@@ -18,6 +18,9 @@ const OFFICIAL_CLI_ENTRYPOINT =
18
18
  const EXACT_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/;
19
19
  const SHA256_REF = /^sha256:[a-f0-9]{64}$/;
20
20
  const TRUSTED_PRIOR_CORE_IDENTITIES = new Map([
21
+ ["0.16.0", new Set([
22
+ "sha256:320fb1d97b4459d1a14b0b67807dcf2bc6b03970492cb9fb2c6245b17912c81e",
23
+ ])],
21
24
  ["0.15.1", new Set([
22
25
  "sha256:e8ca57522a8e473da356ceb3768bb650267894638d450d5e49463ab6f51c752b",
23
26
  ])],
@@ -140,7 +140,40 @@ function allowedKeys(value, expected) {
140
140
  return Object.keys(value).every(key => expected.includes(key));
141
141
  }
142
142
 
143
- function inspectLeases(root, executionRoot, runId, contract) {
143
+ function validateHistoricalLeaseOwnedPaths(paths, contract) {
144
+ try {
145
+ return contract.validateLeaseOwnedPaths(paths);
146
+ } catch {
147
+ if (!Array.isArray(paths) || paths.length === 0) throw new Error("invalid");
148
+ const normalized = [...new Set(paths.map(value => {
149
+ if (
150
+ typeof value !== "string"
151
+ || value.length === 0
152
+ || path.isAbsolute(value)
153
+ || path.win32.isAbsolute(value)
154
+ || value.includes("\\")
155
+ ) throw new Error("invalid");
156
+ const segments = value.split("/");
157
+ if (segments.some(segment => (
158
+ segment.length === 0 || segment === "." || segment === ".."
159
+ ))) throw new Error("invalid");
160
+ if (
161
+ value.startsWith(`${contract.runtimeRoot}/`)
162
+ && value !== `${contract.runtimeRoot}/profiles.json`
163
+ ) throw new Error("invalid");
164
+ return value;
165
+ }))].sort(compareCodeUnits);
166
+ return normalized;
167
+ }
168
+ }
169
+
170
+ function inspectLeases(
171
+ root,
172
+ executionRoot,
173
+ runId,
174
+ contract,
175
+ { historicalAccepted = false, expectedReleasedLeaseIds = null } = {},
176
+ ) {
144
177
  const leasesRoot = path.join(executionRoot, "leases");
145
178
  if (!hasFilesystemEntry(leasesRoot)) {
146
179
  return {
@@ -200,7 +233,9 @@ function inspectLeases(root, executionRoot, runId, contract) {
200
233
  issues.push(`Lease attempt is invalid: ${runId}/${entry.name}`);
201
234
  }
202
235
  try {
203
- const ownedPaths = contract.validateLeaseOwnedPaths(lease.ownedPaths);
236
+ const ownedPaths = historicalAccepted
237
+ ? validateHistoricalLeaseOwnedPaths(lease.ownedPaths, contract)
238
+ : contract.validateLeaseOwnedPaths(lease.ownedPaths);
204
239
  if (ownedPaths.some(ownedPath => (
205
240
  ownedPath.includes("*")
206
241
  && (!ownedPath.endsWith("/**") || ownedPath.slice(0, -3).includes("*"))
@@ -232,6 +267,14 @@ function inspectLeases(root, executionRoot, runId, contract) {
232
267
  .map(lease => lease.workItemId)
233
268
  .filter(workItemId => typeof workItemId === "string")
234
269
  .sort(compareCodeUnits);
270
+ if (
271
+ historicalAccepted
272
+ && Array.isArray(expectedReleasedLeaseIds)
273
+ && JSON.stringify(releasedWorkItemIds)
274
+ !== JSON.stringify([...expectedReleasedLeaseIds].sort(compareCodeUnits))
275
+ ) {
276
+ issues.push(`Historical accepted released lease binding mismatch: ${runId}`);
277
+ }
235
278
  return {
236
279
  status: issues.length > 0
237
280
  ? "invalid"
@@ -337,6 +380,11 @@ function inspectCloseout(root, executionRoot, runId, pin, contract) {
337
380
  }
338
381
  : {}),
339
382
  core: issues.length === 0 ? closeout.artifact.core : null,
383
+ releasedLeaseIds: issues.length === 0
384
+ && payload.decision === "accepted"
385
+ && Array.isArray(payload.verification?.releasedLeaseIds)
386
+ ? [...payload.verification.releasedLeaseIds]
387
+ : null,
340
388
  issues,
341
389
  };
342
390
  }
@@ -746,7 +794,18 @@ export function parseProjectControlState({
746
794
  && contract.validateExecutionPin({ expected: pin, actual: currentCore }).status !== "valid";
747
795
  const preserveHistoricalLeases = lifecycle === "closed"
748
796
  && new Set(["blocked", "rejected"]).has(closeout.decision);
749
- const inspectedLease = inspectLeases(root, executionRoot, runId, contract);
797
+ const inspectedLease = inspectLeases(
798
+ root,
799
+ executionRoot,
800
+ runId,
801
+ contract,
802
+ {
803
+ historicalAccepted: historical
804
+ && lifecycle === "closed"
805
+ && closeout.decision === "accepted",
806
+ expectedReleasedLeaseIds: closeout.releasedLeaseIds,
807
+ },
808
+ );
750
809
  const lease = preserveHistoricalLeases && inspectedLease.status !== "invalid"
751
810
  ? {
752
811
  ...inspectedLease,
@@ -93,7 +93,10 @@ import {
93
93
  } from "./profile-onboarding.mjs";
94
94
  import {
95
95
  discoverFleet,
96
+ inspectFleetRegistry,
96
97
  registerFleetCoverageRoot,
98
+ replaceFleetRegistry,
99
+ rollbackFleetRegistry,
97
100
  } from "./fleet-discovery.mjs";
98
101
  import { routeRunKitAssuranceV1 } from "./assurance-router.mjs";
99
102
  import { deriveHumanStatusFromInspectV1 } from "./human-status.mjs";
@@ -162,9 +165,10 @@ Two-stage deployment
162
165
  owlrunkit deployment execute --workspace . [--resume] --prepare <receipt> --owner-decision <decision-v1.json> --owner-authority <signed-v2.json> --manifest <remote.json>
163
166
 
164
167
  Fleet and status
165
- owlrunkit fleet register-root --fleet-root <directory>
166
- owlrunkit fleet discover
167
- owlrunkit status --workspace .
168
+ owlrunkit fleet <register-root|inspect-registry> [options]
169
+ owlrunkit fleet replace-registry --request <file> --receipt <file> [--dry-run]
170
+ owlrunkit fleet rollback-registry --receipt <file> --rollback-receipt <file>
171
+ owlrunkit fleet discover; owlrunkit status --workspace .
168
172
 
169
173
  Core successor
170
174
  owlrunkit core-successor <plan|apply|resume> --workspace . [...]
@@ -193,12 +197,33 @@ Required:
193
197
  `,
194
198
  fleet: `Usage:
195
199
  owlrunkit fleet register-root --fleet-root <directory>
200
+ owlrunkit fleet inspect-registry [--registry <file>]
201
+ owlrunkit fleet replace-registry --request <file> --receipt <file> [--registry <file>] [--dry-run]
202
+ owlrunkit fleet rollback-registry --receipt <file> --rollback-receipt <file> [--registry <file>]
196
203
  owlrunkit fleet discover [--fleet-root <directory>] [--fleet-manifest <file>]
197
204
  `,
198
205
  "fleet register-root": `Usage:
199
206
  owlrunkit fleet register-root --fleet-root <directory>
200
207
 
201
208
  Registers one durable fleet coverage root for later no-argument discovery.
209
+ `,
210
+ "fleet inspect-registry": `Usage:
211
+ owlrunkit fleet inspect-registry [--registry <file>]
212
+
213
+ Reads the exact registry bytes, hashes, roots, and membership without mutation.
214
+ `,
215
+ "fleet replace-registry": `Usage:
216
+ owlrunkit fleet replace-registry --request <file> --receipt <file>
217
+ [--registry <file>] [--dry-run]
218
+
219
+ Atomically replaces a registry from an exact preimage and evidence-bound fleet
220
+ membership. Coverage reduction requires explicit exclusion evidence.
221
+ `,
222
+ "fleet rollback-registry": `Usage:
223
+ owlrunkit fleet rollback-registry --receipt <replacement-receipt.json>
224
+ --rollback-receipt <file> [--registry <file>]
225
+
226
+ Restores the exact preimage recorded by a replacement receipt.
202
227
  `,
203
228
  "fleet discover": `Usage:
204
229
  owlrunkit fleet discover [--fleet-root <directory>] [--fleet-manifest <file>]
@@ -1602,6 +1627,8 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1602
1627
  ? ["json"]
1603
1628
  : command === "profiles"
1604
1629
  ? ["json", "dry-run", "apply"]
1630
+ : command === "fleet" && action === "replace-registry"
1631
+ ? ["dry-run"]
1605
1632
  : command === "candidate"
1606
1633
  ? ["delivery-v1"]
1607
1634
  : command === "core-successor" && action === "resume"
@@ -1651,19 +1678,50 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1651
1678
  if (action === "register-root") {
1652
1679
  const registered = await registerFleetCoverageRoot({
1653
1680
  fleetRoot: requireOption(options, "fleet-root"),
1681
+ fleetRegistryPath: options.registry,
1654
1682
  });
1655
1683
  return {
1656
1684
  ...registered,
1657
1685
  exitCode: 0,
1658
1686
  };
1659
1687
  }
1688
+ if (action === "inspect-registry") {
1689
+ return {
1690
+ ...await inspectFleetRegistry({
1691
+ fleetRegistryPath: options.registry,
1692
+ }),
1693
+ exitCode: 0,
1694
+ };
1695
+ }
1696
+ if (action === "replace-registry") {
1697
+ return {
1698
+ ...await replaceFleetRegistry({
1699
+ replacementRequestPath: requireOption(options, "request"),
1700
+ receiptPath: options.receipt,
1701
+ dryRun: options["dry-run"] === true,
1702
+ fleetRegistryPath: options.registry,
1703
+ }),
1704
+ exitCode: 0,
1705
+ };
1706
+ }
1707
+ if (action === "rollback-registry") {
1708
+ return {
1709
+ ...await rollbackFleetRegistry({
1710
+ replacementReceiptPath: requireOption(options, "receipt"),
1711
+ rollbackReceiptPath: requireOption(options, "rollback-receipt"),
1712
+ fleetRegistryPath: options.registry,
1713
+ }),
1714
+ exitCode: 0,
1715
+ };
1716
+ }
1660
1717
  if (action !== "discover") {
1661
- throw new Error("Usage: owlrunkit fleet <register-root|discover> [--fleet-root <directory> | --fleet-manifest <file> | --workspace-root <directory>]");
1718
+ throw new Error("Usage: owlrunkit fleet <register-root|inspect-registry|replace-registry|rollback-registry|discover>");
1662
1719
  }
1663
1720
  const discovered = await discoverFleet({
1664
1721
  fleetRoots: options["fleet-root"] ?? null,
1665
1722
  fleetManifestPath: options["fleet-manifest"] ?? null,
1666
1723
  workspaceRoots: options["workspace-root"] ?? null,
1724
+ fleetRegistryPath: options.registry ?? null,
1667
1725
  });
1668
1726
  return {
1669
1727
  ...discovered,
@@ -97,7 +97,7 @@
97
97
  "discovery": {
98
98
  "type": "object",
99
99
  "additionalProperties": false,
100
- "required": ["schemaVersion", "source", "coverageRoots", "unreachableRoots", "workspaceRoots", "complete", "frozenManifestSha256", "authorizationGranted"],
100
+ "required": ["schemaVersion", "source", "coverageRoots", "unreachableRoots", "workspaceRoots", "classifications", "issues", "complete", "frozenManifestSha256", "authorizationGranted"],
101
101
  "properties": {
102
102
  "schemaVersion": { "const": "OwlCodaRunKitFleetDiscoveryV1" },
103
103
  "source": { "type": "string", "minLength": 1 },
@@ -105,6 +105,18 @@
105
105
  "coverageRoots": { "type": "array", "items": { "type": "string" } },
106
106
  "unreachableRoots": { "type": "array", "items": { "type": "string" } },
107
107
  "workspaceRoots": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } },
108
+ "classifications": {
109
+ "type": "object",
110
+ "additionalProperties": false,
111
+ "required": ["active", "retired", "excluded", "invalid"],
112
+ "properties": {
113
+ "active": { "type": "array", "items": { "type": "string", "minLength": 1 } },
114
+ "retired": { "type": "array", "items": { "type": "string", "minLength": 1 } },
115
+ "excluded": { "type": "array", "items": { "type": "string", "minLength": 1 } },
116
+ "invalid": { "type": "array", "items": { "type": "string", "minLength": 1 } }
117
+ }
118
+ },
119
+ "issues": { "type": "array", "maxItems": 0 },
108
120
  "complete": { "const": true },
109
121
  "frozenManifestSha256": { "$ref": "#/$defs/hash" },
110
122
  "authorizationGranted": { "const": false }
@@ -146,7 +158,7 @@
146
158
  "materializationProof": { "candidateSha256": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "payloadSha256": "sha256:3333333333333333333333333333333333333333333333333333333333333333", "materializedCore": { "contractVersion": "0.2", "coreVersion": "0.16.0", "coreManifestSha256": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "coreSourceRef": "artifact:sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }, "matchesToCore": true }
147
159
  },
148
160
  "fleetDiscoveryRequest": { "fleetRoots": ["/fleet"] },
149
- "fleetDiscovery": { "schemaVersion": "OwlCodaRunKitFleetDiscoveryV1", "source": "fleet_roots", "coverageRoots": ["/fleet"], "unreachableRoots": [], "workspaceRoots": ["/fleet/project"], "complete": true, "frozenManifestSha256": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "authorizationGranted": false },
161
+ "fleetDiscovery": { "schemaVersion": "OwlCodaRunKitFleetDiscoveryV1", "source": "fleet_roots", "coverageRoots": ["/fleet"], "unreachableRoots": [], "workspaceRoots": ["/fleet/project"], "classifications": { "active": ["/fleet/project"], "retired": [], "excluded": [], "invalid": [] }, "issues": [], "complete": true, "frozenManifestSha256": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "authorizationGranted": false },
150
162
  "migrationContract": { "completeFleetRequired": true, "globalPreflightBeforeWrites": true, "ownerMigrationAuthorityRequired": true, "migrationScope": "project_runkit_config_and_local_migration_receipt_only", "projectOrder": "canonical_workspace_root" },
151
163
  "repositoryActions": { "stage": false, "commit": false, "push": false, "publish": false, "deploy": false },
152
164
  "authorizationGranted": false,
@@ -4,16 +4,40 @@
4
4
  "title": "OwlCoda RunKit Fleet Discovery V1",
5
5
  "type": "object",
6
6
  "additionalProperties": false,
7
- "required": ["schemaVersion", "source", "coverageRoots", "unreachableRoots", "workspaceRoots", "complete", "frozenManifestSha256", "authorizationGranted"],
7
+ "required": ["schemaVersion", "source", "coverageRoots", "unreachableRoots", "workspaceRoots", "classifications", "issues", "complete", "frozenManifestSha256", "authorizationGranted"],
8
8
  "properties": {
9
9
  "schemaVersion": { "const": "OwlCodaRunKitFleetDiscoveryV1" },
10
- "source": { "enum": ["fleet_registry", "fleet_roots", "fleet_manifest", "explicit_workspaces"] },
10
+ "source": { "enum": ["fleet_registry", "fleet_registry_membership", "fleet_roots", "fleet_manifest", "explicit_workspaces"] },
11
11
  "manifestPath": { "type": "string", "minLength": 1 },
12
12
  "registryPath": { "type": "string", "minLength": 1 },
13
13
  "registrySha256": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
14
14
  "coverageRoots": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
15
15
  "unreachableRoots": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
16
16
  "workspaceRoots": { "type": "array", "maxItems": 256, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
17
+ "classifications": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "required": ["active", "retired", "excluded", "invalid"],
21
+ "properties": {
22
+ "active": { "type": "array", "maxItems": 256, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
23
+ "retired": { "type": "array", "maxItems": 256, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
24
+ "excluded": { "type": "array", "maxItems": 256, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
25
+ "invalid": { "type": "array", "maxItems": 256, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
26
+ }
27
+ },
28
+ "issues": {
29
+ "type": "array",
30
+ "items": {
31
+ "type": "object",
32
+ "additionalProperties": false,
33
+ "required": ["code", "path", "coverageRoot"],
34
+ "properties": {
35
+ "code": { "type": "string", "minLength": 1 },
36
+ "path": { "type": "string", "minLength": 1 },
37
+ "coverageRoot": { "type": "string", "minLength": 1 }
38
+ }
39
+ }
40
+ },
17
41
  "complete": { "type": "boolean" },
18
42
  "frozenManifestSha256": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
19
43
  "authorizationGranted": { "const": false }
@@ -24,6 +48,13 @@
24
48
  "coverageRoots": ["/absolute/path/to/fleet"],
25
49
  "unreachableRoots": [],
26
50
  "workspaceRoots": ["/absolute/path/to/fleet/project"],
51
+ "classifications": {
52
+ "active": ["/absolute/path/to/fleet/project"],
53
+ "retired": [],
54
+ "excluded": [],
55
+ "invalid": []
56
+ },
57
+ "issues": [],
27
58
  "complete": true,
28
59
  "frozenManifestSha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
29
60
  "authorizationGranted": false
@@ -19,8 +19,13 @@ const RELEASE_FILES = Object.freeze({
19
19
  "integrations/codex/skills/owlcoda-runkit/assets/templates/config.json",
20
20
  });
21
21
 
22
+ const RELEASE_VERSION = "0.16.1";
22
23
  const ATTEST_RUNTIME_CORE016 =
23
- /(coreVersion:\s*"0\.16\.0",\s*coreManifestSha256:\s*")sha256:[a-f0-9]{64}("\s*,?)/gu;
24
+ new RegExp(
25
+ `(coreVersion:\\s*"${RELEASE_VERSION.replaceAll(".", "\\.")}",`
26
+ + `\\s*coreManifestSha256:\\s*")sha256:[a-f0-9]{64}("\\s*,?)`,
27
+ "gu",
28
+ );
24
29
 
25
30
  function readJson(ref) {
26
31
  return JSON.parse(readFileSync(ref, "utf8"));
@@ -54,7 +59,7 @@ export function synchronizeCore016ReleaseIdentityV1({
54
59
  const root = path.resolve(repositoryRoot);
55
60
  if (
56
61
  core?.contractVersion !== "0.2"
57
- || core?.coreVersion !== "0.16.0"
62
+ || core?.coreVersion !== RELEASE_VERSION
58
63
  || !/^sha256:[a-f0-9]{64}$/u.test(
59
64
  core?.coreManifestSha256 ?? "",
60
65
  )
@@ -66,12 +71,12 @@ export function synchronizeCore016ReleaseIdentityV1({
66
71
  const packageManifest = readJson(refs.packageManifest);
67
72
  if (
68
73
  packageManifest.name !== "owlrunkit"
69
- || packageManifest.version !== "0.16.0"
74
+ || packageManifest.version !== RELEASE_VERSION
70
75
  ) throw new Error("core016_release_package_invalid");
71
76
  const attestManifest = readJson(refs.attestManifest);
72
77
  const candidateIndexes = attestManifest.supportedProducerCoreIdentities
73
78
  ?.map((identity, index) => ({ identity, index }))
74
- .filter(({ identity }) => identity?.coreVersion === "0.16.0") ?? [];
79
+ .filter(({ identity }) => identity?.coreVersion === RELEASE_VERSION) ?? [];
75
80
  if (candidateIndexes.length !== 1) {
76
81
  throw new Error("core016_release_attest_candidate_ambiguous");
77
82
  }