owlrunkit 0.19.0 → 0.19.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.1
4
+
5
+ - Fixes profile reconciliation for mature projects where an existing profile
6
+ already owns command IDs such as `npm-build` or `npm-test`. When those
7
+ detected commands have one existing owner, reconciliation extends that owner
8
+ with the detected paths and current authoritative command definitions instead
9
+ of creating an invalid duplicate-command profile.
10
+ - Preserves create-only receipts, atomic rollback, strict profile validation,
11
+ project-local CLI binding, `authorizationGranted=false`, and the separate
12
+ fleet/shared Skill activation gate.
13
+
3
14
  ## 0.19.0
4
15
 
5
16
  - Adds `bootstrap --dry-run|--apply` as one exact-registry, project-local,
package/README.md CHANGED
@@ -45,6 +45,13 @@ transfer actions, business-layer outcome projection, and local efficiency
45
45
  metrics. These conveniences do not weaken Formal routing or grant Git,
46
46
  release, deployment, production, or business authority.
47
47
 
48
+ RunKit 0.19.1 fixes mature-project onboarding when an existing owner profile
49
+ already owns command IDs proposed by detection. Reconciliation now extends that
50
+ sole command owner with the newly detected paths and authoritative command
51
+ binding instead of creating a second profile with duplicate IDs. Existing
52
+ owner profiles, strict validation, atomic rollback, and shared-Skill activation
53
+ boundaries remain unchanged.
54
+
48
55
  The 0.18 Project Driver is a bounded surface for new projects and controlled
49
56
  dogfood. Its product name does not claim to be a general long-running,
50
57
  multi-phase, or enterprise control plane. Version 0.18 adds one bounded
@@ -59,7 +66,7 @@ separate authority boundaries.
59
66
  ## Install
60
67
 
61
68
  ```bash
62
- npm install --save-exact owlrunkit@0.19.0
69
+ npm install --save-exact owlrunkit@0.19.1
63
70
  ```
64
71
 
65
72
  Use `npx --no-install owlrunkit` for project commands. The package bootstrap
@@ -75,9 +82,9 @@ the project Config must independently bind the same Core.
75
82
  ```bash
76
83
  npx --no-install owlrunkit --version
77
84
  npx --no-install owlrunkit bootstrap --workspace /absolute/path/to/project \
78
- --exact owlrunkit@0.19.0 --dry-run
85
+ --exact owlrunkit@0.19.1 --dry-run
79
86
  npx --no-install owlrunkit bootstrap --workspace /absolute/path/to/project \
80
- --exact owlrunkit@0.19.0 --apply
87
+ --exact owlrunkit@0.19.1 --apply
81
88
  npx --no-install owlrunkit init --workspace /absolute/path/to/project
82
89
  npx --no-install owlrunkit doctor --workspace /absolute/path/to/project
83
90
  npx --no-install owlrunkit mode recommend --workspace /absolute/path/to/project
@@ -1,6 +1,6 @@
1
1
  # OwlRunKit 0.19.0 Consolidated Daily-Use Product Decision
2
2
 
3
- 状态:**Owner 已授权实施;七个 Wave 的源代码候选已完成,正式发布验证进行中**
3
+ 状态:**七个 Wave 已实现;私仓、tag、npm 与 exact-registry consumer 发布闭环已完成**
4
4
 
5
5
  ## Decision
6
6
 
@@ -87,11 +87,14 @@ acceptance 才强制 Formal。风险解除后允许降级,升级不成为粘
87
87
 
88
88
  低层证据不得自动提升为高层结论。
89
89
 
90
- ## What Cannot Be Claimed Yet
91
-
92
- - 0.19.0 尚未 tag、publish 或被任何外部项目采用;
93
- - 本文不是 npm registry receipt,源代码完成不能替代 packed consumer 与
94
- registry consumer 验证;
95
- - 当前可以声称七个 Wave 已进入单一 0.19.0 release candidate,不能声称
96
- npm latest 已改变;
97
- - public mirror、官网、8019、全局 Skill 与外部项目升级不属于本次授权。
90
+ ## Release Truth And What Cannot Be Claimed
91
+
92
+ - `owlrunkit@0.19.0` 已由私仓 release commit `830aa91c` 发布,npm
93
+ `latest` 已读回为 `0.19.0`;精确 registry consumer 已完成原子
94
+ bootstrap、doctor、profile、inspect、Quick 与 metrics 验证;
95
+ - 发布不等于 fleet/shared Skill 激活、OwlCoda 项目 Core 迁移或任何外部项目
96
+ adoption;这些仍需要各自安全边界和独立读回;
97
+ - 本文记录产品决策和已发布能力,完整 registry 字节、测试与未触碰边界见
98
+ `docs/handoff/OWLCODA_RUNKIT_0190_PRIVATE_GIT_NPM_RELEASE_RECEIPT_20260813.md`;
99
+ - public mirror、官网、8019、全局 Skill、生产与业务验收不属于本次授权,不能
100
+ 从本次 package release 推导为已完成。
@@ -0,0 +1,30 @@
1
+ # OwlRunKit 0.19.1 Profile Reconcile Patch Product Decision
2
+
3
+ 状态:**候选实现完成,发布实况以 registry 读回和发布回执为准**
4
+
5
+ ## Decision
6
+
7
+ 0.19.1 是 0.19.0 的兼容补丁,不扩展 RunKit 的产品范围。真实 OwlCoda
8
+ dogfood 发现,成熟项目已有 profile 持有 `npm-build`、`npm-test` 时,检测器
9
+ 提出新的 `node-quality` profile 会重复这些全局 command ID,使 bootstrap 在
10
+ profile reconcile 阶段失败。
11
+
12
+ 当检测出的 commands 只有一个现有 owner 时,reconcile 现在复用该 owner:
13
+ 增加真实检测到的 paths,并以项目本地 authoritative tool binding 更新对应
14
+ command。它不会新增第二份重复 command,也不会削弱最终 profile 校验。
15
+
16
+ ## Preserved Boundaries
17
+
18
+ - owner profile bytes 仍只通过原子 reconcile 事务更新,失败恢复原始 bytes;
19
+ - 多个不同 command owner 的歧义不会被静默合并;
20
+ - bootstrap、receipt 与 mode 仍不授予 Git、发布、部署、生产或业务权限;
21
+ - npm package 发布、项目 Core adoption 与 process-level shared Skill 激活仍是
22
+ 三个独立状态转换;bootstrap 只诊断 Skill drift,不静默刷新 fleet Skill;
23
+ - 0.19.0 的 continuity、assurance、Formal 和 predecessor-contract 边界不变。
24
+
25
+ ## Evidence And Claims
26
+
27
+ 发布前必须通过成熟项目冲突回归、profile/bootstrap 聚焦测试、完整 RunKit
28
+ gate、Core identity、packed package/Skill、干净 consumer 和 npm registry
29
+ 字节读回。本文不能在这些 Gate 完成前声称 0.19.1 已发布,也不能把一份
30
+ package receipt 冒充 shared Skill 已激活或其他项目已推广。
@@ -7,10 +7,10 @@ description: Run receipt-backed, project-owned work with OwlCoda RunKit. Use whe
7
7
 
8
8
  Use the bundled deterministic Core to coordinate work through project artifacts rather than chat memory. Require Node.js 20 or later.
9
9
 
10
- Bundled release: standalone `owlrunkit@0.19.0`, bundling Contract `0.2` and
11
- Core `0.19.0` with manifest
12
- `sha256:803fb7de76a6ccffd1ec5e0164eeff15a580209fa6dfbef9e561345ab616b403`.
13
- The published `owlrunkit@0.18.4` package is the trusted prior for rollback;
10
+ Bundled release: standalone `owlrunkit@0.19.1`, bundling Contract `0.2` and
11
+ Core `0.19.1` with manifest
12
+ `sha256:291ef97c93a513eed24a29f75c400b61cefd6a8c0ab228401cf2c6a73ea9e622`.
13
+ The published `owlrunkit@0.19.0` package is the trusted prior for rollback;
14
14
  verify exact official npm registry provenance before adoption. The immutable
15
15
  rollback baseline for the prior release is `owlrunkit@0.16.1` with SHA-1
16
16
  `1bc119d24879bdd8959af16b364af55ca9d61ea9` and canonical npm tarball URL
@@ -191,9 +191,9 @@ below has no CLI entry.
191
191
 
192
192
  ```bash
193
193
  npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
194
- --exact owlrunkit@0.19.0 --dry-run
194
+ --exact owlrunkit@0.19.1 --dry-run
195
195
  npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
196
- --exact owlrunkit@0.19.0 --apply
196
+ --exact owlrunkit@0.19.1 --apply
197
197
  npx --no-install owlrunkit init --workspace "$PROJECT_ROOT"
198
198
  npx --no-install owlrunkit inspect --json --workspace "$PROJECT_ROOT"
199
199
  npx --no-install owlrunkit status --workspace "$PROJECT_ROOT"
@@ -2,9 +2,9 @@
2
2
  "schemaVersion": "OwlCodaRunKitConfigV2",
3
3
  "core": {
4
4
  "contractVersion": "0.2",
5
- "coreVersion": "0.19.0",
6
- "coreManifestSha256": "sha256:803fb7de76a6ccffd1ec5e0164eeff15a580209fa6dfbef9e561345ab616b403",
7
- "coreSourceRef": "artifact:sha256:803fb7de76a6ccffd1ec5e0164eeff15a580209fa6dfbef9e561345ab616b403"
5
+ "coreVersion": "0.19.1",
6
+ "coreManifestSha256": "sha256:291ef97c93a513eed24a29f75c400b61cefd6a8c0ab228401cf2c6a73ea9e622",
7
+ "coreSourceRef": "artifact:sha256:291ef97c93a513eed24a29f75c400b61cefd6a8c0ab228401cf2c6a73ea9e622"
8
8
  },
9
9
  "authorizationPolicy": "external_explicit_authority_required"
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "owlrunkit",
3
- "version": "0.19.0",
3
+ "version": "0.19.1",
4
4
  "description": "Project Driver for cross-Agent project continuity and progression; execution, evidence, verification, and recovery are the underlying trust substrate.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "yeemio <owlclaw@163.com>",
@@ -39,6 +39,11 @@
39
39
  "sha256": "sha256:3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986"
40
40
  },
41
41
  "supportedProducerCoreIdentities": [
42
+ {
43
+ "contractVersion": "0.2",
44
+ "coreVersion": "0.19.1",
45
+ "coreManifestSha256": "sha256:291ef97c93a513eed24a29f75c400b61cefd6a8c0ab228401cf2c6a73ea9e622"
46
+ },
42
47
  {
43
48
  "contractVersion": "0.2",
44
49
  "coreVersion": "0.19.0",
@@ -19,6 +19,11 @@ import { captureWorkspaceSnapshot } from "./workspace-snapshot.mjs";
19
19
  export { validQuickReceiptShape } from "./quick-receipt-contract.mjs";
20
20
 
21
21
  export const SUPPORTED_QUICK_CORE_IDENTITIES = Object.freeze([
22
+ {
23
+ contractVersion: "0.2",
24
+ coreVersion: "0.19.1",
25
+ coreManifestSha256: "sha256:291ef97c93a513eed24a29f75c400b61cefd6a8c0ab228401cf2c6a73ea9e622",
26
+ },
22
27
  {
23
28
  contractVersion: "0.2",
24
29
  coreVersion: "0.19.0",
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": "OwlCodaRunKitRegistryReleasePolicyV1",
3
3
  "status": "release_candidate_unpublished",
4
4
  "packageName": "owlrunkit",
5
- "candidateVersion": "0.19.0",
5
+ "candidateVersion": "0.19.1",
6
6
  "registry": "https://registry.npmjs.org",
7
7
  "registryRequiredBeforeAdoption": true,
8
8
  "exactVersionRequired": true,
@@ -23,10 +23,10 @@
23
23
  ],
24
24
  "currentPublishedRelease": {
25
25
  "packageName": "owlrunkit",
26
- "version": "0.18.4",
27
- "shasum": "8f2ef01da287b76b545eeebd6973bc40449dd302",
28
- "integrity": "sha512-L3cFuJnU39p/EhgrRaJbEIB7gTRFxKzEpNmANw3kwNFrTe9Fe8wtwgdFOBXldX6xCJY+W44/8cw4P/dtAxiCAA==",
29
- "tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.18.4.tgz"
26
+ "version": "0.19.0",
27
+ "shasum": "83d156554924e2e1c58d972e1c7d31262bddb186",
28
+ "integrity": "sha512-edtzE58ShWEM4C0IpHJQiu2h0kKBSprU+LjaZNsXTXObeVZlGuAxZXkD7Jn6chMk3mpCidOf4VtA1/an+EZNWw==",
29
+ "tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.19.0.tgz"
30
30
  },
31
31
  "registryRelease": null,
32
32
  "registryEvidenceMustBeExternal": true,
package/sbom.spdx.json CHANGED
@@ -2,8 +2,8 @@
2
2
  "spdxVersion": "SPDX-2.3",
3
3
  "dataLicense": "CC0-1.0",
4
4
  "SPDXID": "SPDXRef-DOCUMENT",
5
- "name": "owlrunkit-0.19.0",
6
- "documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.19.0",
5
+ "name": "owlrunkit-0.19.1",
6
+ "documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.19.1",
7
7
  "creationInfo": {
8
8
  "created": "2026-07-29T00:00:00Z",
9
9
  "creators": [
@@ -14,8 +14,8 @@
14
14
  {
15
15
  "name": "owlrunkit",
16
16
  "SPDXID": "SPDXRef-Package-OwlRunKit",
17
- "versionInfo": "0.19.0",
18
- "downloadLocation": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.19.0.tgz",
17
+ "versionInfo": "0.19.1",
18
+ "downloadLocation": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.19.1.tgz",
19
19
  "filesAnalyzed": false,
20
20
  "licenseConcluded": "GPL-3.0-or-later",
21
21
  "licenseDeclared": "GPL-3.0-or-later",
@@ -24,7 +24,7 @@
24
24
  {
25
25
  "referenceCategory": "PACKAGE-MANAGER",
26
26
  "referenceType": "purl",
27
- "referenceLocator": "pkg:npm/owlrunkit@0.19.0"
27
+ "referenceLocator": "pkg:npm/owlrunkit@0.19.1"
28
28
  }
29
29
  ]
30
30
  }
@@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url";
14
14
  import { parseProjectControlState } from "./project-control-parser.mjs";
15
15
 
16
16
  export const CONTRACT_VERSION = "0.2";
17
- export const CORE_VERSION = "0.19.0";
17
+ export const CORE_VERSION = "0.19.1";
18
18
  export const RUNTIME_ROOT = ".owlcoda/runkit";
19
19
 
20
20
  const CORE_FILES = [
@@ -1440,9 +1440,47 @@ export function applyDetectedProfilesV3(input = {}) {
1440
1440
  });
1441
1441
  }
1442
1442
 
1443
+ function mergeDetectedProfileDefinition(current, detected) {
1444
+ current.commands ??= [];
1445
+ const addedPaths = detected.paths
1446
+ .filter((value) => !current.paths.includes(value))
1447
+ .sort();
1448
+ current.paths = [...new Set([...current.paths, ...detected.paths])].sort();
1449
+ const commands = new Map(current.commands.map((entry) => [entry.id, entry]));
1450
+ const addedCommandIds = [];
1451
+ const updatedCommandIds = [];
1452
+ for (const detectedCommand of detected.commands) {
1453
+ const currentCommand = commands.get(detectedCommand.id);
1454
+ if (!currentCommand) {
1455
+ current.commands.push(structuredClone(detectedCommand));
1456
+ commands.set(detectedCommand.id, detectedCommand);
1457
+ addedCommandIds.push(detectedCommand.id);
1458
+ } else if (canonicalJson(currentCommand) !== canonicalJson(detectedCommand)) {
1459
+ const index = current.commands.findIndex((entry) => entry.id === detectedCommand.id);
1460
+ current.commands[index] = structuredClone(detectedCommand);
1461
+ commands.set(detectedCommand.id, detectedCommand);
1462
+ updatedCommandIds.push(detectedCommand.id);
1463
+ }
1464
+ }
1465
+ current.commands.sort((left, right) => left.id.localeCompare(right.id));
1466
+ if (
1467
+ addedPaths.length === 0
1468
+ && addedCommandIds.length === 0
1469
+ && updatedCommandIds.length === 0
1470
+ ) return null;
1471
+ return {
1472
+ profileId: current.id,
1473
+ addedPaths,
1474
+ addedCommandIds: addedCommandIds.sort(),
1475
+ updatedCommandIds: updatedCommandIds.sort(),
1476
+ };
1477
+ }
1478
+
1443
1479
  function mergeDetectedProfiles(currentProfiles, detectedProfiles) {
1444
1480
  const profiles = currentProfiles.profiles.map((profile) => structuredClone(profile));
1445
1481
  const byId = new Map(profiles.map((profile) => [profile.id, profile]));
1482
+ const commandOwners = new Map(profiles.flatMap((profile) =>
1483
+ (profile.commands ?? []).map((entry) => [entry.id, profile.id])));
1446
1484
  const addedProfileIds = [];
1447
1485
  const updatedProfiles = [];
1448
1486
  for (const detected of [...detectedProfiles.profiles]
@@ -1456,45 +1494,26 @@ function mergeDetectedProfiles(currentProfiles, detectedProfiles) {
1456
1494
  const primaryCoverageComplete = impact.uncoveredPaths.length === 0
1457
1495
  && !impact.warnings.some((warning) => warning.startsWith("supporting_only_match:"));
1458
1496
  if (primaryCoverageComplete) continue;
1497
+ const existingCommandOwnerIds = [...new Set(detected.commands
1498
+ .map((command) => commandOwners.get(command.id))
1499
+ .filter(Boolean))];
1500
+ if (existingCommandOwnerIds.length === 1) {
1501
+ const owner = byId.get(existingCommandOwnerIds[0]);
1502
+ const update = mergeDetectedProfileDefinition(owner, detected);
1503
+ if (update !== null) updatedProfiles.push(update);
1504
+ for (const command of owner.commands) commandOwners.set(command.id, owner.id);
1505
+ continue;
1506
+ }
1459
1507
  const added = { ...structuredClone(detected), primary: false };
1460
1508
  profiles.push(added);
1461
1509
  byId.set(added.id, added);
1510
+ for (const command of added.commands) commandOwners.set(command.id, added.id);
1462
1511
  addedProfileIds.push(added.id);
1463
1512
  continue;
1464
1513
  }
1465
- const addedPaths = detected.paths
1466
- .filter((value) => !current.paths.includes(value))
1467
- .sort();
1468
- current.paths = [...new Set([...current.paths, ...detected.paths])].sort();
1469
- const commands = new Map(current.commands.map((entry) => [entry.id, entry]));
1470
- const addedCommandIds = [];
1471
- const updatedCommandIds = [];
1472
- for (const detectedCommand of detected.commands) {
1473
- const currentCommand = commands.get(detectedCommand.id);
1474
- if (!currentCommand) {
1475
- current.commands.push(structuredClone(detectedCommand));
1476
- commands.set(detectedCommand.id, detectedCommand);
1477
- addedCommandIds.push(detectedCommand.id);
1478
- } else if (canonicalJson(currentCommand) !== canonicalJson(detectedCommand)) {
1479
- const index = current.commands.findIndex((entry) => entry.id === detectedCommand.id);
1480
- current.commands[index] = structuredClone(detectedCommand);
1481
- commands.set(detectedCommand.id, detectedCommand);
1482
- updatedCommandIds.push(detectedCommand.id);
1483
- }
1484
- }
1485
- current.commands.sort((left, right) => left.id.localeCompare(right.id));
1486
- if (
1487
- addedPaths.length > 0
1488
- || addedCommandIds.length > 0
1489
- || updatedCommandIds.length > 0
1490
- ) {
1491
- updatedProfiles.push({
1492
- profileId: current.id,
1493
- addedPaths,
1494
- addedCommandIds: addedCommandIds.sort(),
1495
- updatedCommandIds: updatedCommandIds.sort(),
1496
- });
1497
- }
1514
+ const update = mergeDetectedProfileDefinition(current, detected);
1515
+ if (update !== null) updatedProfiles.push(update);
1516
+ for (const command of current.commands) commandOwners.set(command.id, current.id);
1498
1517
  }
1499
1518
  return {
1500
1519
  proposedProfiles: {
@@ -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.19.0", new Set([
22
+ "sha256:803fb7de76a6ccffd1ec5e0164eeff15a580209fa6dfbef9e561345ab616b403",
23
+ ])],
21
24
  ["0.18.4", new Set([
22
25
  "sha256:372d4c247e4b40b0fd2f3fe0f5bf928548095bfb7e2e92e9ac66790e2717f77d",
23
26
  ])],