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 +11 -0
- package/README.md +10 -3
- package/docs/architecture/OWLCODA_RUNKIT_0190_CONSOLIDATED_DAILY_USE_PRODUCT_DECISION_20260812.md +12 -9
- package/docs/architecture/OWLCODA_RUNKIT_0191_PROFILE_RECONCILE_PATCH_PRODUCT_DECISION_20260813.md +30 -0
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +6 -6
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
- 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 +5 -5
- package/sbom.spdx.json +5 -5
- package/scripts/runkit-contract/core-contract.mjs +1 -1
- package/scripts/runkit-contract/profile-onboarding.mjs +52 -33
- package/scripts/runkit-contract/project-cli-resolver.mjs +3 -0
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.
|
|
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.
|
|
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.
|
|
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
|
package/docs/architecture/OWLCODA_RUNKIT_0190_CONSOLIDATED_DAILY_USE_PRODUCT_DECISION_20260812.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OwlRunKit 0.19.0 Consolidated Daily-Use Product Decision
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
91
|
-
|
|
92
|
-
- 0.19.0
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
-
|
|
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 推导为已完成。
|
package/docs/architecture/OWLCODA_RUNKIT_0191_PROFILE_RECONCILE_PATCH_PRODUCT_DECISION_20260813.md
ADDED
|
@@ -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.
|
|
11
|
-
Core `0.19.
|
|
12
|
-
`sha256:
|
|
13
|
-
The published `owlrunkit@0.
|
|
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.
|
|
194
|
+
--exact owlrunkit@0.19.1 --dry-run
|
|
195
195
|
npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
|
|
196
|
-
--exact owlrunkit@0.19.
|
|
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.
|
|
6
|
-
"coreManifestSha256": "sha256:
|
|
7
|
-
"coreSourceRef": "artifact:sha256:
|
|
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.
|
|
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.
|
|
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.
|
|
27
|
-
"shasum": "
|
|
28
|
-
"integrity": "sha512-
|
|
29
|
-
"tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.
|
|
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.
|
|
6
|
-
"documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.19.
|
|
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.
|
|
18
|
-
"downloadLocation": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.19.
|
|
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.
|
|
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.
|
|
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
|
|
1466
|
-
|
|
1467
|
-
|
|
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
|
])],
|