@acidicsoil/portable-capabilities 0.1.8 → 0.1.10
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 +12 -0
- package/README.md +1 -0
- package/dist-release/cli.js +515 -309
- package/dist-release/cli.js.map +4 -4
- package/dist-release/index.js +522 -256
- package/dist-release/index.js.map +4 -4
- package/package.json +33 -25
- package/schemas/runtime-descriptor.schema.json +6 -0
package/dist-release/cli.js
CHANGED
|
@@ -3594,10 +3594,81 @@ import { parse } from "yaml";
|
|
|
3594
3594
|
import { parseDocument } from "yaml";
|
|
3595
3595
|
|
|
3596
3596
|
// packages/compiler/src/evidence/runtime-claims.ts
|
|
3597
|
+
function parseVersion(value) {
|
|
3598
|
+
const match = value.match(/(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/u);
|
|
3599
|
+
if (!match) return void 0;
|
|
3600
|
+
return {
|
|
3601
|
+
major: Number(match[1]),
|
|
3602
|
+
minor: Number(match[2]),
|
|
3603
|
+
patch: Number(match[3]),
|
|
3604
|
+
prerelease: match[4] ? match[4].split(".").map((part) => /^\d+$/u.test(part) ? Number(part) : part) : []
|
|
3605
|
+
};
|
|
3606
|
+
}
|
|
3607
|
+
function compareVersions(left, right) {
|
|
3608
|
+
for (const key of ["major", "minor", "patch"]) {
|
|
3609
|
+
if (left[key] !== right[key]) return left[key] > right[key] ? 1 : -1;
|
|
3610
|
+
}
|
|
3611
|
+
if (left.prerelease.length === 0 && right.prerelease.length === 0) return 0;
|
|
3612
|
+
if (left.prerelease.length === 0) return 1;
|
|
3613
|
+
if (right.prerelease.length === 0) return -1;
|
|
3614
|
+
for (let index = 0; index < Math.max(left.prerelease.length, right.prerelease.length); index += 1) {
|
|
3615
|
+
const leftPart = left.prerelease[index];
|
|
3616
|
+
const rightPart = right.prerelease[index];
|
|
3617
|
+
if (leftPart === void 0) return -1;
|
|
3618
|
+
if (rightPart === void 0) return 1;
|
|
3619
|
+
if (leftPart === rightPart) continue;
|
|
3620
|
+
if (typeof leftPart === "number" && typeof rightPart === "string") return -1;
|
|
3621
|
+
if (typeof leftPart === "string" && typeof rightPart === "number") return 1;
|
|
3622
|
+
return leftPart > rightPart ? 1 : -1;
|
|
3623
|
+
}
|
|
3624
|
+
return 0;
|
|
3625
|
+
}
|
|
3626
|
+
function caretUpperBound(version) {
|
|
3627
|
+
if (version.major > 0) return { major: version.major + 1, minor: 0, patch: 0, prerelease: [] };
|
|
3628
|
+
if (version.minor > 0) return { major: 0, minor: version.minor + 1, patch: 0, prerelease: [] };
|
|
3629
|
+
return { major: 0, minor: 0, patch: version.patch + 1, prerelease: [] };
|
|
3630
|
+
}
|
|
3631
|
+
function tildeUpperBound(version) {
|
|
3632
|
+
return { major: version.major, minor: version.minor + 1, patch: 0, prerelease: [] };
|
|
3633
|
+
}
|
|
3634
|
+
function matchesConstraint(actual, operator, expected) {
|
|
3635
|
+
if (actual.prerelease.length > 0 && expected.prerelease.length === 0) return false;
|
|
3636
|
+
const comparison = compareVersions(actual, expected);
|
|
3637
|
+
switch (operator ?? "=") {
|
|
3638
|
+
case ">=":
|
|
3639
|
+
return comparison >= 0;
|
|
3640
|
+
case "<=":
|
|
3641
|
+
return comparison <= 0;
|
|
3642
|
+
case ">":
|
|
3643
|
+
return comparison > 0;
|
|
3644
|
+
case "<":
|
|
3645
|
+
return comparison < 0;
|
|
3646
|
+
case "^":
|
|
3647
|
+
return comparison >= 0 && compareVersions(actual, caretUpperBound(expected)) < 0;
|
|
3648
|
+
case "~":
|
|
3649
|
+
return comparison >= 0 && compareVersions(actual, tildeUpperBound(expected)) < 0;
|
|
3650
|
+
default:
|
|
3651
|
+
return comparison === 0;
|
|
3652
|
+
}
|
|
3653
|
+
}
|
|
3654
|
+
function isRuntimeVersionInRange(range, runtimeVersion) {
|
|
3655
|
+
const normalizedRange = range.trim();
|
|
3656
|
+
if (normalizedRange === "*") return true;
|
|
3657
|
+
const actual = parseVersion(runtimeVersion);
|
|
3658
|
+
if (!actual) return false;
|
|
3659
|
+
const expression = normalizedRange.includes(";") ? normalizedRange.slice(normalizedRange.lastIndexOf(";") + 1).trim() : normalizedRange;
|
|
3660
|
+
const constraints = expression.split(/\s+/u).map((token) => {
|
|
3661
|
+
const match = token.match(/^(>=|<=|>|<|=|\^|~)?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/u);
|
|
3662
|
+
if (!match || !match[2]) return void 0;
|
|
3663
|
+
const version = parseVersion(match[2]);
|
|
3664
|
+
return version ? { operator: match[1], version } : void 0;
|
|
3665
|
+
});
|
|
3666
|
+
return constraints.length > 0 && constraints.every(
|
|
3667
|
+
(constraint) => constraint?.version && matchesConstraint(actual, constraint.operator, constraint.version)
|
|
3668
|
+
);
|
|
3669
|
+
}
|
|
3597
3670
|
function resolveRuntimeEvidence(claim4, runtimeVersion) {
|
|
3598
|
-
const
|
|
3599
|
-
const runtimeMajor = runtimeVersion.match(/^\d+/)?.[0];
|
|
3600
|
-
const applicable = claim4.versionRange === "*" || rangeMajor !== void 0 && rangeMajor === runtimeMajor;
|
|
3671
|
+
const applicable = isRuntimeVersionInRange(claim4.versionRange, runtimeVersion);
|
|
3601
3672
|
const sufficientState = ["documented", "source-observed", "runtime-observed"].includes(
|
|
3602
3673
|
claim4.state
|
|
3603
3674
|
);
|
|
@@ -3615,85 +3686,26 @@ function resolveRuntimeEvidence(claim4, runtimeVersion) {
|
|
|
3615
3686
|
}
|
|
3616
3687
|
|
|
3617
3688
|
// packages/compiler/src/negotiation/adapter-registry.ts
|
|
3618
|
-
var
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
purityClass: "planned-effect",
|
|
3630
|
-
effectClass: "configuration",
|
|
3631
|
-
requiredEvidenceCategories: ["configuration"]
|
|
3632
|
-
},
|
|
3633
|
-
{
|
|
3634
|
-
id: "pi-extension-registration",
|
|
3635
|
-
operationKinds: ["InstallExtension"],
|
|
3636
|
-
purityClass: "planned-effect",
|
|
3637
|
-
effectClass: "registration",
|
|
3638
|
-
requiredEvidenceCategories: ["configuration"]
|
|
3639
|
-
},
|
|
3640
|
-
{
|
|
3641
|
-
id: "oh-my-pi-code-as-hooks",
|
|
3642
|
-
operationKinds: ["InstallExtension"],
|
|
3643
|
-
purityClass: "planned-effect",
|
|
3644
|
-
effectClass: "registration",
|
|
3645
|
-
requiredEvidenceCategories: ["hooks", "configuration"]
|
|
3646
|
-
},
|
|
3647
|
-
{
|
|
3648
|
-
id: "antigravity-plugin-registration",
|
|
3649
|
-
operationKinds: ["RegisterPlugin"],
|
|
3650
|
-
purityClass: "planned-effect",
|
|
3651
|
-
effectClass: "registration",
|
|
3652
|
-
requiredEvidenceCategories: ["plugin", "location"]
|
|
3653
|
-
},
|
|
3654
|
-
{
|
|
3655
|
-
id: "antigravity-hook-registration",
|
|
3656
|
-
operationKinds: ["RegisterHook"],
|
|
3657
|
-
purityClass: "planned-effect",
|
|
3658
|
-
effectClass: "registration",
|
|
3659
|
-
requiredEvidenceCategories: ["hooks", "location"]
|
|
3660
|
-
},
|
|
3661
|
-
{
|
|
3662
|
-
id: "antigravity-mcp-registration",
|
|
3663
|
-
operationKinds: ["RegisterMcpServer"],
|
|
3664
|
-
purityClass: "planned-effect",
|
|
3665
|
-
effectClass: "registration",
|
|
3666
|
-
requiredEvidenceCategories: ["mcp", "location"]
|
|
3667
|
-
},
|
|
3668
|
-
{
|
|
3669
|
-
id: "opencode-custom-tool",
|
|
3670
|
-
operationKinds: ["InstallExtension"],
|
|
3671
|
-
purityClass: "planned-effect",
|
|
3672
|
-
effectClass: "registration",
|
|
3673
|
-
requiredEvidenceCategories: ["location", "discovery"]
|
|
3674
|
-
},
|
|
3675
|
-
{
|
|
3676
|
-
id: "opencode-plugin",
|
|
3677
|
-
operationKinds: ["RegisterPlugin"],
|
|
3678
|
-
purityClass: "planned-effect",
|
|
3679
|
-
effectClass: "registration",
|
|
3680
|
-
requiredEvidenceCategories: ["plugin", "discovery"]
|
|
3681
|
-
}
|
|
3682
|
-
];
|
|
3683
|
-
var adapterRegistry = new Map(
|
|
3684
|
-
entries.map((x) => [x.id, x])
|
|
3685
|
-
);
|
|
3689
|
+
var adapterIds = Object.freeze([
|
|
3690
|
+
"materialize-markdown",
|
|
3691
|
+
"patch-structured-config",
|
|
3692
|
+
"pi-extension-registration",
|
|
3693
|
+
"oh-my-pi-code-as-hooks",
|
|
3694
|
+
"antigravity-plugin-registration",
|
|
3695
|
+
"antigravity-hook-registration",
|
|
3696
|
+
"antigravity-mcp-registration",
|
|
3697
|
+
"opencode-custom-tool",
|
|
3698
|
+
"opencode-plugin"
|
|
3699
|
+
]);
|
|
3686
3700
|
function requireAdapter(id) {
|
|
3687
|
-
|
|
3688
|
-
if (!item) throw new Error(`Unknown adapter ID: ${id}`);
|
|
3689
|
-
return item;
|
|
3701
|
+
if (!adapterIds.includes(id)) throw new Error(`Unknown adapter ID: ${id}`);
|
|
3690
3702
|
}
|
|
3691
3703
|
|
|
3692
3704
|
// packages/compiler/src/negotiation/negotiate-capability.ts
|
|
3693
3705
|
function negotiateCapability(artifact, descriptor, claims, version) {
|
|
3694
3706
|
return artifact.invocationIntents.map((intent) => {
|
|
3695
3707
|
const surface = descriptor.surfaces.find(
|
|
3696
|
-
(x) => x.semanticKind === intent && x.evidenceClaimIds.some((claimId) => {
|
|
3708
|
+
(x) => x.semanticKind === intent && (x.versionRange === void 0 || isRuntimeVersionInRange(x.versionRange, version)) && x.evidenceClaimIds.some((claimId) => {
|
|
3697
3709
|
const claim4 = claims.find((candidate) => candidate.id === claimId);
|
|
3698
3710
|
return claim4 !== void 0 && resolveRuntimeEvidence(claim4, version).reason !== "version-inapplicable";
|
|
3699
3711
|
})
|
|
@@ -3749,8 +3761,8 @@ var operationalSectionNames = Object.freeze([
|
|
|
3749
3761
|
]);
|
|
3750
3762
|
function validateOperationalSkillContract(contract) {
|
|
3751
3763
|
for (const section of operationalSectionNames) {
|
|
3752
|
-
const
|
|
3753
|
-
if (!Array.isArray(
|
|
3764
|
+
const entries = contract[section];
|
|
3765
|
+
if (!Array.isArray(entries) || entries.length === 0 || entries.some((entry) => !entry.trim())) {
|
|
3754
3766
|
throw new Error(`Missing operational section: ${section}`);
|
|
3755
3767
|
}
|
|
3756
3768
|
}
|
|
@@ -3770,13 +3782,26 @@ var headings = {
|
|
|
3770
3782
|
function renderOperationalSkillContract(contract) {
|
|
3771
3783
|
validateOperationalSkillContract(contract);
|
|
3772
3784
|
return operationalSectionNames.map((section) => {
|
|
3773
|
-
const
|
|
3785
|
+
const entries = contract[section].map((entry, index) => `${index + 1}. ${entry}`).join("\n");
|
|
3774
3786
|
return `## ${headings[section]}
|
|
3775
3787
|
|
|
3776
|
-
${
|
|
3788
|
+
${entries}`;
|
|
3777
3789
|
}).join("\n\n");
|
|
3778
3790
|
}
|
|
3779
3791
|
|
|
3792
|
+
// packages/contracts/src/skill-document.ts
|
|
3793
|
+
function renderSkillDocument(input) {
|
|
3794
|
+
const description = input.description.replace(/[\r\n\t]+/gu, " ").replace(/\s{2,}/gu, " ").trim();
|
|
3795
|
+
if (!description) throw new Error(`Skill ${input.name} requires a non-empty description`);
|
|
3796
|
+
return `---
|
|
3797
|
+
name: ${JSON.stringify(input.name)}
|
|
3798
|
+
description: ${JSON.stringify(description)}
|
|
3799
|
+
---
|
|
3800
|
+
${input.marker}
|
|
3801
|
+
${input.content}
|
|
3802
|
+
`;
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3780
3805
|
// packages/contracts/src/structured-config.ts
|
|
3781
3806
|
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
3782
3807
|
import { parse as parse2, stringify } from "yaml";
|
|
@@ -3809,6 +3834,7 @@ function planProjection(artifact, runtimeId, scope, negotiations) {
|
|
|
3809
3834
|
id: `materialize:${n4.intent}`,
|
|
3810
3835
|
artifactId: artifact.id,
|
|
3811
3836
|
logicalDestination: `${n4.intent}/${artifact.id}`,
|
|
3837
|
+
description: artifact.title,
|
|
3812
3838
|
content: artifact.operationalContract ? renderOperationalSkillContract(artifact.operationalContract) : artifact.title
|
|
3813
3839
|
});
|
|
3814
3840
|
for (const resource2 of artifact.resourceFiles ?? [])
|
|
@@ -3844,14 +3870,14 @@ function planProjection(artifact, runtimeId, scope, negotiations) {
|
|
|
3844
3870
|
|
|
3845
3871
|
// packages/compiler/src/planning/plan-installation.ts
|
|
3846
3872
|
import { createHash as createHash3 } from "node:crypto";
|
|
3847
|
-
function planInstallation(plan, descriptor) {
|
|
3873
|
+
function planInstallation(plan, descriptor, runtimeVersion) {
|
|
3848
3874
|
const operations = [];
|
|
3849
3875
|
for (const op of plan.operations) {
|
|
3850
3876
|
if (op.kind === "MaterializeArtifact") {
|
|
3851
3877
|
const location = descriptor.locations.find(
|
|
3852
|
-
(x) => x.scope === plan.scope && (x.artifactKind === "skill" || x.artifactKind === op.logicalDestination.split("/")[0])
|
|
3878
|
+
(x) => x.scope === plan.scope && (x.artifactKind === "skill" || x.artifactKind === op.logicalDestination.split("/")[0]) && (!x.versionRange || isRuntimeVersionInRange(x.versionRange, runtimeVersion))
|
|
3853
3879
|
);
|
|
3854
|
-
if (!location
|
|
3880
|
+
if (!location?.pathTemplate || location.installation === "manual") {
|
|
3855
3881
|
operations.push({
|
|
3856
3882
|
kind: "EmitManualStep",
|
|
3857
3883
|
id: `manual:${op.id}`,
|
|
@@ -3879,14 +3905,15 @@ function planInstallation(plan, descriptor) {
|
|
|
3879
3905
|
uninstall: "remove-owned-only",
|
|
3880
3906
|
ownershipIntent: "own",
|
|
3881
3907
|
destination: `${location.pathTemplate}/${op.logicalDestination}`,
|
|
3908
|
+
description: op.description,
|
|
3882
3909
|
content: op.content
|
|
3883
3910
|
});
|
|
3884
3911
|
}
|
|
3885
3912
|
if (op.kind === "IncludeResource") {
|
|
3886
3913
|
const location = descriptor.locations.find(
|
|
3887
|
-
(candidate) => candidate.scope === plan.scope && candidate.artifactKind === "skill"
|
|
3914
|
+
(candidate) => candidate.scope === plan.scope && candidate.artifactKind === "skill" && (!candidate.versionRange || isRuntimeVersionInRange(candidate.versionRange, runtimeVersion))
|
|
3888
3915
|
);
|
|
3889
|
-
if (!location
|
|
3916
|
+
if (!location?.pathTemplate || location.installation === "manual") {
|
|
3890
3917
|
operations.push({
|
|
3891
3918
|
kind: "EmitManualStep",
|
|
3892
3919
|
id: `manual:${op.id}`,
|
|
@@ -3958,7 +3985,7 @@ function planSetup(request, artifact, descriptor, claims, ownershipManifest) {
|
|
|
3958
3985
|
request.runtimeVersion
|
|
3959
3986
|
);
|
|
3960
3987
|
const projectionPlan = planProjection(artifact, descriptor.id, request.scope, negotiations);
|
|
3961
|
-
const baseInstallationPlan = planInstallation(projectionPlan, descriptor);
|
|
3988
|
+
const baseInstallationPlan = planInstallation(projectionPlan, descriptor, request.runtimeVersion);
|
|
3962
3989
|
const mutatingIntent = request.intent === "setup" || request.intent === "update";
|
|
3963
3990
|
let installationPlan = mutatingIntent ? baseInstallationPlan : { ...baseInstallationPlan, operations: [] };
|
|
3964
3991
|
if (request.intent === "remove") {
|
|
@@ -4029,7 +4056,7 @@ function planSetup(request, artifact, descriptor, claims, ownershipManifest) {
|
|
|
4029
4056
|
approvals: request.approvalPolicy === "preapproved" ? [] : approvals,
|
|
4030
4057
|
manualSteps: installationPlan.operations.filter((operation) => operation.kind === "EmitManualStep").map((operation) => operation.id),
|
|
4031
4058
|
verificationExpectations: projectionPlan.operations.filter((operation) => operation.kind === "ExpectVerification").map((operation) => operation.expectation),
|
|
4032
|
-
nativeUsageInputs: negotiations.
|
|
4059
|
+
nativeUsageInputs: negotiations.flatMap(({ surfaceId }) => surfaceId ? [surfaceId] : [])
|
|
4033
4060
|
};
|
|
4034
4061
|
}
|
|
4035
4062
|
|
|
@@ -11406,8 +11433,8 @@ async function assertNoSymlinks(current) {
|
|
|
11406
11433
|
async function treeDigest(root) {
|
|
11407
11434
|
const hash = createHash5("sha256");
|
|
11408
11435
|
async function visit(current, relative4 = "") {
|
|
11409
|
-
const
|
|
11410
|
-
for (const entry of
|
|
11436
|
+
const entries = await readdir(current, { withFileTypes: true });
|
|
11437
|
+
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
11411
11438
|
if ([".git", "node_modules", ".turbo"].includes(entry.name)) continue;
|
|
11412
11439
|
const path9 = join(current, entry.name);
|
|
11413
11440
|
const child = relative4 ? `${relative4}/${entry.name}` : entry.name;
|
|
@@ -11706,9 +11733,9 @@ function writeEnvelope(envelope, format2) {
|
|
|
11706
11733
|
}
|
|
11707
11734
|
|
|
11708
11735
|
// packages/cli/src/release.ts
|
|
11709
|
-
var cliVersion = true ? "0.1.
|
|
11736
|
+
var cliVersion = true ? "0.1.10" : createRequire(import.meta.url)("../../../package.json").version;
|
|
11710
11737
|
|
|
11711
|
-
// packages/adapters/antigravity/
|
|
11738
|
+
// packages/adapters/src/antigravity/materialize.ts
|
|
11712
11739
|
import { resolve as resolve2 } from "node:path";
|
|
11713
11740
|
var marker = "<!-- portable-capabilities:owned antigravity -->";
|
|
11714
11741
|
function destination(value) {
|
|
@@ -11739,15 +11766,15 @@ function diagnostic(operation, kind, message) {
|
|
|
11739
11766
|
}
|
|
11740
11767
|
function render(operation) {
|
|
11741
11768
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
11742
|
-
|
|
11769
|
+
const name = skill?.[1];
|
|
11770
|
+
if (!name) return `${marker}
|
|
11743
11771
|
${operation.content}`;
|
|
11744
|
-
return
|
|
11745
|
-
name
|
|
11746
|
-
description:
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
`;
|
|
11772
|
+
return renderSkillDocument({
|
|
11773
|
+
name,
|
|
11774
|
+
description: operation.description,
|
|
11775
|
+
marker,
|
|
11776
|
+
content: operation.content
|
|
11777
|
+
});
|
|
11751
11778
|
}
|
|
11752
11779
|
function registration(operation) {
|
|
11753
11780
|
return `${JSON.stringify({ adapterId: operation.adapterId, kind: operation.kind, target: operation.target }, null, 2)}
|
|
@@ -11856,7 +11883,7 @@ function prepareAntigravityMaterialization(plan, root) {
|
|
|
11856
11883
|
});
|
|
11857
11884
|
}
|
|
11858
11885
|
|
|
11859
|
-
// packages/adapters/antigravity/
|
|
11886
|
+
// packages/adapters/src/antigravity/runtime-descriptor.ts
|
|
11860
11887
|
var markdown = "materialize-markdown";
|
|
11861
11888
|
var plugin = "antigravity-plugin-registration";
|
|
11862
11889
|
var hook = "antigravity-hook-registration";
|
|
@@ -12049,7 +12076,7 @@ var antigravityRuntimeDescriptor = {
|
|
|
12049
12076
|
]
|
|
12050
12077
|
};
|
|
12051
12078
|
|
|
12052
|
-
// packages/adapters/antigravity/
|
|
12079
|
+
// packages/adapters/src/antigravity/runtime-evidence.ts
|
|
12053
12080
|
import { createHash as createHash7 } from "node:crypto";
|
|
12054
12081
|
var digest2 = (value) => createHash7("sha256").update(value).digest("hex");
|
|
12055
12082
|
var retrievedAt = "2026-08-10T00:00:00.000Z";
|
|
@@ -12197,7 +12224,7 @@ var antigravityRuntimeEvidence = [
|
|
|
12197
12224
|
)
|
|
12198
12225
|
];
|
|
12199
12226
|
|
|
12200
|
-
// packages/adapters/claude-code/
|
|
12227
|
+
// packages/adapters/src/claude-code/materialize.ts
|
|
12201
12228
|
import { resolve as resolve3 } from "node:path";
|
|
12202
12229
|
var marker2 = "<!-- portable-capabilities:owned claude-code -->";
|
|
12203
12230
|
function destination2(value) {
|
|
@@ -12232,15 +12259,15 @@ function diagnostic2(operation, kind, message) {
|
|
|
12232
12259
|
}
|
|
12233
12260
|
function render2(operation) {
|
|
12234
12261
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
12235
|
-
|
|
12262
|
+
const name = skill?.[1];
|
|
12263
|
+
if (!name) return `${marker2}
|
|
12236
12264
|
${operation.content}`;
|
|
12237
|
-
return
|
|
12238
|
-
name
|
|
12239
|
-
description:
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
`;
|
|
12265
|
+
return renderSkillDocument({
|
|
12266
|
+
name,
|
|
12267
|
+
description: operation.description,
|
|
12268
|
+
marker: marker2,
|
|
12269
|
+
content: operation.content
|
|
12270
|
+
});
|
|
12244
12271
|
}
|
|
12245
12272
|
function config(operation, root, path9) {
|
|
12246
12273
|
if (operation.format !== "json")
|
|
@@ -12354,7 +12381,7 @@ function prepareClaudeCodeMaterialization(plan, root) {
|
|
|
12354
12381
|
});
|
|
12355
12382
|
}
|
|
12356
12383
|
|
|
12357
|
-
// packages/adapters/claude-code/
|
|
12384
|
+
// packages/adapters/src/claude-code/runtime-descriptor.ts
|
|
12358
12385
|
var markdown2 = "materialize-markdown";
|
|
12359
12386
|
var claudeCodeRuntimeDescriptor = {
|
|
12360
12387
|
schemaVersion: "1.0",
|
|
@@ -12556,7 +12583,7 @@ var claudeCodeRuntimeDescriptor = {
|
|
|
12556
12583
|
]
|
|
12557
12584
|
};
|
|
12558
12585
|
|
|
12559
|
-
// packages/adapters/claude-code/
|
|
12586
|
+
// packages/adapters/src/claude-code/runtime-evidence.ts
|
|
12560
12587
|
import { createHash as createHash8 } from "node:crypto";
|
|
12561
12588
|
var digest3 = (value) => createHash8("sha256").update(value).digest("hex");
|
|
12562
12589
|
var retrievedAt2 = "2026-08-10T00:00:00.000Z";
|
|
@@ -12727,18 +12754,20 @@ var claudeCodeRuntimeEvidence = Object.freeze([
|
|
|
12727
12754
|
}))
|
|
12728
12755
|
]);
|
|
12729
12756
|
|
|
12730
|
-
// packages/adapters/codex/
|
|
12757
|
+
// packages/adapters/src/codex/materialize.ts
|
|
12731
12758
|
import { resolve as resolve4 } from "node:path";
|
|
12732
12759
|
var marker3 = "<!-- portable-capabilities:owned codex -->";
|
|
12733
12760
|
function destination3(value) {
|
|
12734
12761
|
const project = value.match(/^\.codex\/skills\/skill\/(.+)$/);
|
|
12735
12762
|
if (project) return `.codex/skills/${project[1]}/SKILL.md`;
|
|
12763
|
+
const currentProject = value.match(/^\.agents\/skills\/skill\/(.+)$/);
|
|
12764
|
+
if (currentProject) return `.agents/skills/${currentProject[1]}/SKILL.md`;
|
|
12736
12765
|
const user = value.match(/^\$CODEX_HOME\/skills\/skill\/(.+)$/);
|
|
12737
12766
|
if (user) return `.codex-user/skills/${user[1]}/SKILL.md`;
|
|
12738
12767
|
return value.replace(/^\$CODEX_HOME\//, ".codex-user/");
|
|
12739
12768
|
}
|
|
12740
12769
|
function resourceDestination3(value) {
|
|
12741
|
-
return value.replace(/^\.codex\/skills\/skill\//u, ".codex/skills/").replace(/^\$CODEX_HOME\/skills\/skill\//u, ".codex-user/skills/");
|
|
12770
|
+
return value.replace(/^\.codex\/skills\/skill\//u, ".codex/skills/").replace(/^\.agents\/skills\/skill\//u, ".agents/skills/").replace(/^\$CODEX_HOME\/skills\/skill\//u, ".codex-user/skills/");
|
|
12742
12771
|
}
|
|
12743
12772
|
function confined3(root, path9) {
|
|
12744
12773
|
const target = resolve4(root, path9);
|
|
@@ -12748,15 +12777,15 @@ function confined3(root, path9) {
|
|
|
12748
12777
|
}
|
|
12749
12778
|
function render3(operation) {
|
|
12750
12779
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
12751
|
-
|
|
12780
|
+
const name = skill?.[1];
|
|
12781
|
+
if (!name) return `${marker3}
|
|
12752
12782
|
${operation.content}`;
|
|
12753
|
-
return
|
|
12754
|
-
name
|
|
12755
|
-
description:
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
`;
|
|
12783
|
+
return renderSkillDocument({
|
|
12784
|
+
name,
|
|
12785
|
+
description: operation.description,
|
|
12786
|
+
marker: marker3,
|
|
12787
|
+
content: operation.content
|
|
12788
|
+
});
|
|
12760
12789
|
}
|
|
12761
12790
|
function transform(operation) {
|
|
12762
12791
|
if (operation.format !== "json")
|
|
@@ -12820,25 +12849,48 @@ function prepareCodexMaterialization(plan, root, ..._options) {
|
|
|
12820
12849
|
});
|
|
12821
12850
|
}
|
|
12822
12851
|
|
|
12823
|
-
// packages/adapters/codex/
|
|
12852
|
+
// packages/adapters/src/codex/runtime-descriptor.ts
|
|
12824
12853
|
var codexRuntimeDescriptor = {
|
|
12825
12854
|
schemaVersion: "1.0",
|
|
12826
12855
|
id: "codex",
|
|
12827
12856
|
aliases: ["codex-cli"],
|
|
12828
|
-
supportedVersions: ["
|
|
12857
|
+
supportedVersions: ["=0.146.0", ">=0.147.0 <0.148.0"],
|
|
12829
12858
|
locations: [
|
|
12830
12859
|
{
|
|
12831
|
-
id: "codex-project-skills",
|
|
12860
|
+
id: "codex-project-skills-0146",
|
|
12832
12861
|
artifactKind: "skill",
|
|
12833
12862
|
scope: "project",
|
|
12834
12863
|
pathTemplate: ".codex/skills",
|
|
12835
12864
|
evidenceClaimIds: ["codex.location.project-skills"],
|
|
12865
|
+
versionRange: "=0.146.0",
|
|
12866
|
+
installation: "automatic",
|
|
12867
|
+
registration: "discovery",
|
|
12868
|
+
uninstall: "automatic"
|
|
12869
|
+
},
|
|
12870
|
+
{
|
|
12871
|
+
id: "codex-project-skills-0147",
|
|
12872
|
+
artifactKind: "skill",
|
|
12873
|
+
scope: "project",
|
|
12874
|
+
pathTemplate: ".agents/skills",
|
|
12875
|
+
evidenceClaimIds: ["codex.location.project-skills-agents"],
|
|
12876
|
+
versionRange: ">=0.147.0 <0.148.0",
|
|
12877
|
+
installation: "automatic",
|
|
12878
|
+
registration: "discovery",
|
|
12879
|
+
uninstall: "automatic"
|
|
12880
|
+
},
|
|
12881
|
+
{
|
|
12882
|
+
id: "codex-user-skills-0147",
|
|
12883
|
+
artifactKind: "skill",
|
|
12884
|
+
scope: "user",
|
|
12885
|
+
pathTemplate: ".agents/skills",
|
|
12886
|
+
evidenceClaimIds: ["codex.location.user-skills-agents"],
|
|
12887
|
+
versionRange: ">=0.147.0 <0.148.0",
|
|
12836
12888
|
installation: "automatic",
|
|
12837
12889
|
registration: "discovery",
|
|
12838
12890
|
uninstall: "automatic"
|
|
12839
12891
|
},
|
|
12840
12892
|
{
|
|
12841
|
-
id: "codex-user-skills",
|
|
12893
|
+
id: "codex-user-skills-0146",
|
|
12842
12894
|
artifactKind: "skill",
|
|
12843
12895
|
scope: "user",
|
|
12844
12896
|
pathTemplate: "$CODEX_HOME/skills",
|
|
@@ -12851,16 +12903,30 @@ var codexRuntimeDescriptor = {
|
|
|
12851
12903
|
],
|
|
12852
12904
|
surfaces: [
|
|
12853
12905
|
{
|
|
12854
|
-
id: "codex-direct-skill",
|
|
12906
|
+
id: "codex-direct-skill-0146",
|
|
12855
12907
|
semanticKind: "skill",
|
|
12856
12908
|
integrationMode: "declarative",
|
|
12857
12909
|
adapterId: "materialize-markdown",
|
|
12858
|
-
discovery: "Codex discovers project
|
|
12859
|
-
invocation: "Invoke the installed skill through Codex
|
|
12910
|
+
discovery: "Codex 0.146.x discovers project skills from .codex/skills.",
|
|
12911
|
+
invocation: "Invoke the installed skill through Codex 0.146.x native skill selection.",
|
|
12860
12912
|
precedence: ["project", "user"],
|
|
12861
12913
|
evidenceClaimIds: ["codex.discovery.skills", "codex.invocation.skills"],
|
|
12862
|
-
|
|
12914
|
+
versionRange: "=0.146.0",
|
|
12915
|
+
stability: "version-gated",
|
|
12863
12916
|
evidenceState: "runtime-observed"
|
|
12917
|
+
},
|
|
12918
|
+
{
|
|
12919
|
+
id: "codex-direct-skill-0147",
|
|
12920
|
+
semanticKind: "skill",
|
|
12921
|
+
integrationMode: "declarative",
|
|
12922
|
+
adapterId: "materialize-markdown",
|
|
12923
|
+
discovery: "Codex 0.147.x discovers project skills from .agents/skills.",
|
|
12924
|
+
invocation: "Invoke the installed skill through Codex 0.147.x native skill selection.",
|
|
12925
|
+
precedence: ["project", "user"],
|
|
12926
|
+
evidenceClaimIds: ["codex.discovery.skills-0147", "codex.invocation.skills-0147"],
|
|
12927
|
+
versionRange: ">=0.147.0 <0.148.0",
|
|
12928
|
+
stability: "version-gated",
|
|
12929
|
+
evidenceState: "source-observed"
|
|
12864
12930
|
}
|
|
12865
12931
|
],
|
|
12866
12932
|
configuration: [],
|
|
@@ -12870,10 +12936,37 @@ var codexRuntimeDescriptor = {
|
|
|
12870
12936
|
degradation: []
|
|
12871
12937
|
};
|
|
12872
12938
|
|
|
12873
|
-
// packages/adapters/codex/
|
|
12939
|
+
// packages/adapters/src/codex/runtime-evidence.ts
|
|
12874
12940
|
import { createHash as createHash9 } from "node:crypto";
|
|
12875
12941
|
var digest4 = (value) => createHash9("sha256").update(value).digest("hex");
|
|
12876
12942
|
var observedAt = "2026-08-08T00:00:00.000Z";
|
|
12943
|
+
var sourceObservedAt = "2026-08-15T00:00:00.000Z";
|
|
12944
|
+
var codexSource = "https://github.com/openai/codex";
|
|
12945
|
+
var codexSkillRootsSource = "https://github.com/openai/codex/blob/53f3fa749659498fa24c81da8fde5440fa7bba7f/codex-rs/ext/skills/src/host_roots.rs";
|
|
12946
|
+
var codexCurrentRange = ">=0.147.0 <0.148.0";
|
|
12947
|
+
var projectSkillRootExcerpt = 'const AGENTS_DIR_NAME: &str = ".agents";\nconst SKILLS_DIR_NAME: &str = "skills";';
|
|
12948
|
+
var userSkillRootExcerpt = "home_dir.join(AGENTS_DIR_NAME).join(SKILLS_DIR_NAME), SkillScope::User";
|
|
12949
|
+
var discoveryExcerpt = "let agents_skills = directory.join(AGENTS_DIR_NAME).join(SKILLS_DIR_NAME);";
|
|
12950
|
+
var invocationExcerpt = 'UserInput::Skill {\n name: "demo".to_string(),';
|
|
12951
|
+
var sourceClaim2 = (id, subject, assertion, sourceLocator, sourceExcerpt) => ({
|
|
12952
|
+
schemaVersion: "1.0",
|
|
12953
|
+
id,
|
|
12954
|
+
runtimeId: "codex",
|
|
12955
|
+
category: id.includes("location") ? "location" : id.includes("discovery") ? "discovery" : "invocation",
|
|
12956
|
+
subject,
|
|
12957
|
+
assertion,
|
|
12958
|
+
versionRange: codexCurrentRange,
|
|
12959
|
+
sourceType: "official-source",
|
|
12960
|
+
source: codexSource,
|
|
12961
|
+
sourceLocator,
|
|
12962
|
+
sourceExcerpt,
|
|
12963
|
+
sourceDigest: digest4(sourceExcerpt),
|
|
12964
|
+
state: "source-observed",
|
|
12965
|
+
confidence: "high",
|
|
12966
|
+
verificationStatus: "verified",
|
|
12967
|
+
stability: "version-gated",
|
|
12968
|
+
verifiedAt: sourceObservedAt
|
|
12969
|
+
});
|
|
12877
12970
|
var codexRuntimeEvidence = Object.freeze([
|
|
12878
12971
|
{
|
|
12879
12972
|
schemaVersion: "1.0",
|
|
@@ -12881,54 +12974,82 @@ var codexRuntimeEvidence = Object.freeze([
|
|
|
12881
12974
|
runtimeId: "codex",
|
|
12882
12975
|
category: "location",
|
|
12883
12976
|
subject: "project skill root",
|
|
12884
|
-
assertion: "Codex project skills are materialized beneath .codex/skills.",
|
|
12885
|
-
versionRange: "
|
|
12977
|
+
assertion: "Codex 0.146.x project skills are materialized beneath .codex/skills.",
|
|
12978
|
+
versionRange: "=0.146.0",
|
|
12886
12979
|
sourceType: "runtime-probe",
|
|
12887
12980
|
source: "codex-cli",
|
|
12888
|
-
sourceLocator: "native
|
|
12981
|
+
sourceLocator: "packages/conformance/src/tracer/codex-native-evidence.json",
|
|
12889
12982
|
sourceExcerpt: ".codex/skills",
|
|
12890
|
-
sourceDigest: digest4("codex project skills .codex/skills"),
|
|
12983
|
+
sourceDigest: digest4("codex 0.146 project skills .codex/skills"),
|
|
12891
12984
|
state: "runtime-observed",
|
|
12892
12985
|
confidence: "high",
|
|
12893
12986
|
verificationStatus: "verified",
|
|
12894
|
-
stability: "
|
|
12987
|
+
stability: "version-gated",
|
|
12895
12988
|
verifiedAt: observedAt
|
|
12896
12989
|
},
|
|
12990
|
+
sourceClaim2(
|
|
12991
|
+
"codex.location.project-skills-agents",
|
|
12992
|
+
"project skill root",
|
|
12993
|
+
"Codex 0.147.x project skills are discovered beneath .agents/skills.",
|
|
12994
|
+
`${codexSkillRootsSource}#L92-L101`,
|
|
12995
|
+
projectSkillRootExcerpt
|
|
12996
|
+
),
|
|
12997
|
+
sourceClaim2(
|
|
12998
|
+
"codex.location.user-skills-agents",
|
|
12999
|
+
"user skill root",
|
|
13000
|
+
"Codex 0.147.x user skills are discovered beneath ~/.agents/skills.",
|
|
13001
|
+
`${codexSkillRootsSource}#L107-L119`,
|
|
13002
|
+
userSkillRootExcerpt
|
|
13003
|
+
),
|
|
12897
13004
|
{
|
|
12898
13005
|
schemaVersion: "1.0",
|
|
12899
13006
|
id: "codex.location.user-skills",
|
|
12900
13007
|
runtimeId: "codex",
|
|
12901
13008
|
category: "location",
|
|
12902
13009
|
subject: "user skill root",
|
|
12903
|
-
assertion: "Codex user skills are materialized beneath CODEX_HOME/skills.",
|
|
12904
|
-
versionRange: "
|
|
13010
|
+
assertion: "Codex 0.146.x user skills are materialized beneath CODEX_HOME/skills.",
|
|
13011
|
+
versionRange: "=0.146.0",
|
|
12905
13012
|
sourceType: "runtime-probe",
|
|
12906
13013
|
source: "codex-cli",
|
|
12907
13014
|
sourceLocator: "native vertical tracer",
|
|
12908
13015
|
sourceExcerpt: "CODEX_HOME/skills",
|
|
12909
|
-
sourceDigest: digest4("codex user skills CODEX_HOME/skills"),
|
|
13016
|
+
sourceDigest: digest4("codex 0.146 user skills CODEX_HOME/skills"),
|
|
12910
13017
|
state: "runtime-observed",
|
|
12911
13018
|
confidence: "high",
|
|
12912
13019
|
verificationStatus: "verified",
|
|
12913
|
-
stability: "
|
|
13020
|
+
stability: "version-gated",
|
|
12914
13021
|
verifiedAt: observedAt
|
|
12915
13022
|
},
|
|
13023
|
+
sourceClaim2(
|
|
13024
|
+
"codex.discovery.skills-0147",
|
|
13025
|
+
"native skill discovery",
|
|
13026
|
+
"Codex 0.147.x discovers Agent Skills from .agents/skills.",
|
|
13027
|
+
`${codexSkillRootsSource}#L139-L161`,
|
|
13028
|
+
discoveryExcerpt
|
|
13029
|
+
),
|
|
13030
|
+
sourceClaim2(
|
|
13031
|
+
"codex.invocation.skills-0147",
|
|
13032
|
+
"native skill invocation",
|
|
13033
|
+
"Codex 0.147.x invokes a discovered Agent Skill through its native skill selection.",
|
|
13034
|
+
"https://github.com/openai/codex/blob/53f3fa749659498fa24c81da8fde5440fa7bba7f/codex-rs/core/tests/suite/skills.rs",
|
|
13035
|
+
invocationExcerpt
|
|
13036
|
+
),
|
|
12916
13037
|
{
|
|
12917
13038
|
schemaVersion: "1.0",
|
|
12918
13039
|
id: "codex.discovery.skills",
|
|
12919
13040
|
runtimeId: "codex",
|
|
12920
13041
|
category: "discovery",
|
|
12921
13042
|
subject: "native skill discovery",
|
|
12922
|
-
assertion: "Codex natively discovers a skill installed in its project skill root.",
|
|
12923
|
-
versionRange: "
|
|
13043
|
+
assertion: "Codex 0.146.x natively discovers a skill installed in its project skill root.",
|
|
13044
|
+
versionRange: "=0.146.0",
|
|
12924
13045
|
sourceType: "runtime-probe",
|
|
12925
13046
|
source: "codex-cli",
|
|
12926
13047
|
sourceLocator: "packages/conformance/src/tracer/codex-native-evidence.json",
|
|
12927
|
-
sourceDigest: digest4("codex native discovery"),
|
|
13048
|
+
sourceDigest: digest4("codex 0.146 native discovery"),
|
|
12928
13049
|
state: "runtime-observed",
|
|
12929
13050
|
confidence: "high",
|
|
12930
13051
|
verificationStatus: "verified",
|
|
12931
|
-
stability: "
|
|
13052
|
+
stability: "version-gated",
|
|
12932
13053
|
verifiedAt: observedAt
|
|
12933
13054
|
},
|
|
12934
13055
|
{
|
|
@@ -12937,21 +13058,22 @@ var codexRuntimeEvidence = Object.freeze([
|
|
|
12937
13058
|
runtimeId: "codex",
|
|
12938
13059
|
category: "invocation",
|
|
12939
13060
|
subject: "native skill invocation",
|
|
12940
|
-
assertion: "Codex can invoke an installed skill through the native client.",
|
|
12941
|
-
versionRange: "
|
|
13061
|
+
assertion: "Codex 0.146.x can invoke an installed skill through the native client.",
|
|
13062
|
+
versionRange: "=0.146.0",
|
|
12942
13063
|
sourceType: "runtime-probe",
|
|
12943
13064
|
source: "codex-cli",
|
|
12944
13065
|
sourceLocator: "packages/conformance/src/tracer/codex-native-evidence.json",
|
|
12945
|
-
sourceDigest: digest4("codex native invocation"),
|
|
13066
|
+
sourceDigest: digest4("codex 0.146 native invocation"),
|
|
12946
13067
|
state: "runtime-observed",
|
|
12947
13068
|
confidence: "high",
|
|
12948
13069
|
verificationStatus: "verified",
|
|
12949
|
-
stability: "
|
|
13070
|
+
stability: "version-gated",
|
|
12950
13071
|
verifiedAt: observedAt
|
|
12951
13072
|
}
|
|
12952
13073
|
]);
|
|
12953
13074
|
|
|
12954
|
-
// packages/adapters/dcode/
|
|
13075
|
+
// packages/adapters/src/dcode/materialize.ts
|
|
13076
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
12955
13077
|
import { resolve as resolve5 } from "node:path";
|
|
12956
13078
|
var marker4 = "<!-- portable-capabilities:owned dcode -->";
|
|
12957
13079
|
function destination4(value) {
|
|
@@ -12983,21 +13105,46 @@ function diagnostic3(operation, kind, message) {
|
|
|
12983
13105
|
}
|
|
12984
13106
|
function render4(operation) {
|
|
12985
13107
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
12986
|
-
|
|
13108
|
+
const name = skill?.[1];
|
|
13109
|
+
if (!name) return `${marker4}
|
|
12987
13110
|
${operation.content}`;
|
|
12988
|
-
return
|
|
12989
|
-
name
|
|
12990
|
-
description:
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
`;
|
|
13111
|
+
return renderSkillDocument({
|
|
13112
|
+
name,
|
|
13113
|
+
description: operation.description,
|
|
13114
|
+
marker: marker4,
|
|
13115
|
+
content: operation.content
|
|
13116
|
+
});
|
|
12995
13117
|
}
|
|
12996
13118
|
function registration3(operation) {
|
|
12997
13119
|
return `${JSON.stringify({ adapterId: operation.adapterId, kind: operation.kind, target: operation.target }, null, 2)}
|
|
12998
13120
|
`;
|
|
12999
13121
|
}
|
|
13000
|
-
function
|
|
13122
|
+
async function mergedInstructions(root, path9, operations, removedIds) {
|
|
13123
|
+
let existing;
|
|
13124
|
+
try {
|
|
13125
|
+
existing = await readFile3(resolve5(root, path9), "utf8");
|
|
13126
|
+
} catch (error) {
|
|
13127
|
+
if (error.code !== "ENOENT") throw error;
|
|
13128
|
+
}
|
|
13129
|
+
if (!existing && operations.length === 0) return void 0;
|
|
13130
|
+
const selectedIds = new Set(operations.map((operation) => operation.id));
|
|
13131
|
+
const existingText = existing ?? "";
|
|
13132
|
+
const firstHeading = existingText.search(/^## .+$/mu);
|
|
13133
|
+
const preamble = firstHeading >= 0 ? existingText.slice(0, firstHeading).trim() : existingText.trim();
|
|
13134
|
+
const sections = firstHeading >= 0 ? existingText.slice(firstHeading).split(/(?=^## .+$)/mu) : [];
|
|
13135
|
+
const retained = sections.filter((section) => {
|
|
13136
|
+
const id = section.match(/^## ([^\n]+)/u)?.[1] ?? "";
|
|
13137
|
+
return !selectedIds.has(id) && !removedIds.some((removedId) => id.startsWith(`${removedId}:`));
|
|
13138
|
+
}).map((section) => section.trim());
|
|
13139
|
+
const generated = operations.slice().sort((left, right) => left.id.localeCompare(right.id)).map((operation) => `## ${operation.id}
|
|
13140
|
+
|
|
13141
|
+
${operation.content.trim()}`);
|
|
13142
|
+
const sectionsToWrite = [...retained, ...generated];
|
|
13143
|
+
return sectionsToWrite.length > 0 ? `${preamble || marker4}
|
|
13144
|
+
${sectionsToWrite.join("\n\n")}
|
|
13145
|
+
` : void 0;
|
|
13146
|
+
}
|
|
13147
|
+
async function prepareDCodeMaterialization(plan, root) {
|
|
13001
13148
|
if (plan.runtimeId !== "dcode") throw new Error(`DCode adapter cannot prepare ${plan.runtimeId}`);
|
|
13002
13149
|
const mutations = [];
|
|
13003
13150
|
const diagnostics = [];
|
|
@@ -13099,28 +13246,39 @@ function prepareDCodeMaterialization(plan, root) {
|
|
|
13099
13246
|
);
|
|
13100
13247
|
}
|
|
13101
13248
|
}
|
|
13102
|
-
|
|
13249
|
+
const instructionRemovals = plan.operations.filter(
|
|
13250
|
+
(operation) => operation.kind === "RemoveOwnedArtifact" && /^\.deepagents\/skills\/[^/]+\/SKILL\.md$/u.test(destination4(operation.detail))
|
|
13251
|
+
);
|
|
13252
|
+
if (instructionOperations.length > 0 || instructionRemovals.length > 0) {
|
|
13103
13253
|
const instructionPath = ".deepagents/AGENTS.md";
|
|
13104
13254
|
confined4(root, instructionPath);
|
|
13105
|
-
const
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
path: instructionPath,
|
|
13111
|
-
kind: "write",
|
|
13112
|
-
content: `<!-- portable-capabilities:owned dcode -->
|
|
13113
|
-
${content}
|
|
13114
|
-
`,
|
|
13115
|
-
mode: 420,
|
|
13116
|
-
operationId: "dcode:shared-instructions",
|
|
13117
|
-
sourceProjectionOperationId: first.sourceProjectionOperationId,
|
|
13118
|
-
ownershipIntent: first.ownershipIntent,
|
|
13119
|
-
approval: first.approval,
|
|
13120
|
-
rollback: first.rollback,
|
|
13121
|
-
upgrade: first.upgrade,
|
|
13122
|
-
uninstall: first.uninstall
|
|
13255
|
+
const first = instructionOperations[0] ?? instructionRemovals[0];
|
|
13256
|
+
if (!first) throw new Error("DCode shared instruction operation is missing");
|
|
13257
|
+
const removedIds = instructionRemovals.flatMap((operation) => {
|
|
13258
|
+
const match = operation.detail.match(/^\.deepagents\/skills\/([^/]+)\/SKILL\.md$/u);
|
|
13259
|
+
return match?.[1] ? [match[1]] : [];
|
|
13123
13260
|
});
|
|
13261
|
+
const content = await mergedInstructions(
|
|
13262
|
+
root,
|
|
13263
|
+
instructionPath,
|
|
13264
|
+
instructionOperations,
|
|
13265
|
+
removedIds
|
|
13266
|
+
);
|
|
13267
|
+
mutations.push(
|
|
13268
|
+
content ? {
|
|
13269
|
+
path: instructionPath,
|
|
13270
|
+
kind: "write",
|
|
13271
|
+
content,
|
|
13272
|
+
mode: 420,
|
|
13273
|
+
operationId: "dcode:shared-instructions",
|
|
13274
|
+
sourceProjectionOperationId: first.sourceProjectionOperationId,
|
|
13275
|
+
ownershipIntent: first.ownershipIntent,
|
|
13276
|
+
approval: first.approval,
|
|
13277
|
+
rollback: first.rollback,
|
|
13278
|
+
upgrade: first.upgrade,
|
|
13279
|
+
uninstall: first.uninstall
|
|
13280
|
+
} : { path: instructionPath, kind: "remove", ...metadata3(first) }
|
|
13281
|
+
);
|
|
13124
13282
|
}
|
|
13125
13283
|
return Object.freeze({
|
|
13126
13284
|
runtimeId: plan.runtimeId,
|
|
@@ -13130,7 +13288,7 @@ ${content}
|
|
|
13130
13288
|
});
|
|
13131
13289
|
}
|
|
13132
13290
|
|
|
13133
|
-
// packages/adapters/dcode/
|
|
13291
|
+
// packages/adapters/src/dcode/runtime-descriptor.ts
|
|
13134
13292
|
var markdown3 = "materialize-markdown";
|
|
13135
13293
|
var source2 = "source-observed";
|
|
13136
13294
|
var dcodeRuntimeDescriptor = {
|
|
@@ -13335,7 +13493,7 @@ var dcodeRuntimeDescriptor = {
|
|
|
13335
13493
|
]
|
|
13336
13494
|
};
|
|
13337
13495
|
|
|
13338
|
-
// packages/adapters/dcode/
|
|
13496
|
+
// packages/adapters/src/dcode/runtime-evidence.ts
|
|
13339
13497
|
import { createHash as createHash10 } from "node:crypto";
|
|
13340
13498
|
var digest5 = (value) => createHash10("sha256").update(value).digest("hex");
|
|
13341
13499
|
var verifiedAt = "2026-08-10T00:00:00.000Z";
|
|
@@ -13518,7 +13676,7 @@ var dcodeRuntimeEvidence = Object.freeze([
|
|
|
13518
13676
|
})
|
|
13519
13677
|
]);
|
|
13520
13678
|
|
|
13521
|
-
// packages/adapters/oh-my-pi/
|
|
13679
|
+
// packages/adapters/src/oh-my-pi/materialize.ts
|
|
13522
13680
|
import { resolve as resolve6 } from "node:path";
|
|
13523
13681
|
var marker5 = "<!-- portable-capabilities:owned oh-my-pi -->";
|
|
13524
13682
|
function resolveOhMyPiProfile(input) {
|
|
@@ -13576,13 +13734,13 @@ function diagnostic4(operation, kind, message) {
|
|
|
13576
13734
|
}
|
|
13577
13735
|
function render5(operation) {
|
|
13578
13736
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
13579
|
-
|
|
13580
|
-
name
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13737
|
+
const name = skill?.[1];
|
|
13738
|
+
return name ? renderSkillDocument({
|
|
13739
|
+
name,
|
|
13740
|
+
description: operation.description,
|
|
13741
|
+
marker: marker5,
|
|
13742
|
+
content: operation.content
|
|
13743
|
+
}) : `${marker5}
|
|
13586
13744
|
${operation.content}`;
|
|
13587
13745
|
}
|
|
13588
13746
|
function registration4(operation) {
|
|
@@ -13691,7 +13849,7 @@ async function prepareOhMyPiMaterialization(plan, root, profile = { home: root }
|
|
|
13691
13849
|
});
|
|
13692
13850
|
}
|
|
13693
13851
|
|
|
13694
|
-
// packages/adapters/oh-my-pi/
|
|
13852
|
+
// packages/adapters/src/oh-my-pi/runtime-descriptor.ts
|
|
13695
13853
|
var markdown4 = "materialize-markdown";
|
|
13696
13854
|
var hooks = "oh-my-pi-code-as-hooks";
|
|
13697
13855
|
var config2 = "patch-structured-config";
|
|
@@ -13939,7 +14097,7 @@ var ohMyPiRuntimeDescriptor = {
|
|
|
13939
14097
|
]
|
|
13940
14098
|
};
|
|
13941
14099
|
|
|
13942
|
-
// packages/adapters/oh-my-pi/
|
|
14100
|
+
// packages/adapters/src/oh-my-pi/runtime-evidence.ts
|
|
13943
14101
|
import { createHash as createHash11 } from "node:crypto";
|
|
13944
14102
|
var digest6 = (value) => createHash11("sha256").update(value).digest("hex");
|
|
13945
14103
|
var verifiedAt2 = "2026-08-10T00:00:00.000Z";
|
|
@@ -14089,7 +14247,7 @@ var ohMyPiRuntimeEvidence = [
|
|
|
14089
14247
|
}
|
|
14090
14248
|
];
|
|
14091
14249
|
|
|
14092
|
-
// packages/adapters/opencode/
|
|
14250
|
+
// packages/adapters/src/opencode/materialize.ts
|
|
14093
14251
|
import { resolve as resolve7 } from "node:path";
|
|
14094
14252
|
var marker6 = "<!-- portable-capabilities:owned opencode -->";
|
|
14095
14253
|
function destination5(value) {
|
|
@@ -14126,15 +14284,15 @@ function diagnostic5(operation, kind, message) {
|
|
|
14126
14284
|
}
|
|
14127
14285
|
function render6(operation) {
|
|
14128
14286
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
14129
|
-
|
|
14287
|
+
const name = skill?.[1];
|
|
14288
|
+
if (!name) return `${marker6}
|
|
14130
14289
|
${operation.content}`;
|
|
14131
|
-
return
|
|
14132
|
-
name
|
|
14133
|
-
description:
|
|
14134
|
-
|
|
14135
|
-
|
|
14136
|
-
|
|
14137
|
-
`;
|
|
14290
|
+
return renderSkillDocument({
|
|
14291
|
+
name,
|
|
14292
|
+
description: operation.description,
|
|
14293
|
+
marker: marker6,
|
|
14294
|
+
content: operation.content
|
|
14295
|
+
});
|
|
14138
14296
|
}
|
|
14139
14297
|
function config3(operation, root, path9) {
|
|
14140
14298
|
if (operation.format !== "json")
|
|
@@ -14242,7 +14400,7 @@ async function prepareOpencodeMaterialization(plan, root) {
|
|
|
14242
14400
|
});
|
|
14243
14401
|
}
|
|
14244
14402
|
|
|
14245
|
-
// packages/adapters/opencode/
|
|
14403
|
+
// packages/adapters/src/opencode/runtime-descriptor.ts
|
|
14246
14404
|
var native = "opencode.stable";
|
|
14247
14405
|
var beta = "opencode.v2-beta";
|
|
14248
14406
|
var opencodeRuntimeDescriptor = {
|
|
@@ -14524,7 +14682,7 @@ var opencodeRuntimeDescriptor = {
|
|
|
14524
14682
|
]
|
|
14525
14683
|
};
|
|
14526
14684
|
|
|
14527
|
-
// packages/adapters/opencode/
|
|
14685
|
+
// packages/adapters/src/opencode/runtime-evidence.ts
|
|
14528
14686
|
import { createHash as createHash12 } from "node:crypto";
|
|
14529
14687
|
var retrievedAt3 = "2026-08-10T00:00:00.000Z";
|
|
14530
14688
|
var docs2 = "docs/RFC/runtime-capability-profiles-revised.md";
|
|
@@ -14608,14 +14766,14 @@ var sourceClaims = [
|
|
|
14608
14766
|
"discovery",
|
|
14609
14767
|
"stable skill discovery",
|
|
14610
14768
|
"OpenCode discovers native project and user skills.",
|
|
14611
|
-
"
|
|
14769
|
+
"source-observed"
|
|
14612
14770
|
],
|
|
14613
14771
|
[
|
|
14614
14772
|
"invocation.skills",
|
|
14615
14773
|
"invocation",
|
|
14616
14774
|
"stable skill invocation",
|
|
14617
14775
|
"OpenCode invokes a discovered skill through its native skill tool.",
|
|
14618
|
-
"
|
|
14776
|
+
"source-observed"
|
|
14619
14777
|
],
|
|
14620
14778
|
[
|
|
14621
14779
|
"discovery.agents",
|
|
@@ -14753,7 +14911,7 @@ var opencodeRuntimeEvidence = Object.freeze([
|
|
|
14753
14911
|
...betaClaims
|
|
14754
14912
|
]);
|
|
14755
14913
|
|
|
14756
|
-
// packages/adapters/pi/
|
|
14914
|
+
// packages/adapters/src/pi/materialize.ts
|
|
14757
14915
|
import { resolve as resolve8 } from "node:path";
|
|
14758
14916
|
var marker7 = "<!-- portable-capabilities:owned pi -->";
|
|
14759
14917
|
function destination6(value) {
|
|
@@ -14774,15 +14932,15 @@ function confined7(root, path9) {
|
|
|
14774
14932
|
}
|
|
14775
14933
|
function render7(operation) {
|
|
14776
14934
|
const skill = operation.destination.match(/skills\/skill\/([^/]+)$/);
|
|
14777
|
-
|
|
14935
|
+
const name = skill?.[1];
|
|
14936
|
+
if (!name) return `${marker7}
|
|
14778
14937
|
${operation.content}`;
|
|
14779
|
-
return
|
|
14780
|
-
name
|
|
14781
|
-
description:
|
|
14782
|
-
|
|
14783
|
-
|
|
14784
|
-
|
|
14785
|
-
`;
|
|
14938
|
+
return renderSkillDocument({
|
|
14939
|
+
name,
|
|
14940
|
+
description: operation.description,
|
|
14941
|
+
marker: marker7,
|
|
14942
|
+
content: operation.content
|
|
14943
|
+
});
|
|
14786
14944
|
}
|
|
14787
14945
|
function transform2(operation) {
|
|
14788
14946
|
if (operation.format !== "json")
|
|
@@ -14846,7 +15004,7 @@ function preparePiMaterialization(plan, root, ..._options) {
|
|
|
14846
15004
|
});
|
|
14847
15005
|
}
|
|
14848
15006
|
|
|
14849
|
-
// packages/adapters/pi/
|
|
15007
|
+
// packages/adapters/src/pi/runtime-descriptor.ts
|
|
14850
15008
|
var piRuntimeDescriptor = {
|
|
14851
15009
|
schemaVersion: "1.0",
|
|
14852
15010
|
id: "pi",
|
|
@@ -14924,7 +15082,7 @@ var piRuntimeDescriptor = {
|
|
|
14924
15082
|
]
|
|
14925
15083
|
};
|
|
14926
15084
|
|
|
14927
|
-
// packages/adapters/pi/
|
|
15085
|
+
// packages/adapters/src/pi/runtime-evidence.ts
|
|
14928
15086
|
import { createHash as createHash13 } from "node:crypto";
|
|
14929
15087
|
var digest8 = (value) => createHash13("sha256").update(value).digest("hex");
|
|
14930
15088
|
var observedAt2 = "2026-08-08T04:24:00-05:00";
|
|
@@ -14990,7 +15148,7 @@ var piRuntimeEvidence = [
|
|
|
14990
15148
|
category: "discovery",
|
|
14991
15149
|
subject: "native skill discovery",
|
|
14992
15150
|
assertion: "Pi natively discovers a project skill with extensions disabled.",
|
|
14993
|
-
versionRange: "
|
|
15151
|
+
versionRange: "=0.64.0",
|
|
14994
15152
|
sourceType: "runtime-probe",
|
|
14995
15153
|
source: "pi",
|
|
14996
15154
|
sourceLocator: "packages/conformance/src/tracer/pi-native-evidence.json",
|
|
@@ -15008,7 +15166,7 @@ var piRuntimeEvidence = [
|
|
|
15008
15166
|
category: "invocation",
|
|
15009
15167
|
subject: "native skill invocation",
|
|
15010
15168
|
assertion: "Pi invokes a discovered project skill with extensions disabled.",
|
|
15011
|
-
versionRange: "
|
|
15169
|
+
versionRange: "=0.64.0",
|
|
15012
15170
|
sourceType: "runtime-probe",
|
|
15013
15171
|
source: "pi",
|
|
15014
15172
|
sourceLocator: "packages/conformance/src/tracer/pi-native-evidence.json",
|
|
@@ -15132,19 +15290,19 @@ function normalizeSetupRequest(input) {
|
|
|
15132
15290
|
// packages/cli/src/setup/service.ts
|
|
15133
15291
|
import { createHash as createHash16 } from "node:crypto";
|
|
15134
15292
|
import { existsSync as existsSync2 } from "node:fs";
|
|
15135
|
-
import { readdir as readdir3, readFile as
|
|
15293
|
+
import { readdir as readdir3, readFile as readFile6 } from "node:fs/promises";
|
|
15136
15294
|
import { dirname as dirname4, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve11 } from "node:path";
|
|
15137
15295
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
15138
15296
|
import { parse as parse3 } from "yaml";
|
|
15139
15297
|
|
|
15140
15298
|
// packages/cli/src/installation/lifecycle.ts
|
|
15141
15299
|
import { createHash as createHash15 } from "node:crypto";
|
|
15142
|
-
import { chmod, copyFile, lstat as lstat2, mkdir as mkdir3, readFile as
|
|
15300
|
+
import { chmod, copyFile, lstat as lstat2, mkdir as mkdir3, readFile as readFile5, rename as rename2, rm, writeFile as writeFile3 } from "node:fs/promises";
|
|
15143
15301
|
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, relative as relative2, resolve as resolve10, sep } from "node:path";
|
|
15144
15302
|
|
|
15145
15303
|
// packages/cli/src/installation/manifest.ts
|
|
15146
15304
|
import { createHash as createHash14 } from "node:crypto";
|
|
15147
|
-
import { mkdir as mkdir2, readFile as
|
|
15305
|
+
import { mkdir as mkdir2, readFile as readFile4, rename, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
15148
15306
|
import { dirname as dirname2, join as join2 } from "node:path";
|
|
15149
15307
|
var installationManifestName = ".portable-capabilities-manifest.json";
|
|
15150
15308
|
var installationJournalName = ".portable-capabilities-journal.json";
|
|
@@ -15163,9 +15321,9 @@ function normalizeDigestValue(value) {
|
|
|
15163
15321
|
function stableManifestDigest(value) {
|
|
15164
15322
|
return digestBytes(new TextEncoder().encode(JSON.stringify(normalizeDigestValue(value))));
|
|
15165
15323
|
}
|
|
15166
|
-
function packageEntriesDigest(
|
|
15324
|
+
function packageEntriesDigest(entries, packageIdentities = []) {
|
|
15167
15325
|
return stableManifestDigest({
|
|
15168
|
-
entries: [...
|
|
15326
|
+
entries: [...entries].sort((left, right) => left.path.localeCompare(right.path)).map((entry) => ({ path: entry.path, digest: entry.digest, mode: entry.mode })),
|
|
15169
15327
|
packageIdentities: [...packageIdentities].sort(
|
|
15170
15328
|
(left, right) => left.lockPath.localeCompare(right.lockPath)
|
|
15171
15329
|
)
|
|
@@ -15198,7 +15356,7 @@ function verifyInstallationManifestDigest(manifest) {
|
|
|
15198
15356
|
}
|
|
15199
15357
|
}
|
|
15200
15358
|
async function digestFile(path9) {
|
|
15201
|
-
return digestBytes(await
|
|
15359
|
+
return digestBytes(await readFile4(path9));
|
|
15202
15360
|
}
|
|
15203
15361
|
function manifestPath(targetRoot) {
|
|
15204
15362
|
return join2(targetRoot, installationManifestName);
|
|
@@ -15209,7 +15367,7 @@ function journalPath(targetRoot) {
|
|
|
15209
15367
|
async function readInstallationManifest(targetRoot) {
|
|
15210
15368
|
try {
|
|
15211
15369
|
const parsed = JSON.parse(
|
|
15212
|
-
await
|
|
15370
|
+
await readFile4(manifestPath(targetRoot), "utf8")
|
|
15213
15371
|
);
|
|
15214
15372
|
if (parsed.schemaVersion !== "1.1.0" || !Array.isArray(parsed.entries)) {
|
|
15215
15373
|
throw new Error("Invalid installation manifest shape");
|
|
@@ -15486,6 +15644,19 @@ async function assertPlanPathsSafe(targetRoot, plan) {
|
|
|
15486
15644
|
}
|
|
15487
15645
|
async function executePreparedInstallation(options) {
|
|
15488
15646
|
const manifest = await readInstallationManifest(options.targetRoot);
|
|
15647
|
+
const operation = options.preparedOperation ?? "install";
|
|
15648
|
+
if (options.preparedDiagnostics?.length) {
|
|
15649
|
+
return result(operation, "degraded", {
|
|
15650
|
+
ok: false,
|
|
15651
|
+
diagnostics: options.preparedDiagnostics
|
|
15652
|
+
});
|
|
15653
|
+
}
|
|
15654
|
+
if (options.preparedMutations.length === 0) {
|
|
15655
|
+
return result(operation, "degraded", {
|
|
15656
|
+
ok: false,
|
|
15657
|
+
diagnostics: ["No prepared mutations can be installed"]
|
|
15658
|
+
});
|
|
15659
|
+
}
|
|
15489
15660
|
const duplicatePaths = /* @__PURE__ */ new Set();
|
|
15490
15661
|
for (const mutation of options.preparedMutations) {
|
|
15491
15662
|
if (duplicatePaths.has(mutation.path)) {
|
|
@@ -15514,7 +15685,7 @@ async function executePreparedInstallation(options) {
|
|
|
15514
15685
|
const exists = await pathExists(target);
|
|
15515
15686
|
if (mutation.ownershipIntent === "preserve-user" && exists) continue;
|
|
15516
15687
|
if (exists && mutation.kind === "write" && mutation.ownershipIntent === "own") {
|
|
15517
|
-
const current = await
|
|
15688
|
+
const current = await readFile5(target, "utf8");
|
|
15518
15689
|
const ownedEntry = manifest?.entries.find((entry) => entry.path === mutation.path);
|
|
15519
15690
|
const isManifestOwned = ownedEntry !== void 0 && await digestFile(target) === ownedEntry.digest;
|
|
15520
15691
|
if (!current.includes("portable-capabilities:owned") && !isManifestOwned)
|
|
@@ -15560,7 +15731,6 @@ async function executePreparedInstallation(options) {
|
|
|
15560
15731
|
packageIdentities,
|
|
15561
15732
|
entries: nextEntries
|
|
15562
15733
|
};
|
|
15563
|
-
const operation = options.preparedOperation ?? "install";
|
|
15564
15734
|
if (options.dryRun)
|
|
15565
15735
|
return result(operation, manifest ? "healthy" : "missing", {
|
|
15566
15736
|
dryRun: true,
|
|
@@ -15595,63 +15765,6 @@ async function statusInstallation(targetRoot) {
|
|
|
15595
15765
|
manifest
|
|
15596
15766
|
});
|
|
15597
15767
|
}
|
|
15598
|
-
async function removeInstallation(targetRoot, faultInjector, capabilityIds) {
|
|
15599
|
-
const manifest = await readInstallationManifest(targetRoot);
|
|
15600
|
-
if (!manifest) return result("remove", "missing", { ok: false });
|
|
15601
|
-
const selected = new Set(capabilityIds ?? []);
|
|
15602
|
-
const scoped = (path9) => {
|
|
15603
|
-
if (selected.size === 0) return true;
|
|
15604
|
-
const normalized = path9.replaceAll("\\", "/");
|
|
15605
|
-
return [...selected].some(
|
|
15606
|
-
(id) => normalized.includes(`/skills/${id}/`) || normalized.endsWith(`/skills/${id}`)
|
|
15607
|
-
);
|
|
15608
|
-
};
|
|
15609
|
-
const classifications = await classifyManifestEntries(manifest);
|
|
15610
|
-
const unchanged = new Set(
|
|
15611
|
-
classifications.unchanged.filter((entry) => scoped(entry.path)).map((entry) => entry.path)
|
|
15612
|
-
);
|
|
15613
|
-
const removes = manifest.entries.filter((entry) => unchanged.has(entry.path)).map((entry) => entry.path);
|
|
15614
|
-
const preserved = manifest.entries.filter((entry) => !unchanged.has(entry.path));
|
|
15615
|
-
const nextManifest = preserved.length ? (() => {
|
|
15616
|
-
const entries2 = Object.freeze(preserved);
|
|
15617
|
-
const preservedPaths = new Set(entries2.map((entry) => entry.path));
|
|
15618
|
-
const packageIdentities = Object.freeze(
|
|
15619
|
-
manifest.packageIdentities.filter((identity3) => preservedPaths.has(identity3.lockPath))
|
|
15620
|
-
);
|
|
15621
|
-
const packageDigest = packageEntriesDigest(entries2, packageIdentities);
|
|
15622
|
-
const base = {
|
|
15623
|
-
runtimeId: manifest.runtimeId,
|
|
15624
|
-
packageVersion: manifest.packageVersion,
|
|
15625
|
-
targetRoot: manifest.targetRoot,
|
|
15626
|
-
journalVersion: manifest.journalVersion,
|
|
15627
|
-
lifecycleState: "modified",
|
|
15628
|
-
packageIdentities,
|
|
15629
|
-
entries: entries2
|
|
15630
|
-
};
|
|
15631
|
-
return {
|
|
15632
|
-
...manifest,
|
|
15633
|
-
...base,
|
|
15634
|
-
packageDigest,
|
|
15635
|
-
installationDigest: installationOwnershipDigest(packageDigest, base)
|
|
15636
|
-
};
|
|
15637
|
-
})() : void 0;
|
|
15638
|
-
return commitPlan(
|
|
15639
|
-
"remove",
|
|
15640
|
-
{
|
|
15641
|
-
sourceRoot: targetRoot,
|
|
15642
|
-
targetRoot,
|
|
15643
|
-
runtimeId: manifest.runtimeId,
|
|
15644
|
-
packageVersion: manifest.packageVersion,
|
|
15645
|
-
...faultInjector ? { faultInjector } : {}
|
|
15646
|
-
},
|
|
15647
|
-
{
|
|
15648
|
-
writes: [],
|
|
15649
|
-
removes,
|
|
15650
|
-
preserved: preserved.map((entry) => entry.path),
|
|
15651
|
-
...nextManifest ? { nextManifest } : {}
|
|
15652
|
-
}
|
|
15653
|
-
);
|
|
15654
|
-
}
|
|
15655
15768
|
|
|
15656
15769
|
// packages/cli/src/setup/service.ts
|
|
15657
15770
|
function roleFacet(role, name) {
|
|
@@ -15712,7 +15825,7 @@ async function loadCanonicalArtifact(catalogRoot, capabilityId) {
|
|
|
15712
15825
|
if (!capabilityId || /[\\/]/u.test(capabilityId))
|
|
15713
15826
|
throw new Error("capability IDs must be single path segments");
|
|
15714
15827
|
const file = resolve11(catalogRoot, "roles", `${capabilityId}.yaml`);
|
|
15715
|
-
const role = parse3(await
|
|
15828
|
+
const role = parse3(await readFile6(file, "utf8"));
|
|
15716
15829
|
if (role.schemaVersion !== "1.0" || role.id !== capabilityId || !role.purpose || !Array.isArray(role.inputs) || !role.output || !role.family || !role.taxonomy || !Array.isArray(role.precedence) || !Array.isArray(role.requiredBehavior) || !Array.isArray(role.forbiddenBehavior) || !Array.isArray(role.evaluation?.criteria)) {
|
|
15717
15830
|
throw new Error(`Invalid canonical capability: ${file}`);
|
|
15718
15831
|
}
|
|
@@ -15721,7 +15834,7 @@ async function loadCanonicalArtifact(catalogRoot, capabilityId) {
|
|
|
15721
15834
|
const schemaRelativePath = relative3(resolve11(catalogRoot), schemaFile);
|
|
15722
15835
|
if (isAbsolute3(schemaRelativePath) || schemaRelativePath.startsWith(".."))
|
|
15723
15836
|
throw new Error(`Canonical output schema escapes catalog: ${role.output.schema}`);
|
|
15724
|
-
const schemaContent = await
|
|
15837
|
+
const schemaContent = await readFile6(schemaFile, "utf8");
|
|
15725
15838
|
const contract = operationalContract(role);
|
|
15726
15839
|
const contractContent = `${JSON.stringify(
|
|
15727
15840
|
{ ...role, output: { ...role.output, schema: "resources/output.schema.json" } },
|
|
@@ -15794,6 +15907,27 @@ function previewSetup(request, artifact, descriptor, claims, ownershipManifest)
|
|
|
15794
15907
|
const body = { ...plan, selectedSurfaces, conversions, conflicts };
|
|
15795
15908
|
return { ...body, digest: stableDigest(body) };
|
|
15796
15909
|
}
|
|
15910
|
+
function composeInstallationPlan(previews, artifacts, runtimeId) {
|
|
15911
|
+
const first = previews[0]?.installationPlan;
|
|
15912
|
+
if (!first) throw new Error("at least one installation plan is required");
|
|
15913
|
+
const operations = previews.flatMap((preview, index) => {
|
|
15914
|
+
const capabilityId = artifacts[index]?.id;
|
|
15915
|
+
if (!capabilityId) throw new Error("installation plan is missing its capability");
|
|
15916
|
+
return preview.installationPlan.operations.map((operation) => ({
|
|
15917
|
+
...operation,
|
|
15918
|
+
id: `${capabilityId}:${operation.id}`,
|
|
15919
|
+
sourceProjectionOperationId: `${capabilityId}:${operation.sourceProjectionOperationId}`
|
|
15920
|
+
}));
|
|
15921
|
+
});
|
|
15922
|
+
const base = {
|
|
15923
|
+
schemaVersion: first.schemaVersion,
|
|
15924
|
+
id: `installation:${runtimeId}:${artifacts.map((artifact) => artifact.id).join(",")}`,
|
|
15925
|
+
runtimeId,
|
|
15926
|
+
scope: first.scope,
|
|
15927
|
+
operations
|
|
15928
|
+
};
|
|
15929
|
+
return { ...base, digest: stableDigest(base) };
|
|
15930
|
+
}
|
|
15797
15931
|
function defaultCatalogRoot() {
|
|
15798
15932
|
const moduleDir = dirname4(fileURLToPath4(import.meta.url));
|
|
15799
15933
|
const packagedCatalog = [resolve11(moduleDir, "catalog"), resolve11(moduleDir, "../catalog")].find(
|
|
@@ -15852,23 +15986,33 @@ async function executeSetupSelection(request, artifacts, descriptor, claims, con
|
|
|
15852
15986
|
...context.faultInjector ? { faultInjector: context.faultInjector } : {}
|
|
15853
15987
|
};
|
|
15854
15988
|
const runtime = resolveProductionRuntime(executionRequest.runtimeId);
|
|
15855
|
-
const lifecycle = executionRequest.intent === "setup" || executionRequest.intent === "update" ? await
|
|
15856
|
-
|
|
15857
|
-
|
|
15858
|
-
|
|
15859
|
-
|
|
15860
|
-
)
|
|
15861
|
-
|
|
15862
|
-
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15989
|
+
const lifecycle = executionRequest.intent === "setup" || executionRequest.intent === "update" || executionRequest.intent === "remove" ? await (async () => {
|
|
15990
|
+
const installationPlan = composeInstallationPlan(
|
|
15991
|
+
previews,
|
|
15992
|
+
planningArtifacts,
|
|
15993
|
+
executionRequest.runtimeId
|
|
15994
|
+
);
|
|
15995
|
+
const prepared = await runtime.prepare(installationPlan, targetRoot);
|
|
15996
|
+
if (prepared.runtimeId !== installationPlan.runtimeId || prepared.planId !== installationPlan.id) {
|
|
15997
|
+
throw new Error(`Materializer returned an invalid ${executionRequest.runtimeId} plan`);
|
|
15998
|
+
}
|
|
15999
|
+
const duplicatePath = prepared.mutations.map((mutation) => mutation.path).find((path9, index, paths) => paths.indexOf(path9) !== index);
|
|
16000
|
+
if (duplicatePath)
|
|
16001
|
+
throw new Error(`Selection produced duplicate prepared path: ${duplicatePath}`);
|
|
16002
|
+
return executePreparedInstallation({
|
|
16003
|
+
...lifecycleOptions,
|
|
16004
|
+
preparedOperation: executionRequest.intent === "update" ? "upgrade" : executionRequest.intent === "remove" ? "remove" : "install",
|
|
16005
|
+
preparedMutations: prepared.mutations,
|
|
16006
|
+
...prepared.diagnostics ? {
|
|
16007
|
+
preparedDiagnostics: prepared.diagnostics.map(
|
|
16008
|
+
(diagnostic6) => `${diagnostic6.kind}: ${diagnostic6.message}`
|
|
16009
|
+
)
|
|
16010
|
+
} : {}
|
|
16011
|
+
});
|
|
16012
|
+
})() : await statusInstallation(targetRoot);
|
|
15866
16013
|
return { request, previews, lifecycle };
|
|
15867
16014
|
}
|
|
15868
16015
|
|
|
15869
|
-
// packages/cli/src/wizard.ts
|
|
15870
|
-
import { execFileSync } from "node:child_process";
|
|
15871
|
-
|
|
15872
16016
|
// node_modules/.pnpm/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
15873
16017
|
import { styleText } from "node:util";
|
|
15874
16018
|
import { stdout, stdin } from "node:process";
|
|
@@ -17076,6 +17220,73 @@ ${r2}
|
|
|
17076
17220
|
}
|
|
17077
17221
|
}).prompt();
|
|
17078
17222
|
|
|
17223
|
+
// packages/cli/src/setup/probe.ts
|
|
17224
|
+
import { execFileSync } from "node:child_process";
|
|
17225
|
+
var executables = Object.freeze({
|
|
17226
|
+
antigravity: "agy",
|
|
17227
|
+
"claude-code": "claude",
|
|
17228
|
+
codex: "codex",
|
|
17229
|
+
dcode: "dcode",
|
|
17230
|
+
"oh-my-pi": "omp",
|
|
17231
|
+
opencode: "opencode",
|
|
17232
|
+
pi: "pi"
|
|
17233
|
+
});
|
|
17234
|
+
function resolveRuntimeProbe(runtimeId) {
|
|
17235
|
+
const runtime = resolveProductionRuntime(runtimeId);
|
|
17236
|
+
const canonicalId = runtime.descriptor.id;
|
|
17237
|
+
const executable = executables[canonicalId];
|
|
17238
|
+
if (!executable) throw new Error(`No runtime probe configured for ${canonicalId}`);
|
|
17239
|
+
return {
|
|
17240
|
+
runtimeId: canonicalId,
|
|
17241
|
+
executable,
|
|
17242
|
+
args: ["--version"],
|
|
17243
|
+
supportedVersions: runtime.descriptor.supportedVersions
|
|
17244
|
+
};
|
|
17245
|
+
}
|
|
17246
|
+
function parseVersion2(output) {
|
|
17247
|
+
return output.match(/\bv?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\b/u)?.[1];
|
|
17248
|
+
}
|
|
17249
|
+
function defaultRun(probe) {
|
|
17250
|
+
return execFileSync(probe.executable, probe.args, {
|
|
17251
|
+
encoding: "utf8",
|
|
17252
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
17253
|
+
timeout: 5e3
|
|
17254
|
+
});
|
|
17255
|
+
}
|
|
17256
|
+
function probeRuntimeVersion(runtimeId, options = {}) {
|
|
17257
|
+
const probe = resolveRuntimeProbe(runtimeId);
|
|
17258
|
+
let output;
|
|
17259
|
+
try {
|
|
17260
|
+
output = (options.run ?? defaultRun)(probe);
|
|
17261
|
+
} catch (error) {
|
|
17262
|
+
const code = error.code;
|
|
17263
|
+
const unavailable = code === "ENOENT" || code === "EACCES";
|
|
17264
|
+
return {
|
|
17265
|
+
status: unavailable ? "unavailable" : "failed",
|
|
17266
|
+
runtimeId: probe.runtimeId,
|
|
17267
|
+
executable: probe.executable,
|
|
17268
|
+
reason: unavailable ? `${probe.executable} is not installed or is not executable` : error instanceof Error ? error.message : String(error)
|
|
17269
|
+
};
|
|
17270
|
+
}
|
|
17271
|
+
const version = parseVersion2(output);
|
|
17272
|
+
if (!version)
|
|
17273
|
+
return {
|
|
17274
|
+
status: "unknown-version",
|
|
17275
|
+
runtimeId: probe.runtimeId,
|
|
17276
|
+
executable: probe.executable,
|
|
17277
|
+
reason: "version probe returned no parseable semantic version"
|
|
17278
|
+
};
|
|
17279
|
+
if (!probe.supportedVersions.some((range) => isRuntimeVersionInRange(range, version)))
|
|
17280
|
+
return {
|
|
17281
|
+
status: "unsupported-version",
|
|
17282
|
+
runtimeId: probe.runtimeId,
|
|
17283
|
+
executable: probe.executable,
|
|
17284
|
+
version,
|
|
17285
|
+
reason: `version ${version} is outside the supported runtime ranges`
|
|
17286
|
+
};
|
|
17287
|
+
return { status: "detected", runtimeId: probe.runtimeId, executable: probe.executable, version };
|
|
17288
|
+
}
|
|
17289
|
+
|
|
17079
17290
|
// packages/cli/src/wizard.ts
|
|
17080
17291
|
var supportedRuntimes = [...productionRuntimeRegistry.keys()];
|
|
17081
17292
|
function unwrap(value) {
|
|
@@ -17086,17 +17297,6 @@ function unwrap(value) {
|
|
|
17086
17297
|
}
|
|
17087
17298
|
return value;
|
|
17088
17299
|
}
|
|
17089
|
-
function detectRuntimeVersion(runtime) {
|
|
17090
|
-
try {
|
|
17091
|
-
const output = execFileSync(runtime, ["--version"], {
|
|
17092
|
-
encoding: "utf8",
|
|
17093
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
17094
|
-
});
|
|
17095
|
-
return output.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0] ?? "unknown";
|
|
17096
|
-
} catch {
|
|
17097
|
-
return "unknown";
|
|
17098
|
-
}
|
|
17099
|
-
}
|
|
17100
17300
|
async function runInstallWizard() {
|
|
17101
17301
|
intro("Portable Capabilities setup");
|
|
17102
17302
|
try {
|
|
@@ -17116,6 +17316,12 @@ async function runInstallWizard() {
|
|
|
17116
17316
|
options: supportedRuntimes.map((value) => ({ value, label: value }))
|
|
17117
17317
|
})
|
|
17118
17318
|
);
|
|
17319
|
+
const probe = probeRuntimeVersion(runtime);
|
|
17320
|
+
if (probe.status !== "detected" || !probe.version) {
|
|
17321
|
+
log.error(`${runtime}: ${probe.reason ?? probe.status}`);
|
|
17322
|
+
process.exitCode = 4;
|
|
17323
|
+
return;
|
|
17324
|
+
}
|
|
17119
17325
|
const target = String(
|
|
17120
17326
|
unwrap(
|
|
17121
17327
|
await text({
|
|
@@ -17133,7 +17339,7 @@ async function runInstallWizard() {
|
|
|
17133
17339
|
);
|
|
17134
17340
|
const request = normalizeSetupRequest({
|
|
17135
17341
|
runtimeId: runtime,
|
|
17136
|
-
runtimeVersion:
|
|
17342
|
+
runtimeVersion: probe.version,
|
|
17137
17343
|
scope: "project",
|
|
17138
17344
|
projectDirectory: target,
|
|
17139
17345
|
capabilityIds,
|
|
@@ -17155,7 +17361,7 @@ async function runInstallWizard() {
|
|
|
17155
17361
|
runtimeEntry.claims,
|
|
17156
17362
|
{ sourceRoot: process.cwd(), packageVersion: cliVersion }
|
|
17157
17363
|
);
|
|
17158
|
-
if (!result2.lifecycle
|
|
17364
|
+
if (!result2.lifecycle?.ok) {
|
|
17159
17365
|
for (const diagnostic6 of result2.lifecycle?.diagnostics ?? ["Approval required."])
|
|
17160
17366
|
log.error(diagnostic6);
|
|
17161
17367
|
process.exitCode = 4;
|