From b946448d023136e15209c6d27afb2ad198e2ac28 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 30 Jul 2026 22:38:40 +0800 Subject: [PATCH 01/11] fix: restore LinkCapabilityDecisionV1 compliance anchor --- content/duplication-inventory.json | 2 +- content/instructions/17-compliance.instructions.md | 2 +- content/skills/compliance/SKILL.md | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/content/duplication-inventory.json b/content/duplication-inventory.json index 4c574f4..5a7e236 100644 --- a/content/duplication-inventory.json +++ b/content/duplication-inventory.json @@ -1,6 +1,6 @@ { "schemaVersion": "ControlContentDuplicationInventoryV1", - "sourceBundleDigest": "72853602cb110e69065c248c4f12410ca3e4f491c9828a121b82e562b64261a9", + "sourceBundleDigest": "80b768bc2bc07fc49cda6c11635441e5930459ceb9715ada5e66bb196268beda", "thresholds": { "minParagraphChars": 100, "sectionThreshold": 0.94, diff --git a/content/instructions/17-compliance.instructions.md b/content/instructions/17-compliance.instructions.md index 3aefa23..5e0a336 100644 --- a/content/instructions/17-compliance.instructions.md +++ b/content/instructions/17-compliance.instructions.md @@ -149,7 +149,7 @@ version: 1.15.3 | FC2 | 报告文件已写入(chat 豁免) | | FC3 | CP 按序执行(dev/fix;其他 N/A) | | FC4 | 文件名/路径合规(`NN--` 双横杠开头;本轮无报告产物时标 N/A) | -| FC5 | `ArtifactDeliveryManifestV1` 完整对账;`UserFacingArtifactSetV1` required hidden=0、计数守恒;semantic name/action/order 与 capability renderer 有效 | +| FC5 | `ArtifactDeliveryManifestV1` 完整对账;`UserFacingArtifactSetV1` required hidden=0、计数守恒;semantic name/action/order 与 `LinkCapabilityDecisionV1` capability renderer 有效 | | FC6 | 新增 DevCodex 规范资产 `.md` 行数检查(instructions / skills / prompts / templates / 规范源等超 500 行须按 C13 拆分;业务项目需求、技术方案、报告和正式项目文档不因 C13 强制拆分) | | FC7 | 用户决策选项与报告决策点必带推荐 + 理由:所有 AskUserQuestion / 多选项呈现 / CP 范围选择 / 方案对比 / analyze-audit 报告决策点必须有且仅有 1 个 🟢 推荐项(首位置 + 标签含"(推荐)"或表格标 ⭐),并附一句话推荐理由;**完成态「下一步/后续建议」适用 UniqueNextStepRecommendationGate**(禁止用「或/或者」并列 ≥2 条可执行路径;探针 `classifyNextStepOrForkSample`);没有可推荐动作时必须显式写 `推荐:无后续动作` 与原因 | diff --git a/content/skills/compliance/SKILL.md b/content/skills/compliance/SKILL.md index 803dfab..98ff2ea 100644 --- a/content/skills/compliance/SKILL.md +++ b/content/skills/compliance/SKILL.md @@ -167,7 +167,7 @@ chat / 纯确认短答:TTFV 可 `N/A + skipReason=chat-or-ack`。 | FC2 | 报告文件已写入(chat 豁免) | | FC3 | CP 按序执行(dev/fix;其他 N/A) | | FC4 | 文件名/路径合规(`NN--` 双横杠开头) | -| FC5 | `ArtifactDeliveryManifestV1` 完整对账;`UserFacingArtifactSetV1` required hidden=0、计数守恒;semantic name/action/order 与 capability renderer 有效 | +| FC5 | `ArtifactDeliveryManifestV1` 完整对账;`UserFacingArtifactSetV1` required hidden=0、计数守恒;semantic name/action/order 与 `LinkCapabilityDecisionV1` capability renderer 有效 | | FC6 | 新增 DevCodex 规范资产 `.md` 行数检查(instructions / skills / prompts / templates / 规范源等超 500 行须按 [C13](../../instructions/01-common.instructions.md) 拆分;业务项目需求、技术方案、报告和正式项目文档不因 C13 强制拆分) | | FC7 | 用户决策选项与报告决策点必带推荐 + 理由:所有 AskUserQuestion / 多选项呈现 / CP 选项 / 方案对比 / analyze-audit 报告决策点必须有且仅有 1 个推荐项,推荐项置首且说明推荐理由;**完成态「下一步/后续建议」适用 UniqueNextStepRecommendationGate**(禁止「或」并列双主动作);无后续动作时写明 `推荐:无后续动作` | @@ -257,4 +257,3 @@ chat / 纯确认短答:TTFV 可 `N/A + skipReason=chat-or-ack`。 | 连续 2 次同类偏差 | 升级分析(追加记忆 `⚠️连续违规` + 报告增加「规范偏差分析」章节);**不自动进入 self-fix**(防递归) | | 文件路径不符合 [`02-output-paths.instructions.md`](../../instructions/02-output-paths.instructions.md) | 立即停止创建,迁移到正确路径 | | 规范文件修改后引用未同步 | 交叉验证后修正 | - From ff5be17ebe977b8ba702025d359d71ddc1c5631a Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 30 Jul 2026 22:45:42 +0800 Subject: [PATCH 02/11] fix: refresh Skill portfolio after compliance sync --- content/skills/portfolio.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/skills/portfolio.json b/content/skills/portfolio.json index 96f5071..48a8962 100644 --- a/content/skills/portfolio.json +++ b/content/skills/portfolio.json @@ -6,7 +6,7 @@ "skillsPattern": "content/skills/*/SKILL.md", "optionalSidecar": "content/skills/*/devcodex.skill.json", "registry": "plugin.json", - "sourceDigest": "8156f518f1fc788a191ac72e4536d1771b25b1c28163c5034ad7280567d82af8", + "sourceDigest": "035975abb24e0760fd9fd23baf3b7b170e387e500838d9a460c5b20bf8120a2e", "sidecarDigest": "774105d7947b340d15d17115fcb8e37b62ae545cf553f06126d529184fd74872", "pluginDigest": "705fe7c86c7225b67756749be5bb3b14a1ee3bffa386483a9ab61dc971f419ae", "portfolioEvidence": "content/skills/portfolio-evidence.json", @@ -14,7 +14,7 @@ "consumerInventoryFileCount": 454, "consumerInventoryDigest": "2c4a1c119386da62a33c92b9c9141e3cfab88a3030af139ff2783fdee21b8504", "consumerProjectionDigest": "c35460a60f21bf352ddac0144e8ee4db59581a7d39f4f548f3ce599ed6cc9a55", - "portfolioInputDigest": "4b4d34eb222086fb14ffe92f1956eb9dade5304215293e00ea3d6d98b050687a" + "portfolioInputDigest": "f82d4eee26cbc18dfb3545b2053f165b5319e9f6cf76130a385bfe2969772e0a" }, "ordering": "skills.id asc; graph edges from/to asc", "summary": { @@ -4417,8 +4417,8 @@ "content/skills/compliance/SKILL.md" ], "source": "content/skills/compliance/SKILL.md", - "hash": "5cbea606761a52d3fe0958fb1ba07c0cd61c2913a2ea170599b6d8d3931dc274", - "sourceBytes": 23431, + "hash": "37aea8ea48e577d492ac71d9496b6fa71cd43fab5c8f6cc598ca8030ca96e15a", + "sourceBytes": 23457, "version": "1.15.3", "lifecycleState": "active", "dependencies": [ From 7525de40a7155ff4f045f3e6b68abc1758038eca Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 30 Jul 2026 23:16:32 +0800 Subject: [PATCH 03/11] fix: refresh Skill route runtime evidence --- hooks/_runtime/host-skill-route-capabilities.v1.json | 6 +++--- hooks/_runtime/workflow-root-registry.v1.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hooks/_runtime/host-skill-route-capabilities.v1.json b/hooks/_runtime/host-skill-route-capabilities.v1.json index 48f3a19..98d19f9 100644 --- a/hooks/_runtime/host-skill-route-capabilities.v1.json +++ b/hooks/_runtime/host-skill-route-capabilities.v1.json @@ -13,10 +13,10 @@ "status": "PASS", "testedVersion": "codex-cli 0.145.0", "protocol": "MCP 2024-11-05", - "runtimeContractDigest": "8e6fd2aa9f8dd4f865ff76b670f3f4a2f61b8ccd4c37546d84579c5d6efd8b41", + "runtimeContractDigest": "e6f509af0135110586eb6c9fc0fe0e0a2ad3f33ed27d1711025246358904fee3", "hostAdapterDigest": "6ba881f7fd7eba6297e1fcb8c55da09abbd5f47a42661fb2269f38d05e014139", - "evidenceDigest": "ce8fb9c145934bb59f2ce1f5d253a21fb9ba33218a728d4b23b7a0c45fe2cc53", - "evidenceRef": "E:/Worker/devcodex/.audit-state/content-root-s15-codex-production-20260730.json", + "evidenceDigest": "2e3a291b99d65f9a4fa2cf7b871c84c623ef54536686653ce9a2473f4b756f2c", + "evidenceRef": "E:/Worker/devcodex/.audit-state/content-root-s15-codex-production-20260730-v51.json", "entrySurface": "codex exec --ephemeral", "bootstrapDelivery": "user-global hooks.json UserPromptSubmit", "defaultEligible": true diff --git a/hooks/_runtime/workflow-root-registry.v1.json b/hooks/_runtime/workflow-root-registry.v1.json index 243670b..8b6b70d 100644 --- a/hooks/_runtime/workflow-root-registry.v1.json +++ b/hooks/_runtime/workflow-root-registry.v1.json @@ -3,7 +3,7 @@ "sourceEvidence": [ { "ref": "content:instructions/01-common.instructions.md", - "digest": "23c07d57acacae34fb5cd065ce784ea8de2d61a85faa769cf1fdf990500ffd84" + "digest": "b0d7262f20704c25dc1d96c6e18649f0594978561a1e5bdaf4773b7811627fc8" }, { "ref": "content:skills/routing/SKILL.md", @@ -11,10 +11,10 @@ }, { "ref": "scripts/lib/host-parity-scorecard.js", - "digest": "4e4fabceba316db62aeb564f060933a4f2d61e1420ac4978103853c7f2d369a2" + "digest": "e2aa31b083f387062d93c4ec00611ecf5b41a195918ef966895c6d25f37b19e5" } ], - "sourceDigest": "b7aea8693be3781cdd63bbc3ab6764f0005240c3c592fc76c4e432419d64d4bb", + "sourceDigest": "8a60bb3fd8bc0b986ff44e624030dedf197652d5a6a3dcd627384258e583facc", "baseBundles": { "chat": [], "resume": [ From 8cfbb42fd72bcad3c66b2a37ac0c40aa13cf1919 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 30 Jul 2026 23:37:40 +0800 Subject: [PATCH 04/11] test: expose global install smoke host diagnostics --- scripts/test-global-install-smoke.js | 31 +++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/scripts/test-global-install-smoke.js b/scripts/test-global-install-smoke.js index 8be8c6d..91fa733 100644 --- a/scripts/test-global-install-smoke.js +++ b/scripts/test-global-install-smoke.js @@ -244,12 +244,37 @@ const statusPayload = JSON.parse(runCommand(binPath, ['status', '--json'], { cwd: workspace, env: installedEnv }).stdout) +function summarizeHostRuntime(hosts) { + return JSON.stringify( + hosts.map(host => ({ + host: host.host, + configured: host.configured, + adapterReady: host.adapterReady, + contractStatus: host.contractStatus, + nativeStatus: host.nativeStatus, + ready: host.ready, + issues: host.issues + })), + null, + 2 + ) +} + assert.strictEqual(statusPayload.ok, true) assert.strictEqual(statusPayload.payload.globalHostRuntime.schemaVersion, 'GlobalHostRuntimeVerificationV2') assert.strictEqual(statusPayload.payload.globalHostRuntime.hosts.length, 5) -assert(statusPayload.payload.globalHostRuntime.hosts.every(host => host.configured === true)) -assert(statusPayload.payload.globalHostRuntime.hosts.every(host => host.adapterReady === true)) -assert(statusPayload.payload.globalHostRuntime.hosts.every(host => host.contractStatus === 'passed')) +assert( + statusPayload.payload.globalHostRuntime.hosts.every(host => host.configured === true), + summarizeHostRuntime(statusPayload.payload.globalHostRuntime.hosts) +) +assert( + statusPayload.payload.globalHostRuntime.hosts.every(host => host.adapterReady === true), + summarizeHostRuntime(statusPayload.payload.globalHostRuntime.hosts) +) +assert( + statusPayload.payload.globalHostRuntime.hosts.every(host => host.contractStatus === 'passed'), + summarizeHostRuntime(statusPayload.payload.globalHostRuntime.hosts) +) assert(statusPayload.payload.globalHostRuntime.hosts.every(host => host.ready === false)) assert.strictEqual(statusPayload.payload.globalHostRuntime.overallState, 'degraded') assert.strictEqual( From fd44b7fac48b06cdae03c2e2d4a82167b630dc36 Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 00:04:04 +0800 Subject: [PATCH 05/11] fix: keep Grok adapter ready when registry unverified --- scripts/lib/global-host-runtime-verifier.js | 1 - scripts/test-global-host-config.js | 11 ++++++---- scripts/test-global-host-runtime-verifier.js | 22 ++++++++++++++++++++ scripts/test-host-installation.js | 10 ++++++--- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/scripts/lib/global-host-runtime-verifier.js b/scripts/lib/global-host-runtime-verifier.js index 8fe6598..b6e5301 100644 --- a/scripts/lib/global-host-runtime-verifier.js +++ b/scripts/lib/global-host-runtime-verifier.js @@ -552,7 +552,6 @@ function verifyGlobalHostRuntime(options = {}) { probes.grokStatic = staticGrok issues.push(...staticGrok.issues) if (staticGrok.status === 'failed') contractStatus = 'failed' - else if (staticGrok.status === 'unverified' && contractStatus === 'passed') contractStatus = 'unverified' } const native = nativeVersionProbe(configurationHost.host, common) diff --git a/scripts/test-global-host-config.js b/scripts/test-global-host-config.js index bdb5c66..8b34ee1 100644 --- a/scripts/test-global-host-config.js +++ b/scripts/test-global-host-config.js @@ -451,10 +451,13 @@ assert(managedDriftRuntimeClaude.issues.some(issue => assert.strictEqual(applyGlobalHostConfig({ packageRoot, env, home }).transaction.status, 'committed') const beforeGrokRegistration = inspectGlobalHostConfig({ packageRoot, env, home }) assert.strictEqual(beforeGrokRegistration.ready, false) -assert.strictEqual( - beforeGrokRegistration.hosts.find(host => host.host === 'grok').contractStatus, - 'unverified' -) +const beforeGrokRegistrationHost = beforeGrokRegistration.hosts.find(host => host.host === 'grok') +assert.strictEqual(beforeGrokRegistrationHost.adapterReady, true) +assert.strictEqual(beforeGrokRegistrationHost.contractStatus, 'passed') +assert.strictEqual(beforeGrokRegistrationHost.nativeStatus, 'unverified') +assert(beforeGrokRegistrationHost.issues.some(issue => + issue.code === 'GROK_PLUGIN_REGISTRY_UNVERIFIED' +)) const grokTarget = targets.find(target => target.host === 'grok') const registryFile = path.join(grokTarget.root, 'installed-plugins', 'registry.json') fs.mkdirSync(path.dirname(registryFile), { recursive: true }) diff --git a/scripts/test-global-host-runtime-verifier.js b/scripts/test-global-host-runtime-verifier.js index 0db199f..7b0231d 100644 --- a/scripts/test-global-host-runtime-verifier.js +++ b/scripts/test-global-host-runtime-verifier.js @@ -104,6 +104,28 @@ assert.strictEqual(healthy.hosts.find(host => host.host === 'copilot').contractS assert.strictEqual(healthy.hosts.find(host => host.host === 'copilot').nativeStatus, 'unverified') assert.strictEqual(healthy.hosts.find(host => host.host === 'grok').nativeStatus, 'unverified') +const missingRegistryFile = path.join(grokRoot, 'installed-plugins', 'registry.json') +const missingRegistryContent = fs.readFileSync(missingRegistryFile, 'utf8') +fs.unlinkSync(missingRegistryFile) +const missingGrokRegistry = verifyGlobalHostRuntime({ + configuration: { + mode: 'GlobalOnlyHostConfigModeV1', + workspaceCleanMode: 'GlobalOnlyWorkspaceCleanModeV1', + packageVersion: 'test', + hosts + }, + env, + home, + fs, + spawnSync: spawnProbe +}) +const missingRegistryGrok = missingGrokRegistry.hosts.find(host => host.host === 'grok') +assert.strictEqual(missingRegistryGrok.adapterReady, true) +assert.strictEqual(missingRegistryGrok.contractStatus, 'passed') +assert.strictEqual(missingRegistryGrok.nativeStatus, 'unverified') +assert(missingRegistryGrok.issues.some(issue => issue.code === 'GROK_PLUGIN_REGISTRY_UNVERIFIED')) +fs.writeFileSync(missingRegistryFile, missingRegistryContent, 'utf8') + const deepSpawn = (command, args) => { if ( command === process.execPath && diff --git a/scripts/test-host-installation.js b/scripts/test-host-installation.js index 146bc34..4787b6e 100644 --- a/scripts/test-host-installation.js +++ b/scripts/test-host-installation.js @@ -755,7 +755,11 @@ console.log(`host installation tests passed selectors=5 dryRunWrites=0 collision const inspection = inspectGlobalHostConfig({ packageRoot: ROOT, env, home }) assert.strictEqual(inspection.ready, false) assert.strictEqual(inspection.overallState, 'degraded') - assert.strictEqual(inspection.hosts.find(host => host.host === 'grok').contractStatus, 'unverified') + const grokInspection = inspection.hosts.find(host => host.host === 'grok') + assert.strictEqual(grokInspection.adapterReady, true) + assert.strictEqual(grokInspection.contractStatus, 'passed') + assert.strictEqual(grokInspection.nativeStatus, 'unverified') + assert(grokInspection.issues.some(issue => issue.code === 'GROK_PLUGIN_REGISTRY_UNVERIFIED')) assert.strictEqual(inspection.hosts.length, 5) assert.ok(fs.existsSync(path.join(home, 'gemini-cli-home', '.gemini', 'devcodex', 'global-host-receipt.json'))) assert.ok(fs.existsSync(path.join(home, '.agents', 'devcodex', 'instructions.full.md'))) @@ -860,7 +864,7 @@ console.log(`host installation tests passed selectors=5 dryRunWrites=0 collision const statusAfterGlobalInstallFacts = JSON.parse(statusAfterGlobalInstall.stdout).payload assert.strictEqual(statusAfterGlobalInstallFacts.globalHostConfig.ready, false) assert.strictEqual(statusAfterGlobalInstallFacts.globalHostConfig.overallState, 'degraded') - assert.strictEqual(statusAfterGlobalInstallFacts.entryFiles.instructionProjection.grokPlugin.globalAdapterReady, false) + assert.strictEqual(statusAfterGlobalInstallFacts.entryFiles.instructionProjection.grokPlugin.globalAdapterReady, true) assert.strictEqual(statusAfterGlobalInstallFacts.entryFiles.instructionProjection.grokPlugin.workspaceSourceRequired, false) assert(!statusAfterGlobalInstallFacts.entryFiles.instructionProjection.issues.some(item => item.code === 'HOST_GROK_WORKSPACE_PLUGIN_MISSING' @@ -873,7 +877,7 @@ console.log(`host installation tests passed selectors=5 dryRunWrites=0 collision assert.strictEqual(doctorAfterGlobalInstall.status, 0, doctorAfterGlobalInstall.stderr || doctorAfterGlobalInstall.stdout) const doctorAfterGlobalInstallFacts = JSON.parse(doctorAfterGlobalInstall.stdout).payload assert.strictEqual(doctorAfterGlobalInstallFacts.globalHostConfig.ready, false) - assert.strictEqual(doctorAfterGlobalInstallFacts.installArtifacts.instructionProjection.grokPlugin.globalAdapterReady, false) + assert.strictEqual(doctorAfterGlobalInstallFacts.installArtifacts.instructionProjection.grokPlugin.globalAdapterReady, true) assert.strictEqual(doctorAfterGlobalInstallFacts.installArtifacts.instructionProjection.grokPlugin.workspaceSourceRequired, false) assert(!doctorAfterGlobalInstallFacts.installArtifacts.instructionProjection.issues.some(item => item.code === 'HOST_GROK_WORKSPACE_PLUGIN_MISSING' From cd530aa1f5fa47da22dd42cc011d9a28fb4ca605 Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 00:19:41 +0800 Subject: [PATCH 06/11] fix: make workspace root scan guard cross-platform --- .../_runtime/lifecycle-dangerous-command.cjs | 3 +- scripts/test-workspace-root-scan-ban.js | 28 ++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/hooks/_runtime/lifecycle-dangerous-command.cjs b/hooks/_runtime/lifecycle-dangerous-command.cjs index aa146e3..4f3e4ff 100644 --- a/hooks/_runtime/lifecycle-dangerous-command.cjs +++ b/hooks/_runtime/lifecycle-dangerous-command.cjs @@ -50,7 +50,8 @@ function buildLifecycleDangerousCommandUtils({ * e.g. E:\Worker\queuebit or E:\Worker\queuebit\docs (R-04: no trailing slash required). */ function commandTargetsWorkspaceChild(cmdLower, rootLower) { - const escaped = rootLower.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + const rootInCommand = rootLower.replace(/\//g, '\\') + const escaped = rootInCommand.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') return new RegExp(escaped + '[\\\\/][a-z0-9._-]+', 'i').test(cmdLower) } diff --git a/scripts/test-workspace-root-scan-ban.js b/scripts/test-workspace-root-scan-ban.js index cdf501c..87caa05 100644 --- a/scripts/test-workspace-root-scan-ban.js +++ b/scripts/test-workspace-root-scan-ban.js @@ -9,7 +9,9 @@ const { } = require('./lib/host-parity-scorecard.js') const { buildLifecycleDangerousCommandUtils } = require('../hooks/_runtime/lifecycle-dangerous-command.cjs') -const ROOT = 'E:\\Worker' +const ROOT = process.platform === 'win32' ? 'E:\\Worker' : '/home/runner/work' +const PROJECT = path.join(ROOT, 'queuebit') +const DOCS = path.join(PROJECT, 'docs') function makeUtils(contextRoot = ROOT) { return buildLifecycleDangerousCommandUtils({ @@ -45,24 +47,24 @@ function expectAllow(cmd, label, payloadExtra = {}) { // R-01 sample / original relapse expectBan( - 'Get-ChildItem -Path "E:\\Worker" -Directory -Filter "*queuebit*" -Recurse -Depth 3', + `Get-ChildItem -Path "${ROOT}" -Directory -Filter "*queuebit*" -Recurse -Depth 3`, 'absolute root recurse depth' ) // project scoped allow expectAllow( - 'Get-ChildItem -Path "E:\\Worker\\queuebit\\docs" -Recurse -Filter *.md', + `Get-ChildItem -Path "${DOCS}" -Recurse -Filter *.md`, 'project docs recurse' ) // R-04: first-level child without trailing slash expectAllow( - 'Get-ChildItem -Path "E:\\Worker\\queuebit" -Recurse', + `Get-ChildItem -Path "${PROJECT}" -Recurse`, 'first-level project path' ) // R-02: dir /s -expectBan('dir /s E:\\Worker', 'dir /s workspace root') +expectBan(`dir /s "${ROOT}"`, 'dir /s workspace root') expectBan('dir /s', 'dir /s relative at workspace cwd') // find at workspace root (C16) -expectBan('find E:\\Worker -type f', 'find workspace root') +expectBan(`find "${ROOT}" -type f`, 'find workspace root') // R-03: relative recurse at workspace cwd expectBan('Get-ChildItem -Recurse -Depth 3', 'relative recurse at workspace cwd') expectBan('Get-ChildItem -Recurse', 'relative recurse bare') @@ -70,10 +72,10 @@ expectBan('Get-ChildItem -Recurse', 'relative recurse bare') expectAllow('Get-ChildItem queuebit -Recurse', 'relative child name') expectAllow('Get-ChildItem -Path queuebit -Recurse', 'relative -Path child') // project cwd relative recurse allowed (CONTEXT_ROOT = project) -const projectUtils = makeUtils('E:\\Worker\\queuebit') +const projectUtils = makeUtils(PROJECT) assert.strictEqual( projectUtils.checkDangerousCommand({ - tool_input: { command: 'Get-ChildItem -Recurse', cwd: 'E:\\Worker\\queuebit' } + tool_input: { command: 'Get-ChildItem -Recurse', cwd: PROJECT } }, 'grok'), null, 'relative recurse inside project cwd' @@ -82,20 +84,20 @@ assert.strictEqual( // Probe parity with Hook (R-04) assert.strictEqual( classifyWorkspaceRootScanSample( - 'Get-ChildItem -Path "E:\\Worker\\queuebit" -Recurse', + `Get-ChildItem -Path "${PROJECT}" -Recurse`, { workspaceRoot: ROOT } ), 'project-scoped-ok' ) assert.strictEqual( classifyWorkspaceRootScanSample( - 'Get-ChildItem -Path "E:\\Worker" -Recurse -Depth 3', + `Get-ChildItem -Path "${ROOT}" -Recurse -Depth 3`, { workspaceRoot: ROOT } ), 'workspace-root-recurse' ) assert.strictEqual( - classifyWorkspaceRootScanSample('dir /s E:\\Worker', { workspaceRoot: ROOT }), + classifyWorkspaceRootScanSample(`dir /s "${ROOT}"`, { workspaceRoot: ROOT }), 'workspace-root-recurse' ) assert.strictEqual( @@ -115,10 +117,10 @@ assert.strictEqual( // direct inventory helpers assert.strictEqual(utils.isWorkspaceRootRecursiveInventory( - 'Get-ChildItem -Path "E:\\Worker" -Recurse', ROOT, { cwd: ROOT } + `Get-ChildItem -Path "${ROOT}" -Recurse`, ROOT, { cwd: ROOT } ), true) assert.strictEqual(utils.isWorkspaceRootRecursiveInventory( - 'Get-ChildItem -Path "E:\\Worker\\queuebit" -Recurse', ROOT, { cwd: ROOT } + `Get-ChildItem -Path "${PROJECT}" -Recurse`, ROOT, { cwd: ROOT } ), false) console.log('workspace-root-scan-ban unit OK (R-01..R-04 matrix)') From 48065c6a41e409af8a343abacac58846395565ba Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 00:34:49 +0800 Subject: [PATCH 07/11] fix: keep host parity smoke source-contained --- scripts/test-host-parity-remaining.js | 57 ++++++++++++++++++--------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/scripts/test-host-parity-remaining.js b/scripts/test-host-parity-remaining.js index 6d95de8..ade2c8b 100644 --- a/scripts/test-host-parity-remaining.js +++ b/scripts/test-host-parity-remaining.js @@ -17,8 +17,11 @@ const path = require('path') const { spawnSync } = require('child_process') const { adaptHostOutput, runHostAdapter } = require('../hooks/_runtime/lifecycle-host-adapters.cjs') const { buildLifecycleHookOutput } = require('../hooks/_runtime/lifecycle-hook-output.cjs') -const { composeEntryCheckBlock } = require('./lib/host-parity-scorecard.js') -const { evaluateGrokHostParity } = require('./lib/host-parity-scorecard.js') +const { + composeEntryCheckBlock, + evaluateGrokHostParity, + formatGrokTurnChecklistMarkdown +} = require('./lib/host-parity-scorecard.js') const hookOut = buildLifecycleHookOutput({ env: {}, enforcementMode: 'safety-only' }) @@ -63,19 +66,33 @@ const codexOut = adaptHostOutput('codex', 'PreToolUse', { }) assert.strictEqual(codexOut.hookSpecificOutput.permissionDecision, 'deny') -// Compose entry check + website page exists +function readIfExists(file) { + return fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null +} + +// Compose entry check + HostParity public/source surface. +// website/ is a maintainer-local optional doc site (see website/README.md); +// clean GitHub Actions checkouts must validate source-contained semantics rather +// than requiring untracked generated website docs to exist. const block = composeEntryCheckBlock({ project: 'demo', status: 'PASS' }) assert.match(block, /### DevCodex · 入口检查/) const sitePage = path.join(__dirname, '../website/docs/intro/host-parity-grok.md') -assert.ok(fs.existsSync(sitePage), 'website intro host-parity-grok.md must exist') -const siteText = fs.readFileSync(sitePage, 'utf8') -assert.match(siteText, /devcodex grok/) -assert.match(siteText, /HostParity/) -assert.match(siteText, /GrokTurnChecklist/) -assert.match(siteText, /repairSteps/) -assert.match(siteText, /Skill 强制包|Skill bundle|Intent → Skill/i) -assert.match(siteText, /scan-hygiene|ttfv-first-delivery/) -assert.match(siteText, /UnalignedLedger|U-A1|未对齐|cannotClaim/i) +const siteText = readIfExists(sitePage) +const checklistText = formatGrokTurnChecklistMarkdown() +const hostParitySurface = siteText || checklistText +assert.match(hostParitySurface, /HostParity|GrokTurnChecklist/) +assert.match(hostParitySurface, /GrokTurnChecklist/) +assert.match(hostParitySurface, /scan-hygiene|ttfv-first-delivery/) +if (siteText) { + assert.match(siteText, /devcodex grok/) + assert.match(siteText, /repairSteps/) + assert.match(siteText, /Skill 强制包|Skill bundle|Intent → Skill/i) + assert.match(siteText, /UnalignedLedger|U-A1|未对齐|cannotClaim/i) +} else { + const websiteReadme = fs.readFileSync(path.join(__dirname, '../website/README.md'), 'utf8') + assert.match(websiteReadme, /不进入公开 Git 默认跟踪/) + assert.match(websiteReadme, /website 视为 optional/) +} assert.ok(fs.existsSync(path.join(__dirname, 'fixtures/host-parity/unaligned-ledger.v1.json'))) // Platform request semantic fixture (source-contained for clean checkout / CI) @@ -124,13 +141,17 @@ if (fs.existsSync(path.join(workspaceRoot, 'AGENTS.md'))) { assert.ok(['full-capable', 'partial'].includes(card.tier)) } -// philosophy Auto honesty +// Optional maintainer website surfaces. const philosophy = path.join(__dirname, '../website/docs/intro/philosophy.md') -assert.match(fs.readFileSync(philosophy, 'utf8'), /宿主诚实分列(Auto)/) -assert.match(fs.readFileSync(philosophy, 'utf8'), /Grok Build/) +const philosophyText = readIfExists(philosophy) +if (philosophyText) { + assert.match(philosophyText, /宿主诚实分列(Auto)/) + assert.match(philosophyText, /Grok Build/) +} -// rspress sidebar link -const rspress = fs.readFileSync(path.join(__dirname, '../website/rspress.config.ts'), 'utf8') -assert.match(rspress, /host-parity-grok/) +const rspress = readIfExists(path.join(__dirname, '../website/rspress.config.ts')) +if (rspress) { + assert.match(rspress, /host-parity-grok/) +} console.log('host parity remaining deliverables smoke passed') From aed0d2620666c4b992c868815162f145dab1af05 Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 00:40:37 +0800 Subject: [PATCH 08/11] fix: make security audit respect optional website --- scripts/test-security-audit.js | 67 ++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/scripts/test-security-audit.js b/scripts/test-security-audit.js index 41d95e0..d742112 100644 --- a/scripts/test-security-audit.js +++ b/scripts/test-security-audit.js @@ -89,16 +89,7 @@ const rootAudit = npmAudit(ROOT) assert.strictEqual(rootAudit.metadata?.vulnerabilities?.total, 0, 'root production dependency audit must remain clean') assert.deepStrictEqual(advisoryIds(rootAudit), policy.rootAllowedAdvisories) -const websiteAudit = npmAudit(WEBSITE) const allowedAdvisories = policy.websiteExceptions.map(item => item.advisoryId).sort() -assert.deepStrictEqual(advisoryIds(websiteAudit), allowedAdvisories, 'website advisory set changed; review before updating policy') -const vulnerabilityPackages = Object.keys(websiteAudit.vulnerabilities || {}).sort() -assert.deepStrictEqual( - vulnerabilityPackages, - [...policy.websiteAllowedPackages].sort(), - 'website vulnerability dependency chain changed' -) - const today = new Date().toISOString().slice(0, 10) for (const exception of policy.websiteExceptions) { assert.ok(today <= exception.expiresOn, `${exception.advisoryId} exception expired on ${exception.expiresOn}`) @@ -106,25 +97,45 @@ for (const exception of policy.websiteExceptions) { assert.ok(exception.replacementTrigger) } -for (const [packageName, minimum] of Object.entries(policy.minimumVersions)) { - const installed = installedVersion(packageName) - assert.ok( - compareVersion(installed, minimum) >= 0, - `${packageName}@${installed} is below the security floor ${minimum}` +const websitePackage = path.join(WEBSITE, 'package.json') +if (fs.existsSync(websitePackage)) { + const websiteAudit = npmAudit(WEBSITE) + assert.deepStrictEqual(advisoryIds(websiteAudit), allowedAdvisories, 'website advisory set changed; review before updating policy') + const vulnerabilityPackages = Object.keys(websiteAudit.vulnerabilities || {}).sort() + assert.deepStrictEqual( + vulnerabilityPackages, + [...policy.websiteAllowedPackages].sort(), + 'website vulnerability dependency chain changed' ) -} -const sourceRecords = websiteRuntimeSources().map(file => ({ - file, - content: fs.readFileSync(file, 'utf8') -})) -for (const pattern of policy.forbiddenWebsiteRuntimePatterns) { - const match = sourceRecords.find(record => record.content.includes(pattern)) - assert.ok(!match, `website runtime source enables unsupported RSC surface ${pattern}: ${match?.file}`) -} + for (const [packageName, minimum] of Object.entries(policy.minimumVersions)) { + const installed = installedVersion(packageName) + assert.ok( + compareVersion(installed, minimum) >= 0, + `${packageName}@${installed} is below the security floor ${minimum}` + ) + } -console.log( - `security audit passed root=0 websiteExceptions=${allowedAdvisories.join(',')} ` + - `expires=${policy.websiteExceptions[0].expiresOn} rspress=${installedVersion('@rspress/core')} ` + - `reactRouter=${installedVersion('react-router')} braceExpansion=${installedVersion('brace-expansion')}` -) + const sourceRecords = websiteRuntimeSources().map(file => ({ + file, + content: fs.readFileSync(file, 'utf8') + })) + for (const pattern of policy.forbiddenWebsiteRuntimePatterns) { + const match = sourceRecords.find(record => record.content.includes(pattern)) + assert.ok(!match, `website runtime source enables unsupported RSC surface ${pattern}: ${match?.file}`) + } + + console.log( + `security audit passed root=0 websiteExceptions=${allowedAdvisories.join(',')} ` + + `expires=${policy.websiteExceptions[0].expiresOn} rspress=${installedVersion('@rspress/core')} ` + + `reactRouter=${installedVersion('react-router')} braceExpansion=${installedVersion('brace-expansion')}` + ) +} else { + const websiteReadme = fs.readFileSync(path.join(WEBSITE, 'README.md'), 'utf8') + assert.match(websiteReadme, /不进入公开 Git 默认跟踪/) + assert.match(websiteReadme, /website 视为 optional/) + console.log( + `security audit passed root=0 website=optional-absent ` + + `policyExceptions=${allowedAdvisories.join(',')} expires=${policy.websiteExceptions[0].expiresOn}` + ) +} From c4a3cc1a696cdd029a60d46a68288eed3f75408d Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 09:38:55 +0800 Subject: [PATCH 09/11] fix: harden skill route context binding --- README.md | 294 +++++++----------- content/skills/portfolio.json | 44 +-- .../host-skill-route-capabilities.v1.json | 2 +- hooks/_runtime/lifecycle-bootstrap-state.cjs | 1 + hooks/_runtime/skill-route-tool.cjs | 15 + .../skill-route-closure-trace.v1.json | 2 +- scripts/lib/canonical-consumer-contracts.js | 52 ++-- scripts/test-client-contracts.js | 2 +- scripts/test-mcp-runtime-closure.js | 2 + scripts/test-skill-route-state.js | 36 ++- scripts/test-workflow-completion-contract.js | 2 +- 11 files changed, 194 insertions(+), 258 deletions(-) diff --git a/README.md b/README.md index 44a8c8e..3e9e590 100644 --- a/README.md +++ b/README.md @@ -1,261 +1,181 @@ # DevCodex -> 把可执行的 AI 开发流程装进 Copilot / Claude Code / Codex / Gemini / **Grok** -> **用户级全局 adapter** + 工作区 `.devcodex` 运行态 · Hook 优先 · Instruction 回退 - [![License](https://img.shields.io/badge/license-AGPL--3.0-green)](LICENSE) -> **安装真相(请先读)** -> - **当前主路径**:从源码根 `npm install -g .` + `npm run global-adapters:apply`(未发版或要最新时用这个)。 -> - **npm 公开包** `npm install -g devcodex`:仅当你确认 registry 上的版本与本文档/源码一致时再使用;**不要**假设 npm 上一定是本仓库最新提交。 -> - 历史包名 `@vextjs/devcodex` 请卸载,避免 PATH 指到旧 CLI。 - ---- - -## DevCodex 是什么? +DevCodex 是面向 AI 编程宿主的工作流运行时和宿主适配包。它通过 npm 安装到用户环境,将同一套任务路由、Skill 加载、Hook / 指令适配、报告和记忆写入机制接入 Codex、Claude Code、GitHub Copilot、Gemini CLI 和 Grok。 -DevCodex 把五宿主的配置、Hooks、Skills 与指令投影写到各 AI 宿主的**用户级目录**;业务仓库里主要保留工作区运行态 **`.devcodex/`**。 +安装完成后,DevCodex 在新会话中按用户请求的意图进入开发、修复、分析、审计等流程,并按需加载内置 Skill 或工作区 Skill。不同宿主的 Hook、指令和插件能力不完全相同;DevCodex 会按宿主能力使用可用的执行方式,并在能力不足时退回指令约束。 -它帮助 AI: +DevCodex 不替代业务框架、GitHub CI、安全审计或人工评审。它也不接管 Codex、Claude Code 等宿主原有的个人 Skill、项目指令或配置文件。 -- 按意图走 `dev` / `fix` / `analyze` / `audit` 等流程 -- 在支持 Hooks 的宿主上拦截危险命令、做收口检查 -- 把报告与会话记忆落到工作区,而不是只留在聊天窗口 - -**不是**通用聊天机器人,也不是替代你的业务框架。 +## DevCodex 是什么? ---- +DevCodex 给五个宿主提供同一套开发工作流入口: -## 5 分钟开始 +- Codex +- Claude Code +- GitHub Copilot +- Gemini CLI +- Grok -### 1. 环境 +它主要处理四件事: -- **Node.js**:建议 `>=18`(维护者本地文档站另需 `^20.19 || >=22.12`,见下文) -- 装完或刷新 adapter 后,请在宿主里 **新开一轮会话** +1. 按用户请求识别任务意图,例如开发、修复、分析、审计。 +2. 按需加载 DevCodex 内置 Skill 或当前项目的工作区 Skill。 +3. 在宿主支持时使用 Hook;宿主能力不足时使用指令约束作为回退。 +4. 将关键过程写入当前项目的报告和记忆。 -### 2. 安装(推荐:源码全局) +## 系统要求 -在 **本仓库源码根**(含 `package.json` / `skills/` 的目录): +- Node.js `>=18` +- npm +- 至少一个受支持的 AI 编程宿主:Codex、Claude Code、GitHub Copilot、Gemini CLI 或 Grok -```bash -npm install -g . -npm run global-adapters:apply -devcodex --version -devcodex doctor -``` +## 安装 Node.js -Windows + Volta 若仍指向旧包: +先确认本机是否已有 Node.js 和 npm: ```bash -npm uninstall -g @vextjs/devcodex -npm install -g . +node -v +npm -v ``` -**仅当 npm 上版本可信时:** +如果命令不存在,安装 Node.js LTS: -```bash -npm install -g devcodex -``` +- Windows / macOS:从 [Node.js 官方下载页](https://nodejs.org/en/download)安装 LTS 版本。 +- macOS / Linux:也可以使用 nvm、fnm、asdf 等版本管理器安装 LTS 版本。 -### 3. 打开业务项目 +安装后重新打开终端,再确认: ```bash -cd <你的业务仓库根> -devcodex init # 只初始化工作区 .devcodex,不写全局宿主 +node -v +npm -v ``` -再在 Codex / Claude / Copilot / Gemini / Grok 中打开该目录对话。 +如果 Node.js 版本低于 18,请先升级 Node.js。 -### 4. 验证技能是否加载(可选) +## 安装 -对话发送: +安装前请确认 npm registry 上的版本与本文档对应;如果 registry 上的版本不是当前文档对应版本,不要把下面命令当作当前版本安装。 -```text -验证技能加载 +```bash +npm install -g devcodex +devcodex --version ``` -期望用户可见固定句: +安装完成后,重新打开 Codex、Claude Code、GitHub Copilot、Gemini CLI 或 Grok 的新会话。 -```text -SKILL-LOAD-VERIFY-OK +## 更新 + +```bash +npm update -g devcodex +devcodex --version ``` -**不会**强制正文出现 `【DevCodex 技能】…` 元行;过程看宿主时间线即可。 +更新完成后,重新打开宿主的新会话。 -CLI: +## 卸载 ```bash -devcodex skill resolve skill-load-verify -npm run test:skill-route +npm uninstall -g devcodex ``` ---- +## 生效方式 -## 安装与刷新(必读) +安装或更新 DevCodex 后,npm 会在安装生命周期中刷新用户级宿主适配。已打开的宿主会话通常不会回读刚更新的配置,因此需要重新打开一个新会话。 -| 命令 | 作用 | -|------|------| -| `npm install -g .` | **源码全局安装**(未发版/最新主路径) | -| `npm run global-adapters:apply` | 用当前包根刷新**用户级五宿主**(改 hooks/MCP 后必跑) | -| `npm install -g devcodex` | 仅 registry 版本可信时使用 | -| `devcodex init` / `update` | **只**管当前工作区 `.devcodex`,**不**写全局宿主 | -| `devcodex status` / `doctor` | 诊断安装与宿主就绪 | +DevCodex 内置 Skill 随安装包一起提供。普通使用者不需要手动配置内置 Skill;新会话开始后,DevCodex 会按请求意图自动选择需要的 Skill。 -规则:**改宿主配置 → `global-adapters apply`;改业务工作区 → `init`/`update`。** -`.devcodex` 始终在项目/工作区,不会装进 npm global prefix。 +## 添加自己的 Skill -`apply` 时还可能合并写入 VS Code 用户级 `mcp.json`(memory/profile MCP,若路径存在)。 +如果你希望为某个项目增加自己的流程、检查清单或团队约定,在这个项目根目录下创建工作区 Skill。 ---- - -## 常用 CLI +这里的“项目根目录”就是你用 Codex、Claude Code、GitHub Copilot、Gemini CLI 或 Grok 打开的业务项目目录。 -```bash -devcodex doctor -devcodex status -devcodex global-adapters apply -devcodex skill plan -devcodex skill resolve -devcodex grok # Grok Full 入口(有边界) -devcodex profile plan|init +```text +<你的项目根目录>/ + .devcodex/ + workspace/ + skills/ + / + SKILL.md + intent.json ``` -完整列表:`devcodex --help`。 - ---- - -## 工作区布局(简) +例如: ```text -/ +my-app/ .devcodex/ - layout.json # workspace-namespace - workspace/ # 工作区 skills、DEVCODEX.md - / # profile / reports / .memory / requirements + workspace/ + skills/ + release-check/ + SKILL.md + intent.json ``` -| 类型 | 路径 | -|------|------| -| 工作区 skill(W 优先) | `.devcodex/workspace/skills//SKILL.md` | -| 全局 skill(hidden) | `~/.agents/devcodex/skills//`(菜单可能不显示,仍可加载) | - -**未发布源码候选**:渐进式 Skill 路由是五宿主唯一默认路由。它会在每轮建立 W + managed G 动态快照,再按 catalog → commit → stage 分页加载正文;全程使用宿主按需启动的本地 stdio MCP 子进程,不监听端口,也不需要服务端。多项目工作区尚未解析出目标时先等待 Profile plan 绑定真实项目,不会把工作区目录名当成项目创建运行态。新增或修改 `.devcodex/workspace/skills//SKILL.md` 会让旧快照失效,并在下一轮重新发现。宿主生产证据继续作为发布后的可观测性材料,不再控制源码路由模式,也不阻塞功能完成。 - -Codex/Claude 等宿主自己的 `AGENTS.md`、`CLAUDE.md`、原生个人/项目 Skill 仍由宿主负责发现。DevCodex 不扫描、复制、合并、覆盖或删除这些用户资产;同名也不视为 DevCodex 所有权。Codex 项目指令使用 `AGENTS.md`(不是 `codex.md`),Claude 项目指令使用精确文件名 `CLAUDE.md`,Skill 入口使用精确文件名 `SKILL.md`。 +`SKILL.md`: +```md --- - -## 宿主能力(诚实上限) - -| 宿主 | 大致能力 | -|------|----------| -| Claude Code / Codex / Copilot CLI 等 | Hook 较完整时可硬拦危险命令、Stop 收口 | -| **Grok** | **Partial enforcement**:UserPromptSubmit 不能可靠注入完整入口块;`devcodex grok` 仍使用统一 local-stdio Skill 路由,但当前精确 variant direct evidence 为 UNVERIFIED,不据此声称与 Codex 的宿主观察能力等价 | -| 仅 Instruction 的 surface | 语义约束,不保证硬拦 | - -「adapter 已安装」≠「五宿主能力完全一致」。 - +name: release-check +description: > + 当用户准备发布版本、检查 changelog、tag、npm publish 或 GitHub release 时使用。 --- +# release-check -## 语言策略(约定,非绝对保证) - -| 项 | 约定 | -|----|------| -| 对话回复 | **目标**跟随用户语言 | -| 工作区过程产物文件名 | 默认 **中文** 标准名(如 `00-需求概况.md`) | -| 完整多语言 i18n / 中英产物双文件名 | **本阶段未承诺** | - ---- +## 步骤 +1. 检查版本号、变更记录和发布分支。 +2. 运行项目约定的测试与打包命令。 +3. 输出发布前风险和下一步。 +``` -## 你能感知到的默认行为 +`intent.json`: + +```json +{ + "schemaVersion": "SkillIntentV1", + "skillId": "release-check", + "intents": [ + { + "id": "release", + "label": "发布检查", + "include": ["发布", "release", "tag", "npm"] + } + ], + "examples": { + "positive": ["帮我发版前检查", "准备 npm publish"], + "negative": ["修复登录 bug", "解释这个函数"] + }, + "summary": "发布前检查版本、changelog、tag、测试、打包和发布风险。" +} +``` -- **确认优先**:大改动、发版、危险命令前应得到确认(Auto 另有白名单边界) -- **危险命令**:可被 Hook 拦截 -- **入口检查**:实质任务前尽量有 PC0~PC7(视宿主能力) -- **报告与记忆**:非闲聊任务写入工作区 +新建或修改后,重新打开会话,或在后续请求中自然触发相关意图。 -Gate/探针编号是维护者资产,日常使用不必背。 +## 与宿主原生 Skill 共存 ---- +Codex、Claude Code 等宿主自己的项目指令、个人 Skill 和配置文件继续按宿主原有规则生效。 -## 技能加载 +DevCodex 不扫描、复制、合并、覆盖或删除这些用户资产。即使名称相同,宿主原生 Skill 也不视为 DevCodex 所有。 -1. 最终回复 **不强制** 技能元行 -2. 过程侧可用「正在加载 `` 技能」 -3. **不要** List `~/.grok/skills` 等主目录 skill 树(会暴露本机路径);只读单个已知 `SKILL.md` -4. 验证:对话「验证技能加载」或上文 CLI - ---- - -## 架构一览 +如果希望五个宿主通过 DevCodex 使用同一套能力,写 DevCodex 工作区 Skill: ```text -npm 全局包 / 源码 install -g - → 用户级:宿主 hooks / instructions / skills 投影 / VS Code mcp.json(apply) - → 工作区:.devcodex(profile、reports、memory、requirements、workspace skills) - → 运行时:hooks/_runtime/lifecycle.cjs + MCP memory/profile +<你的项目根目录>/.devcodex/workspace/skills//SKILL.md ``` ---- +如果只希望某个宿主单独使用,继续使用该宿主自己的 Skill 或指令机制。 ## 边界 -- 默认 **safety-only**:危险命令硬拦;流程项多为提醒,**strict** 才全面升级阻断 -- **不**替代业务 CI、安全审计与人工评审 -- Grok 等存在 **Partial** 上限 -- 敏感信息:以项目与你的要求为准;未禁止时不强制脱敏 - ---- - -## 文档与仓库边界 - -| 内容 | 位置 | -|------|------| -| **用户文档** | 本 README(公开仓主入口) | -| **维护者文档站** `website/` | **默认不进公开 Git 跟踪**、**不进 npm**;本机可保留完整拷贝(见 `website/README.md`) | -| 未发布变更 | `changelogs/unreleased.md` | -| 已发布说明 | `changelogs/releases/` | - ---- - -## 本地开发(贡献者) - -```bash -cd -npm install -npm run check:control-content -npm run test:stop-gate -npm run test:docs-surface-inventory -npm run test:skill-route -npm run global-adapters:apply -``` - -源码仓中的 instruction、prompt 与 Skill Markdown 唯一维护入口统一位于 `content/`。修改 canonical content 后先运行 `npm run check:control-content`;仓库兼容路径由 `npm run generate:control-content` 确定性投影,npm 打包则通过带锁和回执的 prepack/postpack 临时投影旧 delivery 路径。运行时和 npm 安装包继续读取 standalone delivery,不读取或携带 `content/`。 - -维护者文档站(需本机已有完整 `website/`): - -```bash -cd website && npm install && npm run dev -``` - -Node:`^20.19 || >=22.12`(仅文档站)。 +- DevCodex 不替代业务框架、GitHub CI、安全审计或人工评审。 +- 不同宿主的 Hook、指令和插件能力不同;同一工作流在不同宿主中的强制能力可能不同。 +- DevCodex 不接管宿主原生 Skill、个人配置或项目指令文件。 +- 工作区 Skill 只影响创建它的项目目录。 --- ## 许可证 [AGPL-3.0](LICENSE) - ---- - -## 用户可见交付与链接兼容 - -用户可见交付物应带可定位路径(工作区相对路径优先);宿主证据不足时用 portable 链接,不假装全宿主可点。 -MCP 侧先用 `profile_context_plan` 生成有界计划,再由 `profile_load` 完成选定正文;记忆侧先用 `memory_status` 定位,再按需查询。完成状态以绑定的 `ContextReadReceiptV2` 为准,V1 receipt 只作兼容读取。工作流技能按意图 **invoke**(按需读取,非整库预载)。 -用户侧文档 review 聚合见 skill `audit-user-manual`。 -规范侧:`PromptLongGateListDriftProbe`(V75)。 - -## 维护者备注 - -- 公开仓:`website/*` 忽略,仅跟踪 `website/README.md` 指针。 -- 过程 ECR 等常在工作区 `.devcodex/`(运行态,默认不进本 npm 包)。 diff --git a/content/skills/portfolio.json b/content/skills/portfolio.json index 48a8962..a49c0a8 100644 --- a/content/skills/portfolio.json +++ b/content/skills/portfolio.json @@ -13,8 +13,8 @@ "portfolioEvidenceDigest": "8364a73c66ed2ec9787cdb9300223278d128a45b689a2b8deda0d1f03189f42b", "consumerInventoryFileCount": 454, "consumerInventoryDigest": "2c4a1c119386da62a33c92b9c9141e3cfab88a3030af139ff2783fdee21b8504", - "consumerProjectionDigest": "c35460a60f21bf352ddac0144e8ee4db59581a7d39f4f548f3ce599ed6cc9a55", - "portfolioInputDigest": "f82d4eee26cbc18dfb3545b2053f165b5319e9f6cf76130a385bfe2969772e0a" + "consumerProjectionDigest": "cf598a884933ed397b977d4f3f61bf806950a1d3fd33760abf4e9aeb392a6c77", + "portfolioInputDigest": "ae225b55d1a2a6dfb4e3f7866e45b25c7e6eed0cc60c53b65835e7c9735d48ad" }, "ordering": "skills.id asc; graph edges from/to asc", "summary": { @@ -3783,10 +3783,6 @@ "path": "plugin.json", "role": "current" }, - { - "path": "README.md", - "role": "current" - }, { "path": "scripts/lib/test-spec-governance-expert.js", "role": "current" @@ -10120,6 +10116,10 @@ "path": "plugin.json", "role": "current" }, + { + "path": "README.md", + "role": "current" + }, { "path": "scripts/fixtures/candidate-review-bundle/phase-conflict.md", "role": "current" @@ -10152,6 +10152,10 @@ "path": "scripts/lib/always-on-governance.js", "role": "current" }, + { + "path": "scripts/lib/canonical-consumer-contracts.js", + "role": "current" + }, { "path": "scripts/lib/cli-install-commands.js", "role": "current" @@ -11144,10 +11148,6 @@ "path": "plugin.json", "role": "current" }, - { - "path": "README.md", - "role": "current" - }, { "path": "scripts/benchmark-runtime-indexes.js", "role": "current" @@ -11184,10 +11184,6 @@ "path": "scripts/lib/always-on-governance.js", "role": "current" }, - { - "path": "scripts/lib/canonical-consumer-contracts.js", - "role": "current" - }, { "path": "scripts/lib/cli-execution-commands.js", "role": "current" @@ -12099,10 +12095,6 @@ "path": "plugin.json", "role": "current" }, - { - "path": "README.md", - "role": "current" - }, { "path": "RULES.md", "role": "current" @@ -14588,10 +14580,6 @@ "path": "plugin.json", "role": "current" }, - { - "path": "README.md", - "role": "current" - }, { "path": "scripts/benchmark-runtime-indexes.js", "role": "current" @@ -16675,14 +16663,6 @@ "path": "plugin.json", "role": "current" }, - { - "path": "README.md", - "role": "current" - }, - { - "path": "scripts/lib/canonical-consumer-contracts.js", - "role": "current" - }, { "path": "scripts/test-host-skill-inventory-ban.js", "role": "current" @@ -17744,6 +17724,10 @@ "path": "plugin.json", "role": "current" }, + { + "path": "README.md", + "role": "current" + }, { "path": "scripts/benchmark-runtime-indexes.js", "role": "current" diff --git a/hooks/_runtime/host-skill-route-capabilities.v1.json b/hooks/_runtime/host-skill-route-capabilities.v1.json index 98d19f9..7723e90 100644 --- a/hooks/_runtime/host-skill-route-capabilities.v1.json +++ b/hooks/_runtime/host-skill-route-capabilities.v1.json @@ -13,7 +13,7 @@ "status": "PASS", "testedVersion": "codex-cli 0.145.0", "protocol": "MCP 2024-11-05", - "runtimeContractDigest": "e6f509af0135110586eb6c9fc0fe0e0a2ad3f33ed27d1711025246358904fee3", + "runtimeContractDigest": "d0454a58407a19880bd66071e7c263f4ef0656c665f9153e75c59708f0f9b291", "hostAdapterDigest": "6ba881f7fd7eba6297e1fcb8c55da09abbd5f47a42661fb2269f38d05e014139", "evidenceDigest": "2e3a291b99d65f9a4fa2cf7b871c84c623ef54536686653ce9a2473f4b756f2c", "evidenceRef": "E:/Worker/devcodex/.audit-state/content-root-s15-codex-production-20260730-v51.json", diff --git a/hooks/_runtime/lifecycle-bootstrap-state.cjs b/hooks/_runtime/lifecycle-bootstrap-state.cjs index d1cc4d0..ef37adf 100644 --- a/hooks/_runtime/lifecycle-bootstrap-state.cjs +++ b/hooks/_runtime/lifecycle-bootstrap-state.cjs @@ -1536,6 +1536,7 @@ function buildLifecycleBootstrapStateUtils(ctx) { return [ 'DevCodex intent-driven context acquisition is active for this user message.', 'Classify the canonical intent first, then obtain ContextReadPlanV2 and load only its selected Profile files and bounded memory queries.', + 'If this host exposes DevCodex MCP tools only after deferred tool discovery/search, perform that discovery first; hidden tools are not a reason to skip ContextReadPlanV2, profile_load, memory_status, or SkillRoute.', 'Resolve the active target against legacy .devcodex/profile/ or workspace-namespace base + project overlay roots before reading.', targetHandoff, 'A full Profile/SUMMARY/tasks read is a legacy or explicit escalation path, not the normal bootstrap default.', diff --git a/hooks/_runtime/skill-route-tool.cjs b/hooks/_runtime/skill-route-tool.cjs index 0a1329e..9c46798 100644 --- a/hooks/_runtime/skill-route-tool.cjs +++ b/hooks/_runtime/skill-route-tool.cjs @@ -277,6 +277,21 @@ function validateTrustedContextBinding (binding, target, options = {}) { error.code = 'CONTEXT_BINDING_PENDING' throw error } + if (Array.isArray(receipt.missingSourceIds) && receipt.missingSourceIds.length > 0) { + const error = new Error('CONTEXT_BINDING_PENDING') + error.code = 'CONTEXT_BINDING_PENDING' + throw error + } + if (Array.isArray(plan.mandatorySourceIds) && plan.mandatorySourceIds.length > 0) { + const satisfiedSourceIds = Array.isArray(receipt.satisfiedSourceIds) + ? new Set(receipt.satisfiedSourceIds) + : new Set() + if (plan.mandatorySourceIds.some(sourceId => !satisfiedSourceIds.has(sourceId))) { + const error = new Error('CONTEXT_BINDING_PENDING') + error.code = 'CONTEXT_BINDING_PENDING' + throw error + } + } if (receipt.status === 'baseline-ready' && (plan.selectedSources?.length || plan.mandatorySourceIds?.length)) { const error = new Error('CONTEXT_BINDING_PENDING') diff --git a/scripts/fixtures/skill-route-closure-trace.v1.json b/scripts/fixtures/skill-route-closure-trace.v1.json index f898d07..0d4fe77 100644 --- a/scripts/fixtures/skill-route-closure-trace.v1.json +++ b/scripts/fixtures/skill-route-closure-trace.v1.json @@ -88,7 +88,7 @@ "M04": {"owner": "scripts/test-global-host-config.js", "anchor": "sourceSkillRouteMode"}, "M05": {"owner": "scripts/probe-skill-route-s15-host.js", "anchor": "authorizationSource"}, "M06": {"owner": "scripts/test-global-install-smoke.js", "anchor": "real global install"}, - "M07": {"owner": "README.md", "anchor": "global-adapters apply"}, + "M07": {"owner": "README.md", "anchor": "安装生命周期中刷新用户级宿主适配"}, "M08": {"owner": "scripts/test-skill-route-state.js", "anchor": "MODE_CAPABILITY_STALE"}, "M08a": {"owner": "scripts/test-skill-route-lifecycle.js", "anchor": "MODE_CAPABILITY_STALE"}, "M08b": {"owner": "scripts/lib/test-hooks-runtime-bootstrap-layout.js", "anchor": "pending-project-rebind"}, diff --git a/scripts/lib/canonical-consumer-contracts.js b/scripts/lib/canonical-consumer-contracts.js index 8f10287..4448237 100644 --- a/scripts/lib/canonical-consumer-contracts.js +++ b/scripts/lib/canonical-consumer-contracts.js @@ -27,38 +27,30 @@ const CONTRACTS = new Map([ const PUBLIC_README_REQUIRED_MARKERS = Object.freeze([ '# DevCodex', - '用户级全局 adapter', - 'npm install -g .', + '工作流运行时和宿主适配包', + 'Codex、Claude Code、GitHub Copilot、Gemini CLI 和 Grok', + 'Node.js `>=18`', + 'node -v', + 'npm -v', 'npm install -g devcodex', - 'registry 上的版本', - 'npm run global-adapters:apply', - 'devcodex doctor', - 'devcodex init', - 'Codex / Claude / Copilot / Gemini / Grok', - 'devcodex skill resolve skill-load-verify', - 'profile / reports / .memory / requirements', - '.devcodex/workspace/skills//SKILL.md', - '~/.agents/devcodex/skills//', - 'W + managed G 动态快照', - '本地 stdio MCP 子进程', - '不监听端口', - 'DevCodex 不扫描、复制、合并、覆盖或删除这些用户资产', - 'AGENTS.md', - 'CLAUDE.md', + 'npm update -g devcodex', + 'npm uninstall -g devcodex', + 'devcodex --version', + '重新打开宿主的新会话', + '安装生命周期中刷新用户级宿主适配', + '内置 Skill', + '工作区 Skill', + '<你的项目根目录>/', + '.devcodex/', + 'workspace/', + 'skills/', + '/', 'SKILL.md', - 'Partial', - 'safety-only', - '用户文档', - 'website/README.md', - '用户可见交付与链接兼容', - 'profile_context_plan', - 'profile_load', - 'memory_status', - 'ContextReadReceiptV2', - 'V1 receipt 只作兼容读取', - 'invoke', - 'npm run test:stop-gate', - 'npm run test:docs-surface-inventory' + 'intent.json', + '<你的项目根目录>/.devcodex/workspace/skills//SKILL.md', + 'DevCodex 不扫描、复制、合并、覆盖或删除这些用户资产', + '不替代业务框架、GitHub CI、安全审计或人工评审', + '[AGPL-3.0](LICENSE)' ]) function evaluatePublicReadmeContract (content) { diff --git a/scripts/test-client-contracts.js b/scripts/test-client-contracts.js index d97f551..164a5cc 100644 --- a/scripts/test-client-contracts.js +++ b/scripts/test-client-contracts.js @@ -25,7 +25,7 @@ if (!hasValidCanonicalContract( )) { failures.push('valid public README must retire legacy internal-anchor projection') } -const damagedPublicReadme = publicReadme.replaceAll('npm run global-adapters:apply', '') +const damagedPublicReadme = publicReadme.replaceAll('npm install -g devcodex', '') if (evaluatePublicReadmeContract(damagedPublicReadme).valid || hasValidCanonicalContract( ROOT, diff --git a/scripts/test-mcp-runtime-closure.js b/scripts/test-mcp-runtime-closure.js index 2c6c69d..b815e34 100644 --- a/scripts/test-mcp-runtime-closure.js +++ b/scripts/test-mcp-runtime-closure.js @@ -100,6 +100,8 @@ function layoutReplaySmoke() { const codex = replayHostAdapter(path.join(workspace, '.codex', 'hooks', '_runtime', 'lifecycle-host-adapters.cjs'), 'codex', workspace) assert.strictEqual(codex.status, 0, `allowlist-only codex hook replay failed: ${codex.stderr || codex.stdout}`) assert.match(`${codex.stdout}`, /SkillRouteBootstrapV1/) + assert.match(`${codex.stdout}`, /deferred tool discovery\/search/) + assert.match(`${codex.stdout}`, /profile_load, memory_status, or SkillRoute/) assert.doesNotMatch(`${codex.stdout}`, /小朋友真可爱/) } diff --git a/scripts/test-skill-route-state.js b/scripts/test-skill-route-state.js index 809c77e..42040b6 100644 --- a/scripts/test-skill-route-state.js +++ b/scripts/test-skill-route-state.js @@ -205,6 +205,35 @@ try { assert.strictEqual(forgedCursor.ok, false) assert.strictEqual(forgedCursor.errorCode, 'CATALOG_CURSOR_INVALID') + const lifecyclePath = path.join( + fixture.activeRoot, + '.memory', + 'hooks', + fixture.project, + 'lifecycle-state.json' + ) + const incompleteMandatoryLifecycle = JSON.parse(fs.readFileSync(lifecyclePath, 'utf8')) + incompleteMandatoryLifecycle.contextAcquisition.plan.mandatorySourceIds = [ + 'profile:README.md', + 'memory:memory_status' + ] + incompleteMandatoryLifecycle.contextAcquisition.receipt.status = 'relevant-complete' + incompleteMandatoryLifecycle.contextAcquisition.receipt.satisfiedSourceIds = ['profile:README.md'] + incompleteMandatoryLifecycle.contextAcquisition.receipt.missingSourceIds = ['memory:memory_status'] + fs.writeFileSync(lifecyclePath, `${JSON.stringify(incompleteMandatoryLifecycle, null, 2)}\n`, 'utf8') + const missingMandatoryContextSource = handleSkillRoute({ + op: 'commit', + project: fixture.project, + turnBinding: boot.bootstrap.turnBinding, + contextEpoch, + catalogDigest: boot.bootstrap.catalogDigest, + skillId: 'workspace-probe', + contextBinding + }, fixture.runtimeOptions) + assert.strictEqual(missingMandatoryContextSource.ok, false) + assert.strictEqual(missingMandatoryContextSource.errorCode, 'CONTEXT_BINDING_PENDING') + writeContextBindingState(fixture, contextEpoch, 'dev') + // Acceptance R01 / R05: choice is exactly null-or-one catalog id and the // public Tool schema rejects caller-authored workflow fields. const unknownChoice = handleSkillRoute({ @@ -296,13 +325,6 @@ try { assert.strictEqual(staleCapability.ok, false) assert.strictEqual(staleCapability.errorCode, 'MODE_CAPABILITY_STALE') - const lifecyclePath = path.join( - fixture.activeRoot, - '.memory', - 'hooks', - fixture.project, - 'lifecycle-state.json' - ) const lifecycle = JSON.parse(fs.readFileSync(lifecyclePath, 'utf8')) lifecycle.contextAcquisition.receipt.status = 'planned' fs.writeFileSync(lifecyclePath, `${JSON.stringify(lifecycle, null, 2)}\n`, 'utf8') diff --git a/scripts/test-workflow-completion-contract.js b/scripts/test-workflow-completion-contract.js index db39030..a00bb05 100644 --- a/scripts/test-workflow-completion-contract.js +++ b/scripts/test-workflow-completion-contract.js @@ -1266,7 +1266,7 @@ inspectMutation(files => { files['hooks/_runtime/lifecycle-workflow-completion.c inspectMutation(files => { files['hooks/_runtime/lifecycle-workflow-completion.cjs'] = files['hooks/_runtime/lifecycle-workflow-completion.cjs'].split('recordShadowEvidenceSample').join('recordShadowSample') }, 'lifecycle-adapter-export-missing:recordShadowEvidenceSample') inspectMutation(files => { files['hooks/_runtime/lifecycle-workflow-completion.cjs'] += '\nconst workflowComplete = true\n' }, 'lifecycle-adapter-direct-completion-forbidden') inspectMutation(files => { files['scripts/test-host-adapters.js'] = files['scripts/test-host-adapters.js'].split('hostCompletionFixtures').join('hostCompletionSamples') }, 'host-completion-matrix-anchor-missing:hostCompletionFixtures') -inspectMutation(files => { files['README.md'] = files['README.md'].split('npm run global-adapters:apply').join('') }, 'completion-public-consumer-drift:README.md:PublicReadmeContractV1:npm run global-adapters:apply') +inspectMutation(files => { files['README.md'] = files['README.md'].split('npm install -g devcodex').join('') }, 'completion-public-consumer-drift:README.md:PublicReadmeContractV1:npm install -g devcodex') inspectMutation(files => { files['.git'] = 'source-checkout-fixture' delete files['website/docs/guide/development.md'] From af76477bd074662cc207d8faba50f23840412ef7 Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 10:27:49 +0800 Subject: [PATCH 10/11] chore: release v1.15.4 --- CHANGELOG.md | 5 +- RULES.md | 4 +- changelogs/releases/v1.15.4.md | 29 +++ content/duplication-inventory.json | 2 +- content/instructions.md | 2 +- .../instructions/00-safety.instructions.md | 2 +- .../instructions/01-common.instructions.md | 2 +- .../01a-profile-loading.instructions.md | 2 +- .../01b-record-router.instructions.md | 2 +- .../01c-intent-expansion.instructions.md | 2 +- .../02-output-paths.instructions.md | 2 +- content/instructions/10-dev.instructions.md | 2 +- content/instructions/11-fix.instructions.md | 2 +- content/instructions/12-audit.instructions.md | 2 +- .../instructions/13-analyze.instructions.md | 2 +- .../instructions/14-self-fix.instructions.md | 2 +- .../instructions/15-memory.instructions.md | 2 +- .../instructions/16-report.instructions.md | 2 +- .../17-compliance.instructions.md | 2 +- .../18-spec-radar.instructions.md | 2 +- .../example-tenant/10-dev.instructions.md | 2 +- content/skills/portfolio.json | 178 +++++++++--------- .../host-skill-route-capabilities.v1.json | 2 +- hooks/_runtime/workflow-root-registry.v1.json | 4 +- host-projections/AGENTS.md | 2 +- host-projections/copilot-instructions.md | 2 +- host-projections/coverage.json | 10 +- package-lock.json | 4 +- package.json | 2 +- plugin.json | 2 +- .../lib/package-compatibility-projection.js | 20 +- scripts/test-global-adapters-cli.js | 2 +- .../test-package-compatibility-projection.js | 32 +++- 33 files changed, 199 insertions(+), 135 deletions(-) create mode 100644 changelogs/releases/v1.15.4.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b323a30..2c6c900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # 变更日志 (CHANGELOG) > **说明**: 版本概览摘要。最新版本的详细变更见下方表格首行的 `changelogs/releases/vX.Y.Z.md` 链接;历史版本见对应详细变更文件 -> **最后更新**: 2026-07-29 +> **最后更新**: 2026-07-31 > **当前未发布**: 控制面 Markdown 已建立统一 authoring source、确定性物化、重复处置与 intent semantic quality 门禁;详见 [`changelogs/unreleased.md`](./changelogs/unreleased.md)。 --- @@ -10,6 +10,7 @@ | 版本 | 日期 | 变更摘要 | 详细 | |------|------|---------|------| +| [v1.15.4](./changelogs/releases/v1.15.4.md) | 2026-07-31 | 🔧 **SkillRoute Context Binding 防复发 + 用户 README 收口 + npmjs 发布候选**:ContextRead mandatory source 硬闸门、deferred MCP tool discovery 提示、用户向 README 简化安装/更新/卸载与工作区 Skill 路径,CI 全绿后进入 npmjs public 发布链 | [查看](./changelogs/releases/v1.15.4.md) | | [v1.15.3](./changelogs/releases/v1.15.3.md) | 2026-07-21 | 🔧 **治理诊断 + 纪律探针 + Skill 侧车与 Dual-Track 门禁**:AlwaysOn/GovernanceStatus、MeasuredVerification/V84、PF-148~165/087 簇、S1 sidecar、M1/M2 process gates、Claude MCP lib 部署与 CVE 卫生 | [查看](./changelogs/releases/v1.15.3.md) | | [v1.15.2](./changelogs/releases/v1.15.2.md) | 2026-07-21 | 🔧 **意图驱动上下文 + 执行链优化 + 发布真相纠偏**:ContextRead V2、任务名续接、validation DAG、ProjectKnowledge、Grok/Gemini 显式宿主、S07/Turn Liveness/可见输出、基座准入与 residual F 闭环 | [查看](./changelogs/releases/v1.15.2.md) | | [v1.15.1](./changelogs/releases/v1.15.1.md) | 2026-07-18 | 🔧 **CI 行数预算单源 + 品牌拓扑假绿 + 共享态闸门**:`ENTRY_MODULE_LINE_BUDGETS`、`ComponentTransparencyTopologyGate`、PI-119 自修/push 闸门、GR-044 验证阶段可追溯、台账 already-fixed 回写 | [查看](./changelogs/releases/v1.15.1.md) | @@ -127,7 +128,7 @@ ## 相关文档 -- [`changelogs/releases/v1.15.3.md`](./changelogs/releases/v1.15.3.md) — 最新版本详细变更文档 +- [`changelogs/releases/v1.15.4.md`](./changelogs/releases/v1.15.4.md) — 最新版本详细变更文档 - [`changelogs/releases/v1.15.0.md`](./changelogs/releases/v1.15.0.md) — 上一版本详细变更文档 - [`changelogs/releases/v1.14.0.md`](./changelogs/releases/v1.14.0.md) — 历史版本详细变更文档 - [`changelogs/releases/v1.11.21.md`](./changelogs/releases/v1.11.21.md) — 历史版本详细变更文档 diff --git a/RULES.md b/RULES.md index 33b680b..86885c1 100644 --- a/RULES.md +++ b/RULES.md @@ -1,6 +1,6 @@ -# DevCodex v1.15.3 — 使用入口 +# DevCodex v1.15.4 — 使用入口 -> AI workflow injector for Copilot / Claude Code / Codex / Gemini / Grok · publisher: Rocky · version: 1.15.3 +> AI workflow injector for Copilot / Claude Code / Codex / Gemini / Grok · publisher: Rocky · version: 1.15.4 ## 正式主支持客户端 diff --git a/changelogs/releases/v1.15.4.md b/changelogs/releases/v1.15.4.md new file mode 100644 index 0000000..099052b --- /dev/null +++ b/changelogs/releases/v1.15.4.md @@ -0,0 +1,29 @@ +# v1.15.4 + +> 发布日期:2026-07-31 +> 类型:Patch + +## 摘要 + +本版本收口 `SkillRoute` 与 `ContextRead` 绑定防复发,并将公共 README 调整为面向最终用户的安装、更新、卸载与工作区 Skill 使用说明。包名继续保持 npmjs unscoped `devcodex`。 + +## 主要变更 + +- `SkillRoute` context binding 加硬:当 `receipt.missingSourceIds` 非空,或 `ContextReadPlanV2.mandatorySourceIds` 未全部进入 `receipt.satisfiedSourceIds` 时,`skill_route commit/rebind/load_stage` 继续返回 `CONTEXT_BINDING_PENDING`,防止 `memory_status` 等 mandatory source 缺失时误判为可继续。 +- `UserPromptSubmit` bootstrap 增加 deferred MCP tool discovery/search 提示,Codex 等延迟暴露 DevCodex MCP 工具的宿主不得因工具初始不可见而跳过 `ContextReadPlanV2`、`profile_load`、`memory_status` 或 `SkillRoute`。 +- README 改为用户视角:保留项目介绍、Node.js 安装、`npm install/update/uninstall -g devcodex`、生效方式、工作区 Skill 添加路径和兼容原宿主 Skill 的说明;移除维护者/贡献者导向内容。 +- 同步 SkillRoute runtime contract digest、closure trace、consumer contract 与发布检查相关 golden。 + +## 验证 + +- `npm test` +- `npm run test:package-release` +- `npm run release:dry-run:all` +- `npm run test:audit` +- GitHub CI run `30596900467`:success + +## 发布说明 + +- npm 包名:`devcodex` +- registry:`https://registry.npmjs.org/` +- 发布路径:tag `v1.15.4` 触发 GitHub Actions `Publish to npm` diff --git a/content/duplication-inventory.json b/content/duplication-inventory.json index 5a7e236..8a059ab 100644 --- a/content/duplication-inventory.json +++ b/content/duplication-inventory.json @@ -1,6 +1,6 @@ { "schemaVersion": "ControlContentDuplicationInventoryV1", - "sourceBundleDigest": "80b768bc2bc07fc49cda6c11635441e5930459ceb9715ada5e66bb196268beda", + "sourceBundleDigest": "d778b1a996a2fd02a1d594ec33c1e6b9403e7adea09738901976d6815f105281", "thresholds": { "minParagraphChars": 100, "sectionThreshold": 0.94, diff --git a/content/instructions.md b/content/instructions.md index c4d33f6..c54f0a9 100644 --- a/content/instructions.md +++ b/content/instructions.md @@ -1,6 +1,6 @@ # DevCodex — 项目规范(统一规范源) -> DevCodex v1.15.3 · 单源规范文件 +> DevCodex v1.15.4 · 单源规范文件 > 本文件是 DevCodex 唯一的规范源文件。`devcodex init` 先通过 `HostAdapterScopeV1` 解析唯一宿主 owner:普通仓库为项目根,workspace-namespace 为工作区根;再在该 owner 投影 Copilot、Claude Code 与 Codex 入口。`devcodex init --claude` 仅安装 Claude Code 入口;`devcodex init --codex` 仅安装 Codex 入口。`CLAUDE.md` 与 `AGENTS.md` 都是本文件的部署副本,由本文件持续覆盖。 --- diff --git a/content/instructions/00-safety.instructions.md b/content/instructions/00-safety.instructions.md index 161eb0f..e910db5 100644 --- a/content/instructions/00-safety.instructions.md +++ b/content/instructions/00-safety.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 安全底线与输出语言规则,定义 S01~S07、违规处理与不可豁免边界 priority: P2 -version: 1.15.3 +version: 1.15.4 --- # 安全底线规范(S01~S07) diff --git a/content/instructions/01-common.instructions.md b/content/instructions/01-common.instructions.md index 0b8825a..b26a8e6 100644 --- a/content/instructions/01-common.instructions.md +++ b/content/instructions/01-common.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 通用规范总则,覆盖优先级、意图路由、Profile/active-root、宿主适配与治理总线 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # 通用规范 diff --git a/content/instructions/01a-profile-loading.instructions.md b/content/instructions/01a-profile-loading.instructions.md index 9ee9cf1..2f103cb 100644 --- a/content/instructions/01a-profile-loading.instructions.md +++ b/content/instructions/01a-profile-loading.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 意图驱动的 Profile 加载、active-root 路径、目标项目识别与项目现实扩展规范 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # Profile 加载与项目现实扩展 diff --git a/content/instructions/01b-record-router.instructions.md b/content/instructions/01b-record-router.instructions.md index 54b47c9..e5a8a1b 100644 --- a/content/instructions/01b-record-router.instructions.md +++ b/content/instructions/01b-record-router.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 任务切换边界、RecordRouter 分流、Improvement Intake 与提交发布边界的通用规范 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # 任务边界与 RecordRouter diff --git a/content/instructions/01c-intent-expansion.instructions.md b/content/instructions/01c-intent-expansion.instructions.md index 0faf189..57bbd5e 100644 --- a/content/instructions/01c-intent-expansion.instructions.md +++ b/content/instructions/01c-intent-expansion.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 意图识别、Intent Expansion Card、上下文重建与可见回复证据的通用规范 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # 意图扩展与上下文重建 diff --git a/content/instructions/02-output-paths.instructions.md b/content/instructions/02-output-paths.instructions.md index 79975e4..1571d57 100644 --- a/content/instructions/02-output-paths.instructions.md +++ b/content/instructions/02-output-paths.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 产物输出路径与命名规范,定义 active-root 下的 requirements、bugs、reports 与记忆落点 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # 产物输出路径规范 diff --git a/content/instructions/10-dev.instructions.md b/content/instructions/10-dev.instructions.md index 7b100d0..3789c8f 100644 --- a/content/instructions/10-dev.instructions.md +++ b/content/instructions/10-dev.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: dev 工作流规则,覆盖子类型路由、CP 流程、计划复审、执行期回退与 ECR priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 开发工作流规则(10-dev) diff --git a/content/instructions/11-fix.instructions.md b/content/instructions/11-fix.instructions.md index 0f90b2f..9ba5e07 100644 --- a/content/instructions/11-fix.instructions.md +++ b/content/instructions/11-fix.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: fix 工作流规则,覆盖子类型路由、CP 流程、修复三步扫描、执行期回退与 ECR priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 修复工作流规则(11-fix) diff --git a/content/instructions/12-audit.instructions.md b/content/instructions/12-audit.instructions.md index 25c9462..cf02eff 100644 --- a/content/instructions/12-audit.instructions.md +++ b/content/instructions/12-audit.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: audit 工作流规则,覆盖审查目标路由、收敛门禁、发现交接与只读授权边界 priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 审计工作流规则(12-audit) diff --git a/content/instructions/13-analyze.instructions.md b/content/instructions/13-analyze.instructions.md index 15d1217..c93006a 100644 --- a/content/instructions/13-analyze.instructions.md +++ b/content/instructions/13-analyze.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: analyze 工作流规则,覆盖只读分析、代码取证顺序、多轮收敛与推荐结论 priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 分析工作流规则(13-analyze) diff --git a/content/instructions/14-self-fix.instructions.md b/content/instructions/14-self-fix.instructions.md index 17556dc..c36a4d7 100644 --- a/content/instructions/14-self-fix.instructions.md +++ b/content/instructions/14-self-fix.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: self-fix 工作流规则,覆盖规范资产修复边界、自动级/Pending 级分流与文件数量限制 priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 规范自修复规则(14-self-fix) diff --git a/content/instructions/15-memory.instructions.md b/content/instructions/15-memory.instructions.md index 7d0c562..e91e092 100644 --- a/content/instructions/15-memory.instructions.md +++ b/content/instructions/15-memory.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 记忆规则,覆盖 tasks、SUMMARY、需求记忆的读取顺序、写入时机与格式约束 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # 记忆写入规则(15-memory) diff --git a/content/instructions/16-report.instructions.md b/content/instructions/16-report.instructions.md index 38bc9fe..04391b8 100644 --- a/content/instructions/16-report.instructions.md +++ b/content/instructions/16-report.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 报告输出规则,覆盖路径、命名、结构、ECR 引用与用户面产物路径要求 priority: P5 -version: 1.15.3 +version: 1.15.4 --- # 报告输出规则(16-report) diff --git a/content/instructions/17-compliance.instructions.md b/content/instructions/17-compliance.instructions.md index 5e0a336..c6bbe92 100644 --- a/content/instructions/17-compliance.instructions.md +++ b/content/instructions/17-compliance.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: dev 模式合规检查规则,覆盖 FC/SC/RC/T、入口检查与完成验证 priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 合规检查规则(17-compliance) diff --git a/content/instructions/18-spec-radar.instructions.md b/content/instructions/18-spec-radar.instructions.md index 06c9b1f..b518067 100644 --- a/content/instructions/18-spec-radar.instructions.md +++ b/content/instructions/18-spec-radar.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: PC4 规范雷达规则,覆盖规范缺口感知、三轴诊断与治理前置信号 priority: P4 -version: 1.15.3 +version: 1.15.4 --- # 规范雷达(18-spec-radar) diff --git a/content/instructions/tenants/example-tenant/10-dev.instructions.md b/content/instructions/tenants/example-tenant/10-dev.instructions.md index ccd6ba4..b10cc55 100644 --- a/content/instructions/tenants/example-tenant/10-dev.instructions.md +++ b/content/instructions/tenants/example-tenant/10-dev.instructions.md @@ -2,7 +2,7 @@ applyTo: "**" description: 示例租户对 dev 工作流的局部覆盖演示,说明如何追加租户级约束而非复制全量规则 priority: P3 -version: 1.15.3 +version: 1.15.4 --- # example-tenant — dev 工作流局部覆盖示例 diff --git a/content/skills/portfolio.json b/content/skills/portfolio.json index a49c0a8..cfd6a10 100644 --- a/content/skills/portfolio.json +++ b/content/skills/portfolio.json @@ -1,20 +1,20 @@ { "schemaVersion": 2, "package": "devcodex", - "packageVersion": "1.15.3", + "packageVersion": "1.15.4", "generatedFrom": { "skillsPattern": "content/skills/*/SKILL.md", "optionalSidecar": "content/skills/*/devcodex.skill.json", "registry": "plugin.json", "sourceDigest": "035975abb24e0760fd9fd23baf3b7b170e387e500838d9a460c5b20bf8120a2e", "sidecarDigest": "774105d7947b340d15d17115fcb8e37b62ae545cf553f06126d529184fd74872", - "pluginDigest": "705fe7c86c7225b67756749be5bb3b14a1ee3bffa386483a9ab61dc971f419ae", + "pluginDigest": "ed06d6f6e05399fb20791ddce1b7234f8016720bf7f1f6a6931b4fd2947084c6", "portfolioEvidence": "content/skills/portfolio-evidence.json", "portfolioEvidenceDigest": "8364a73c66ed2ec9787cdb9300223278d128a45b689a2b8deda0d1f03189f42b", "consumerInventoryFileCount": 454, "consumerInventoryDigest": "2c4a1c119386da62a33c92b9c9141e3cfab88a3030af139ff2783fdee21b8504", "consumerProjectionDigest": "cf598a884933ed397b977d4f3f61bf806950a1d3fd33760abf4e9aeb392a6c77", - "portfolioInputDigest": "ae225b55d1a2a6dfb4e3f7866e45b25c7e6eed0cc60c53b65835e7c9735d48ad" + "portfolioInputDigest": "c86d1444a3e9d6ad61fd6efe742b5ddab3bab78650cf2207f395ec366cb63263" }, "ordering": "skills.id asc; graph edges from/to asc", "summary": { @@ -579,7 +579,7 @@ "source": "content/skills/accessibility-i18n/SKILL.md", "hash": "e3741e362368044ea745160ee9d58812796391ff3c230e519e91fab008d95857", "sourceBytes": 5180, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -729,7 +729,7 @@ "source": "content/skills/ai-agent-system-architecture/SKILL.md", "hash": "984cae75c5ded3d64937ae296f69181f67c10697918d736cbdefbd9450417dc7", "sourceBytes": 11164, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -894,7 +894,7 @@ "source": "content/skills/ai-evaluation-engineering/SKILL.md", "hash": "30d8c4287a14a2b21d353bda05a2bad6394e10c1ece2c1fa8777cd5bbef30f15", "sourceBytes": 3106, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -1041,7 +1041,7 @@ "source": "content/skills/analyze-default/SKILL.md", "hash": "cbea857f22562c4f95585022e5dc48902af4e201143d3c939301f0d92c08ece8", "sourceBytes": 10645, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "load-profile" @@ -1230,7 +1230,7 @@ "source": "content/skills/analyze-research/SKILL.md", "hash": "6e9772a5947b38abbd0e023ec5c3c95049f53c4e753fe5e0dcb9fcb70b6e1c90", "sourceBytes": 3578, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -1386,7 +1386,7 @@ "source": "content/skills/api-contract-architecture/SKILL.md", "hash": "aa38b2f7dc0fc9a47bf4078f4fa0559a1aa9e5b53cf30f75ad08d7e84791cf3c", "sourceBytes": 5490, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -1540,7 +1540,7 @@ "source": "content/skills/api-verification/SKILL.md", "hash": "dca28ceaa5cae41ab1bf291a1b8104afa6d73ac3897a701a674a7a0db3380b78", "sourceBytes": 9559, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -1741,7 +1741,7 @@ "source": "content/skills/audit-common/SKILL.md", "hash": "dea8e78dfecdd193597f65b311d10e3f8734af02f7cc05b54a3bf9941b42b317", "sourceBytes": 30192, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -1973,7 +1973,7 @@ "source": "content/skills/audit-dimensions/SKILL.md", "hash": "11f7bae485e4b22ac6c8e9c3b108d1e0a7e2c70d402245688b1546fd236e59e1", "sourceBytes": 12881, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -2115,7 +2115,7 @@ "source": "content/skills/audit-document/SKILL.md", "hash": "cb05839b15258f7585fa2c2b36c425893d28b49ab1bf6503b7de54b1bad44983", "sourceBytes": 5636, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -2289,7 +2289,7 @@ "source": "content/skills/audit-execution-guide/SKILL.md", "hash": "59f578b488816efdd2faf9be0dfc8bb43e608d5ab7a00b2b29296cf53982017d", "sourceBytes": 6946, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -2481,7 +2481,7 @@ "source": "content/skills/audit-project/SKILL.md", "hash": "1c50aebcb2262b1dba5df4d043d006c2da381ae79d9049250480468cc909933f", "sourceBytes": 6585, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -2659,7 +2659,7 @@ "source": "content/skills/audit-readme/SKILL.md", "hash": "01e8fbc3066a9609ca723de4f0c0219e44726840431adc8a71231804c409c66c", "sourceBytes": 9730, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -2867,7 +2867,7 @@ "source": "content/skills/audit-release/SKILL.md", "hash": "48366b997d8772b5a19005a9fbd5a9662d88e0b67c0146e3f4e01280f8ea2319", "sourceBytes": 6307, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -3072,7 +3072,7 @@ "source": "content/skills/audit-report/SKILL.md", "hash": "38d5589b0648d0ae57b0e5fc0e8d80e3f0ad4e562db6883ae8848251ed2cf523", "sourceBytes": 3834, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -3221,7 +3221,7 @@ "source": "content/skills/audit-requirements/SKILL.md", "hash": "3f167b939f398ef4ca33e57b2d98723336ad9483495d6f32085902a344155b5e", "sourceBytes": 14093, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -3407,7 +3407,7 @@ "source": "content/skills/audit-session/SKILL.md", "hash": "4bbaccb628cda79bde6d0bfe192a99961bb43b7255971c195539896fe2b1e4a3", "sourceBytes": 8488, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -3591,7 +3591,7 @@ "source": "content/skills/audit-tech-design/SKILL.md", "hash": "a56588d8593d62fb41f8e8da4e9fb50c7f9f3ab9b0f4f35924f08424e85f22b9", "sourceBytes": 10730, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -3753,7 +3753,7 @@ "source": "content/skills/audit-user-manual/SKILL.md", "hash": "549da485cf2ec7d8d957a5c1afd6b0a14d7c0107d0becf0e596c7ef38f249223", "sourceBytes": 8323, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -3929,7 +3929,7 @@ "source": "content/skills/backend-domain-architecture/SKILL.md", "hash": "be1ffa54658623881d29451f14b6b7da613c2da8800ec81dc01e94046fffc003", "sourceBytes": 4067, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -4069,7 +4069,7 @@ "source": "content/skills/brand-visual-quality/SKILL.md", "hash": "52a55718755285553b4b2c63a5f86a38689064a7a5f2d60e18ac7308bf3fcbf3", "sourceBytes": 7536, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "gray", "dependencies": [], "references": [], @@ -4264,7 +4264,7 @@ "source": "content/skills/business-model-review/SKILL.md", "hash": "970e31768c7e09e6b35052c30fa4a0e7b469d36d5d931d92df4d847d5374bb44", "sourceBytes": 4355, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -4415,7 +4415,7 @@ "source": "content/skills/compliance/SKILL.md", "hash": "37aea8ea48e577d492ac71d9496b6fa71cd43fab5c8f6cc598ca8030ca96e15a", "sourceBytes": 23457, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "intent" @@ -4792,7 +4792,7 @@ "source": "content/skills/consumer-validation-engineering/SKILL.md", "hash": "253b1762b96bdf9035360415300c00f0909cc18769549cab06dd298372a189d0", "sourceBytes": 11031, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "gray", "dependencies": [], "references": [], @@ -4971,7 +4971,7 @@ "source": "content/skills/cp-gate/SKILL.md", "hash": "5fac202f905c6bfb9578c04fa17baff8a3bdd0dc4aff1e75dd3824819293ff8c", "sourceBytes": 26801, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -5275,7 +5275,7 @@ "source": "content/skills/data-architecture/SKILL.md", "hash": "bc4b0d1d9c0b5ae8e90e314da4352a8506674796c590fa2341dfb5e32ca47581", "sourceBytes": 3104, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -5417,7 +5417,7 @@ "source": "content/skills/design-system-architecture/SKILL.md", "hash": "6ac2efaf27c707104ab89385ff514ce4384c3b497d033315c034b61057cff3bf", "sourceBytes": 3618, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -5567,7 +5567,7 @@ "source": "content/skills/dev-database/SKILL.md", "hash": "4584707c2617b81e919673bfc8a118546e75bb36286d65c9ee5ddee4386dc958", "sourceBytes": 3240, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -5724,7 +5724,7 @@ "source": "content/skills/dev-default/SKILL.md", "hash": "cc2357f5fe4d21a893b90848511e0eb72ff649649323f677e9ebdf5a79d62723", "sourceBytes": 15506, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "cp-gate", @@ -5985,7 +5985,7 @@ "source": "content/skills/dev-docs/SKILL.md", "hash": "599956087771df0b721578080b3e5f4b854981309e0e1f44ac64f4b524cfc650", "sourceBytes": 9377, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -6183,7 +6183,7 @@ "source": "content/skills/dev-init/SKILL.md", "hash": "9bd7275ed18abf9b837617c499b224541bbc27320b483b254eb2b46b880ef0a9", "sourceBytes": 2932, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -6328,7 +6328,7 @@ "source": "content/skills/dev-optimization/SKILL.md", "hash": "2e1dce949e5c79cbe1e8e6d305dd841cb358423bbad653e09a87a8ee77610a12", "sourceBytes": 2596, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -6478,7 +6478,7 @@ "source": "content/skills/dev-plan-review/SKILL.md", "hash": "cf4b95a30824932a38e5d940d197d93eb2fb96bd2ce7395fd5fa61351e47497d", "sourceBytes": 22363, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "impact-review" @@ -6743,7 +6743,7 @@ "source": "content/skills/dev-refactor/SKILL.md", "hash": "292dc109806225cf977c2691c405357490eeafe157a5a050a94c691183239bc9", "sourceBytes": 1736, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "impact-review" @@ -6877,7 +6877,7 @@ "source": "content/skills/dev-scenario-test/SKILL.md", "hash": "881c7ceb155950cb1696cfc57a19fdcee3cfc496fe4f1c56a1fbcbc9c2322adb", "sourceBytes": 4180, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -7041,7 +7041,7 @@ "source": "content/skills/dev-testing/SKILL.md", "hash": "20c3cc6ef5c61709513ab2179829b683be6393c0bb388e14db0e6f7a063eab42", "sourceBytes": 19285, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "api-verification", @@ -7248,7 +7248,7 @@ "source": "content/skills/developer-experience-architecture/SKILL.md", "hash": "a61068f5e9d92d6e958d49d548b65c9725cfa65a7578f83822ca75c8a9b4a103", "sourceBytes": 6386, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -7399,7 +7399,7 @@ "source": "content/skills/distributed-systems-architecture/SKILL.md", "hash": "35ace6bf38e49d9b75200d86aa7699aa3b8e17c550e41943aec97d6446e22f59", "sourceBytes": 4108, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -7546,7 +7546,7 @@ "source": "content/skills/document-sync/SKILL.md", "hash": "c186620b0c3dc8a2ebec0e6b71ff4b7e585eeeabe7f6ff0ce585cb5a072f98c1", "sourceBytes": 9429, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "source-consumer-sync" @@ -7775,7 +7775,7 @@ "source": "content/skills/evolution-governance/SKILL.md", "hash": "37e1de8a7e35b333ee9b649b4060771c1ddd1e26b014028f8b473c06384a13c1", "sourceBytes": 10088, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "skill-lifecycle-governance" @@ -7928,7 +7928,7 @@ "source": "content/skills/execution-contract/SKILL.md", "hash": "48c363ecfa761e656343917ee4d0e85829f1fbb7e746bf0a0bee41d178939acf", "sourceBytes": 19710, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -8182,7 +8182,7 @@ "source": "content/skills/expert-output-quality/SKILL.md", "hash": "bf3030e293d6f8253bdaac3e3ab82c066d90d1fe2615030703f5353040dea7ee", "sourceBytes": 9773, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -8344,7 +8344,7 @@ "source": "content/skills/external-integration-architecture/SKILL.md", "hash": "e4f250905a49ccae22bb398f915f762c6a665b1d7f0649209f28751e689e992f", "sourceBytes": 3314, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -8488,7 +8488,7 @@ "source": "content/skills/fix-default/SKILL.md", "hash": "13388d5443f60fafe5055d7cff4fadca87fb77443595162f3cc2295f746cabc9", "sourceBytes": 7515, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "impact-review", @@ -8711,7 +8711,7 @@ "source": "content/skills/fix-security/SKILL.md", "hash": "ba00055f013aa556f99f4b8ef4f0524306ff4f01b7610db19957a34caa31316d", "sourceBytes": 1663, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -8852,7 +8852,7 @@ "source": "content/skills/frontend-architecture/SKILL.md", "hash": "4af9a690106af964a6edf006eea0929bec6264d7a5417cf8a28c55153e813ddc", "sourceBytes": 4371, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -8997,7 +8997,7 @@ "source": "content/skills/growth-analytics/SKILL.md", "hash": "0394a02a30bbe4343b12099023f02e8937b38da76c8c81f1e506826a0375753a", "sourceBytes": 4098, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -9141,7 +9141,7 @@ "source": "content/skills/host-capability-routing/SKILL.md", "hash": "42f03fbba286ffabfff91a6e27f047499ab1104c821ec397afde56c19565b7b1", "sourceBytes": 10925, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -9311,7 +9311,7 @@ "source": "content/skills/host-contract-verification/SKILL.md", "hash": "00e7c7eb5fb5339411e017636989a13ccdc1f3cc977386858f3f316b0d7d27d3", "sourceBytes": 12967, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -9519,7 +9519,7 @@ "source": "content/skills/host-instruction-projection/SKILL.md", "hash": "8e07feab42ad5f33a7f07bd0d6c6a37cb134ec9f3be60ca8cd29b29650d44bf9", "sourceBytes": 11472, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -9694,7 +9694,7 @@ "source": "content/skills/impact-review/SKILL.md", "hash": "54db11b70aa102f27d00199ac968b3bb81bb559b1def82120a96d93faf8a2be1", "sourceBytes": 1912, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -9821,7 +9821,7 @@ "source": "content/skills/incremental-project-analysis/SKILL.md", "hash": "34291cafb7412c2ccf28037ea293c4c345fbb2e3937d8bcb0095c37ffdebfbf9", "sourceBytes": 12066, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "analyze-default", @@ -9996,7 +9996,7 @@ "source": "content/skills/intent/SKILL.md", "hash": "7ca23ecde201527b99e33552ef60c840d7920043a35a1c1c72f308f5d831ce75", "sourceBytes": 12679, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -10560,7 +10560,7 @@ "source": "content/skills/load-profile/SKILL.md", "hash": "af2980daabc852c3f4f08dfb123d52badb186108e0e83c7cf1468ad23de566a7", "sourceBytes": 23127, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -10801,7 +10801,7 @@ "source": "content/skills/maintainer-docs-site-authoring/SKILL.md", "hash": "1ea054a1790c1d09c0ed8a9ffb255083dc2b726e2fb202ebd215e81391c30e7c", "sourceBytes": 2962, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -10928,7 +10928,7 @@ "source": "content/skills/memory/SKILL.md", "hash": "eed3f7e0050c4c25f8d8fa0cd382b8a7ed34f33e5072e83b14e4fb308555cdb1", "sourceBytes": 21665, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -11697,7 +11697,7 @@ "source": "content/skills/performance-engineering/SKILL.md", "hash": "e5017807c5620e2028a2c46249cdd58ee181af8ff4248151ebb87e707bef50e2", "sourceBytes": 5535, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -11854,7 +11854,7 @@ "source": "content/skills/plan/SKILL.md", "hash": "394d7d46d5d560036fc086bae37a69a5ebb882e10dd66bd8440dc05dcab81e2b", "sourceBytes": 1658, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -12768,7 +12768,7 @@ "source": "content/skills/platform-ecosystem-architecture/SKILL.md", "hash": "9b9f348dd84d6774e9a11b5d234cec3e2be9c49e3442d8f60c2a60a5ada7ed62", "sourceBytes": 4811, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -12920,7 +12920,7 @@ "source": "content/skills/privacy-compliance-architecture/SKILL.md", "hash": "4f61fbc9da67c797fac3df344466fc9a248534665adf183e864df15db658ee26", "sourceBytes": 3093, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -13064,7 +13064,7 @@ "source": "content/skills/product-strategy/SKILL.md", "hash": "481dd20ab98994507a5a83e9d375a211003ee732f8abd5e12e374c43d58c61dc", "sourceBytes": 3860, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -13204,7 +13204,7 @@ "source": "content/skills/production-readiness-sre/SKILL.md", "hash": "155b8b910b4365f5341e0d027187a6b4b09c3418345589134a4fe0e503cec236", "sourceBytes": 4304, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -13346,7 +13346,7 @@ "source": "content/skills/profile-bootstrap/SKILL.md", "hash": "98d6b2aabd7761c33d99ae703c96f223f82b48410ad7d4937be15f20b4314ecd", "sourceBytes": 10399, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -13543,7 +13543,7 @@ "source": "content/skills/quality-strategy/SKILL.md", "hash": "027980e6f70b9ee07c57f1245db59f38ef6676d6881d33ae085703dd74252309", "sourceBytes": 4222, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -13696,7 +13696,7 @@ "source": "content/skills/readme-authoring/SKILL.md", "hash": "a20dbfc6063ee800cff9be558632f4b587c63a87ed7d571c4a65625e0a75dd39", "sourceBytes": 7834, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "audit-readme" @@ -13879,7 +13879,7 @@ "source": "content/skills/release-verification/SKILL.md", "hash": "8c5865d7696da75f76d9722cc55964826c1480808248be50d521df28af46f40f", "sourceBytes": 17557, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -14128,7 +14128,7 @@ "source": "content/skills/repair-prevention-assessment/SKILL.md", "hash": "0a9b288234443aeb56bf3c4898aaa9432df27edd78ebd74bf7e7fa3c34560561", "sourceBytes": 4889, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -14310,7 +14310,7 @@ "source": "content/skills/report/SKILL.md", "hash": "bf205291ec6a9389ca3ee605dd0fe76b8918cb14efa507b142e946bc39780358", "sourceBytes": 21304, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "compliance" @@ -15139,7 +15139,7 @@ "source": "content/skills/requirement-parallel-orchestration/SKILL.md", "hash": "e60229b400b74ef53beb7a239e8c327aa47eb918b4e5f9ad3c668f5de4bcc41a", "sourceBytes": 7016, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -15286,7 +15286,7 @@ "source": "content/skills/review-checklist/SKILL.md", "hash": "568134154307261e0a6765dba4ccd048fdfb68a3ecdbe20e3adc4bde10fe6073", "sourceBytes": 15785, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -15499,7 +15499,7 @@ "source": "content/skills/rework-prevention-engineering/SKILL.md", "hash": "f28eb9cc8abbe73501916448ae85df24efde4c730224b9237a18e3b6b1ae1064", "sourceBytes": 10416, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "gray", "dependencies": [], "references": [ @@ -15698,7 +15698,7 @@ "source": "content/skills/routing/SKILL.md", "hash": "4e05428e378b10e80889561eff0790232835d496a97744644a86cd2fdefd17f6", "sourceBytes": 17535, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "intent", @@ -16166,7 +16166,7 @@ "source": "content/skills/security-threat-modeling/SKILL.md", "hash": "b21b07eb7f72497c6b6c307cc3fb70378698cf847db007870cc2115bf4b638eb", "sourceBytes": 5648, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -16308,7 +16308,7 @@ "source": "content/skills/skill-gap-analysis/SKILL.md", "hash": "aff2c4b089957c3b9a43a51a134f52150ba3a5c52f4df4729ee160a6e0f1dcd2", "sourceBytes": 8519, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -16458,7 +16458,7 @@ "source": "content/skills/skill-lifecycle-governance/SKILL.md", "hash": "e04446fe43f9e9f034ca57a8c0bc7f2a2ca0ca64772151a2ea1f40d5dc579b6c", "sourceBytes": 10702, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -16645,7 +16645,7 @@ "source": "content/skills/skill-load-verify/SKILL.md", "hash": "515fb259f444911adefe20cac05140f7533e9d96a3b57d1182716d6696493914", "sourceBytes": 1385, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -16785,7 +16785,7 @@ "source": "content/skills/source-consumer-sync/SKILL.md", "hash": "851fb46b0700a4ab0f826e80f918a63b5c0ba3e58a90afd56cd0f06b2a107dae", "sourceBytes": 6066, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -16980,7 +16980,7 @@ "source": "content/skills/spec-absorption/SKILL.md", "hash": "d8c24015565b5c81642b30b0c077d4fba327bf74c680290e77b222a3cd549f83", "sourceBytes": 28698, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "skill-gap-analysis" @@ -17194,7 +17194,7 @@ "source": "content/skills/spec-governance/SKILL.md", "hash": "e89b7b991da58e4afbb9883870f6e8b686e5d532197b5e107e82dd01b9feab09", "sourceBytes": 35305, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [ "spec-absorption" @@ -17628,7 +17628,7 @@ "source": "content/skills/summary/SKILL.md", "hash": "e2d6f6eadfb083c7ca9a6262c1bb67405e94bb1bd6733b171ba0063ce6579e50", "sourceBytes": 3322, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -18128,7 +18128,7 @@ "source": "content/skills/test-router/SKILL.md", "hash": "cbc3574d2b32059497ca2c830fa59fb2abb0564e350a7448cf0e56cfb56ae8e4", "sourceBytes": 12048, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [ @@ -18482,7 +18482,7 @@ "source": "content/skills/token-check/SKILL.md", "hash": "5e52887da96137e707636847e9456e675c9fc1c11ae2ff4d12252245dad90d72", "sourceBytes": 803, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -18635,7 +18635,7 @@ "source": "content/skills/user-manual-authoring/SKILL.md", "hash": "63d7c39b1d19405329a3b649f575f97e82f96b7e0dca40be2d59178b0a16b4da", "sourceBytes": 12146, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -18813,7 +18813,7 @@ "source": "content/skills/user-visible-output-contract/SKILL.md", "hash": "c88f9f98e0a952b79bc874cc9b6c8563c7375e1203d3b0a24570b17001c01234", "sourceBytes": 20344, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -19016,7 +19016,7 @@ "source": "content/skills/ux-interaction-architecture/SKILL.md", "hash": "a42c1b8c4de8103677cd777a3866dbb064f059ad27a981b7412c534ee1fd134c", "sourceBytes": 4072, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], @@ -19160,7 +19160,7 @@ "source": "content/skills/workspace-skill-author/SKILL.md", "hash": "b7d5230ee6ef579c8adefc5ed6307d865105619af3e384df57feff282e891760", "sourceBytes": 2828, - "version": "1.15.3", + "version": "1.15.4", "lifecycleState": "active", "dependencies": [], "references": [], diff --git a/hooks/_runtime/host-skill-route-capabilities.v1.json b/hooks/_runtime/host-skill-route-capabilities.v1.json index 7723e90..01fd032 100644 --- a/hooks/_runtime/host-skill-route-capabilities.v1.json +++ b/hooks/_runtime/host-skill-route-capabilities.v1.json @@ -13,7 +13,7 @@ "status": "PASS", "testedVersion": "codex-cli 0.145.0", "protocol": "MCP 2024-11-05", - "runtimeContractDigest": "d0454a58407a19880bd66071e7c263f4ef0656c665f9153e75c59708f0f9b291", + "runtimeContractDigest": "0f2a101fe4a9ba608d00cfcb43d93ef10814b52d0b8b3794bb8cef273c2f4eff", "hostAdapterDigest": "6ba881f7fd7eba6297e1fcb8c55da09abbd5f47a42661fb2269f38d05e014139", "evidenceDigest": "2e3a291b99d65f9a4fa2cf7b871c84c623ef54536686653ce9a2473f4b756f2c", "evidenceRef": "E:/Worker/devcodex/.audit-state/content-root-s15-codex-production-20260730-v51.json", diff --git a/hooks/_runtime/workflow-root-registry.v1.json b/hooks/_runtime/workflow-root-registry.v1.json index 8b6b70d..c0e7811 100644 --- a/hooks/_runtime/workflow-root-registry.v1.json +++ b/hooks/_runtime/workflow-root-registry.v1.json @@ -3,7 +3,7 @@ "sourceEvidence": [ { "ref": "content:instructions/01-common.instructions.md", - "digest": "b0d7262f20704c25dc1d96c6e18649f0594978561a1e5bdaf4773b7811627fc8" + "digest": "f33643c12a90b47d7bb4608dd44875f4df13e0977d4eb56218f5812bf13d16f0" }, { "ref": "content:skills/routing/SKILL.md", @@ -14,7 +14,7 @@ "digest": "e2aa31b083f387062d93c4ec00611ecf5b41a195918ef966895c6d25f37b19e5" } ], - "sourceDigest": "8a60bb3fd8bc0b986ff44e624030dedf197652d5a6a3dcd627384258e583facc", + "sourceDigest": "afeffe3a6740cd4cb0766b74cd3ae71ae40682393fd7618f661948fd0102c8d7", "baseBundles": { "chat": [], "resume": [ diff --git a/host-projections/AGENTS.md b/host-projections/AGENTS.md index 07629c4..3540675 100644 --- a/host-projections/AGENTS.md +++ b/host-projections/AGENTS.md @@ -1,7 +1,7 @@ # DevCodex — Shared Host Kernel(generated) > Generated from the unified DevCodex instructions source. Do not edit this file directly. -> sourceDigest: c880916353bdd69632f5d142366876a9dc77990182b3986610f1028ec6b569cd +> sourceDigest: 5f844a53b928275089e6c2d152cab6b13b4315c28088e0bb744296b4f2ff585f > configDigest: aa34ae2dc6c1b1f105c5af6e0d3ad650bda0a8742ebc6d3e74ff72e37e4c823c > Full fallback: user://agents/devcodex/instructions.full.md > Host surface: Codex / Claude import / Gemini import / Grok native AGENTS.md diff --git a/host-projections/copilot-instructions.md b/host-projections/copilot-instructions.md index e6c7fbf..86fb3d0 100644 --- a/host-projections/copilot-instructions.md +++ b/host-projections/copilot-instructions.md @@ -1,7 +1,7 @@ # DevCodex — Copilot Host Kernel(generated) > Generated from the unified DevCodex instructions source. Do not edit this file directly. -> sourceDigest: c880916353bdd69632f5d142366876a9dc77990182b3986610f1028ec6b569cd +> sourceDigest: 5f844a53b928275089e6c2d152cab6b13b4315c28088e0bb744296b4f2ff585f > configDigest: aa34ae2dc6c1b1f105c5af6e0d3ad650bda0a8742ebc6d3e74ff72e37e4c823c > Full fallback: user://agents/devcodex/instructions.full.md > Host surface: GitHub Copilot CLI user-global instructions; Hooks/MCP/Skills are deployed separately diff --git a/host-projections/coverage.json b/host-projections/coverage.json index 40cc3b5..0a4cfe1 100644 --- a/host-projections/coverage.json +++ b/host-projections/coverage.json @@ -1,12 +1,12 @@ { "schemaVersion": "HostInstructionCoverageReceiptV1", "sourceFile": "content/instructions.md", - "sourceDigest": "c880916353bdd69632f5d142366876a9dc77990182b3986610f1028ec6b569cd", + "sourceDigest": "5f844a53b928275089e6c2d152cab6b13b4315c28088e0bb744296b4f2ff585f", "configDigest": "aa34ae2dc6c1b1f105c5af6e0d3ad650bda0a8742ebc6d3e74ff72e37e4c823c", "mode": "kernel", "fallback": { "destination": "user://agents/devcodex/instructions.full.md", - "sourceDigest": "c880916353bdd69632f5d142366876a9dc77990182b3986610f1028ec6b569cd", + "sourceDigest": "5f844a53b928275089e6c2d152cab6b13b4315c28088e0bb744296b4f2ff585f", "available": true }, "budgets": { @@ -305,12 +305,12 @@ "host-projections/AGENTS.md": { "bytes": 11112, "lines": 90, - "digest": "690285fa10e08b553189674561ad15af7ee18399ac95e3ccb330318767451949" + "digest": "aeb3a36016c7c8d716da15a5b1ef81bd544dc37cbf5d29119b446a4e0ef20c22" }, "host-projections/copilot-instructions.md": { "bytes": 11137, "lines": 90, - "digest": "035134285cb09d57417d2cc55c4c474bf44f4e97578927a3ee97321a409afc2e" + "digest": "9354a8294bac7b04918ca03915ead37582930b966d51782c2886fa37250f9db7" }, "host-projections/CLAUDE.md": { "bytes": 510, @@ -328,5 +328,5 @@ "valid": true, "errors": [] }, - "receiptId": "host-instruction-coverage-2224e23f7da97a8a6fc52e4f9a97a90b150fedc894731be02f700992d7fe67d6" + "receiptId": "host-instruction-coverage-f0538ff5f44bd1bb1e6bf299984a5b5b19ca89f245b80ad66fe99d124f49e5d0" } diff --git a/package-lock.json b/package-lock.json index f12d32b..fa7a45c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "devcodex", - "version": "1.15.3", + "version": "1.15.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "devcodex", - "version": "1.15.3", + "version": "1.15.4", "hasInstallScript": true, "license": "AGPL-3.0-or-later", "bin": { diff --git a/package.json b/package.json index ab08d83..dc50ab5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "devcodex", - "version": "1.15.3", + "version": "1.15.4", "description": "DevCodex — AI-powered development workflow rules for Copilot, Claude Code, Codex, Gemini CLI and Grok", "main": "index.js", "bin": { diff --git a/plugin.json b/plugin.json index b77a954..21a433c 100644 --- a/plugin.json +++ b/plugin.json @@ -2,7 +2,7 @@ "_format": "DevCodex internal metadata — NOT a GitHub Copilot official format. Copilot reads .github/agents|skills|instructions|prompts directly.", "_note_skills": "Adding a new sub-type Skill (e.g. dev- / fix-) requires L1~L3 sync per audit-dimensions D5: (L1) routing/SKILL.md 路由表 (L2) 02-output-paths.instructions.md 产物目录 (L3) 对应 report 模板子类型字段. Skill name field must match directory name. See audit-dimensions D5 关键检查 for full rules.", "id": "devcodex", - "version": "1.15.3", + "version": "1.15.4", "name": "DevCodex", "publisher": "Rocky", "displayName": "DevCodex — AI Development Workflow Assistant", diff --git a/scripts/lib/package-compatibility-projection.js b/scripts/lib/package-compatibility-projection.js index 81bb968..a2fd686 100644 --- a/scripts/lib/package-compatibility-projection.js +++ b/scripts/lib/package-compatibility-projection.js @@ -306,17 +306,18 @@ function preparePackageProjection (root, options = {}) { } const existing = plan.files.filter(file => fs.existsSync(path.join(root, file.target))) + const existingMismatches = existing.filter(file => + sha256(fs.readFileSync(path.join(root, file.target))) !== file.digest + ) const foreignExisting = existing.filter(file => !tracked.has(file.target)) - if (foreignExisting.length) { + const foreignMismatches = existingMismatches.filter(file => !tracked.has(file.target)) + if (foreignMismatches.length) { const error = new Error( - `PACKAGE_PROJECTION_COLLISION: ${foreignExisting.map(file => file.target).join(', ')}` + `PACKAGE_PROJECTION_COLLISION: ${foreignMismatches.map(file => file.target).join(', ')}` ) error.code = 'PACKAGE_PROJECTION_COLLISION' throw error } - const existingMismatches = existing.filter(file => - sha256(fs.readFileSync(path.join(root, file.target))) !== file.digest - ) if (existingMismatches.length) { const error = new Error( `PACKAGE_PROJECTION_VERIFY_FAILED: ${existingMismatches.map(file => file.target).join(', ')}` @@ -325,7 +326,10 @@ function preparePackageProjection (root, options = {}) { throw error } const missing = plan.files.filter(file => !fs.existsSync(path.join(root, file.target))) - if (missing.length === 0) { + const reusableForeignExisting = foreignExisting.filter(file => + sha256(fs.readFileSync(path.join(root, file.target))) === file.digest + ) + if (missing.length === 0 && reusableForeignExisting.length === 0) { return { schemaVersion: SCHEMA_VERSION, mode: 'verify-existing', @@ -338,13 +342,14 @@ function preparePackageProjection (root, options = {}) { for (const file of missing) writeAtomic(path.join(root, file.target), file.content) const receiptPath = path.join(root, options.receiptFile || DEFAULT_RECEIPT) + const receiptFiles = [...missing, ...reusableForeignExisting] const receipt = { schemaVersion: RECEIPT_SCHEMA, owner: 'devcodex', createdAt: new Date().toISOString(), root: path.resolve(root), planDigest: plan.planDigest, - files: missing.map(file => ({ + files: receiptFiles.map(file => ({ target: file.target, digest: file.digest, trackedAtMaterialize: tracked.has(file.target) @@ -358,6 +363,7 @@ function preparePackageProjection (root, options = {}) { planDigest: plan.planDigest, trackedTargetCount: existing.filter(file => tracked.has(file.target)).length, materializedCount: missing.length, + adoptedExistingCount: reusableForeignExisting.length, reusedExistingCount: existing.length, receiptWritten: true, receiptPath diff --git a/scripts/test-global-adapters-cli.js b/scripts/test-global-adapters-cli.js index 06006c1..cd44e51 100644 --- a/scripts/test-global-adapters-cli.js +++ b/scripts/test-global-adapters-cli.js @@ -16,7 +16,7 @@ assert.strictEqual(isDevCodexSourceCheckout(ROOT), true) const sourceGuidance = describeGlobalAdapterRefresh({ sourceCheckout: true, - packageVersion: '1.15.3' + packageVersion: '1.15.4' }) assert.strictEqual(sourceGuidance.primary, 'devcodex global-adapters apply') assert.match(sourceGuidance.secondary, /npm install -g \./) diff --git a/scripts/test-package-compatibility-projection.js b/scripts/test-package-compatibility-projection.js index 7669a66..510d481 100644 --- a/scripts/test-package-compatibility-projection.js +++ b/scripts/test-package-compatibility-projection.js @@ -43,11 +43,18 @@ function fixture () { const currentPlan = buildPackageProjectionPlan(ROOT) assert.strictEqual(currentPlan.entryCount, EXPECTED_ENTRY_COUNT) assert.strictEqual(new Set(currentPlan.files.map(file => file.target)).size, EXPECTED_ENTRY_COUNT) +const currentTracked = new Set(git(ROOT, ['ls-files', '-z', '--']) + .split('\0') + .filter(Boolean) + .map(file => file.replace(/\\/g, '/'))) const currentMissingCount = currentPlan.files.filter(file => !fs.existsSync(path.join(ROOT, file.target)) ).length +const currentReusableForeignCount = currentPlan.files.filter(file => + fs.existsSync(path.join(ROOT, file.target)) && !currentTracked.has(file.target) +).length const current = preparePackageProjection(ROOT) -if (currentMissingCount === 0) { +if (currentMissingCount === 0 && currentReusableForeignCount === 0) { assert.strictEqual(current.mode, 'verify-existing') assert.strictEqual(current.trackedTargetCount, EXPECTED_ENTRY_COUNT) assert.strictEqual(current.receiptWritten, false) @@ -55,10 +62,11 @@ if (currentMissingCount === 0) { } else { assert.strictEqual(current.mode, 'materialize') assert.strictEqual(current.materializedCount, currentMissingCount) + assert.strictEqual(current.adoptedExistingCount, currentReusableForeignCount) assert.strictEqual(current.receiptWritten, true) const currentCleanup = cleanupPackageProjection(ROOT) assert.strictEqual(currentCleanup.status, 'cleaned') - assert.strictEqual(currentCleanup.removed.length, currentMissingCount) + assert.strictEqual(currentCleanup.removed.length, currentMissingCount + currentReusableForeignCount) } { @@ -174,6 +182,26 @@ if (currentMissingCount === 0) { } } +{ + const root = fixture() + try { + const first = preparePackageProjection(root) + assert.strictEqual(first.materializedCount, EXPECTED_ENTRY_COUNT) + fs.unlinkSync(path.join(root, DEFAULT_RECEIPT)) + + const adopted = preparePackageProjection(root) + assert.strictEqual(adopted.mode, 'materialize') + assert.strictEqual(adopted.materializedCount, 0) + assert.strictEqual(adopted.adoptedExistingCount, EXPECTED_ENTRY_COUNT) + assert.strictEqual(adopted.receiptWritten, true) + const cleaned = cleanupPackageProjection(root) + assert.strictEqual(cleaned.status, 'cleaned') + assert.strictEqual(cleaned.removed.length, EXPECTED_ENTRY_COUNT) + } finally { + fs.rmSync(root, { recursive: true, force: true }) + } +} + { const root = fixture() try { From 392b71593fe970d9687d0612021c205f3b7572c8 Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 31 Jul 2026 10:35:29 +0800 Subject: [PATCH 11/11] chore: refresh release portfolio --- content/skills/portfolio.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/content/skills/portfolio.json b/content/skills/portfolio.json index cfd6a10..eb659f0 100644 --- a/content/skills/portfolio.json +++ b/content/skills/portfolio.json @@ -11,10 +11,10 @@ "pluginDigest": "ed06d6f6e05399fb20791ddce1b7234f8016720bf7f1f6a6931b4fd2947084c6", "portfolioEvidence": "content/skills/portfolio-evidence.json", "portfolioEvidenceDigest": "8364a73c66ed2ec9787cdb9300223278d128a45b689a2b8deda0d1f03189f42b", - "consumerInventoryFileCount": 454, - "consumerInventoryDigest": "2c4a1c119386da62a33c92b9c9141e3cfab88a3030af139ff2783fdee21b8504", - "consumerProjectionDigest": "cf598a884933ed397b977d4f3f61bf806950a1d3fd33760abf4e9aeb392a6c77", - "portfolioInputDigest": "c86d1444a3e9d6ad61fd6efe742b5ddab3bab78650cf2207f395ec366cb63263" + "consumerInventoryFileCount": 455, + "consumerInventoryDigest": "b2fa9e1c5e76b9451e2974801621a74994e61604a55d973c3946a351226f39c0", + "consumerProjectionDigest": "6bdeece8879b3b87ca62cedbb160edfdfda18d4efe4f8403ee4c751ba5f7ff09", + "portfolioInputDigest": "787e2d05aeed7b571a3678ffee18e81ad3ebdee035f9c532141a42bd453372c5" }, "ordering": "skills.id asc; graph edges from/to asc", "summary": { @@ -11000,6 +11000,10 @@ "path": "changelogs/releases/v1.15.3.md", "role": "historical" }, + { + "path": "changelogs/releases/v1.15.4.md", + "role": "historical" + }, { "path": "changelogs/releases/v1.3.5.md", "role": "historical"