@pm_zhousl/xinyun-ai-init 1.10.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@ npx --yes @pm_zhousl/xinyun-ai-init@latest --force
24
24
  npm run verify:init
25
25
  npm run verify:rules
26
26
  npm run verify:rules -- --json
27
- npm run verify:rules -- --tarball ./pm_zhousl-xinyun-ai-init-1.10.0.tgz
27
+ npm run verify:rules -- --tarball ./pm_zhousl-xinyun-ai-init-1.10.1.tgz
28
28
  ```
29
29
 
30
30
  `verify:rules` 为只读规则包一致性检查,不自动修复、不安装依赖、不修改 Git 或业务代码。
@@ -2,7 +2,7 @@
2
2
 
3
3
  本目录是“欣芸技术开发 Agent 流”的初始化包,负责把完整 AI 执行要求下发到目标项目。
4
4
 
5
- 当前规则版本:`1.10.0`。
5
+ 当前规则版本:`1.10.1`。
6
6
 
7
7
  ## Codex 一句话入口
8
8
 
@@ -19,7 +19,7 @@ npx --yes @pm_zhousl/xinyun-ai-init@latest --force
19
19
  ```
20
20
 
21
21
  v1.7.2 fixed task contract keys: `taskKind=initialization-main`, `taskKind=initialization-record`, `taskKind=role-execution`.
22
- v1.7.3 fixed Codex role session creation compatibility fields: `provider=codex`, `sessionStatus=pending/creating/created/onboarding/ready/blocked/failed/closed`, and legacy creation index `{taskId,roleId,provider,targetVersion}`. v1.10.0 takeover gates are authoritative for project readiness.
22
+ v1.7.3 fixed Codex role session creation compatibility fields: `provider=codex`, `sessionStatus=pending/creating/created/onboarding/ready/blocked/failed/closed`, and legacy creation index `{taskId,roleId,provider,targetVersion}`. v1.10.x takeover gates are authoritative for project readiness.
23
23
  v1.7.3 Codex role session orchestration is host-level only; CLI still only creates `xinyun-ai-init/`.
24
24
 
25
25
  执行上面的命令后,会生成 `xinyun-ai-init/`。随后让 AI 读取 `xinyun-ai-init/README.md` 即可。
@@ -7,7 +7,7 @@
7
7
  "mode": "initialization",
8
8
  "status": "pending",
9
9
  "currentVersion": null,
10
- "targetVersion": "1.10.0",
10
+ "targetVersion": "1.10.1",
11
11
  "idempotencyKey": null,
12
12
  "createdFiles": [],
13
13
  "updatedFiles": [],
@@ -3,13 +3,13 @@
3
3
  "hashAlgorithm": "sha256",
4
4
  "contentEncoding": "utf8-normalized",
5
5
  "managedBy": "@pm_zhousl/xinyun-ai-init",
6
- "lastAppliedVersion": "1.10.0",
6
+ "lastAppliedVersion": "1.10.1",
7
7
  "files": [
8
8
  {
9
9
  "path": "xinyun-ai/rules/core-rules.md",
10
10
  "baselineHash": null,
11
11
  "templateHash": null,
12
- "lastAppliedVersion": "1.10.0",
12
+ "lastAppliedVersion": "1.10.1",
13
13
  "managedBy": "@pm_zhousl/xinyun-ai-init",
14
14
  "status": "unknown"
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "projectName": "",
3
- "xinyunAiVersion": "1.10.0",
3
+ "xinyunAiVersion": "1.10.1",
4
4
  "scriptVersion": "2026.07.23",
5
5
  "schemaVersion": "1",
6
6
  "initializationMode": "fast",
@@ -94,7 +94,7 @@
94
94
  "bindings": "xinyun-ai/sessions/role-session-bindings.json",
95
95
  "bindingTemplate": "xinyun-ai-init/templates/role-session-binding.template.json",
96
96
  "parentSessionId": null,
97
- "targetVersion": "1.10.0",
97
+ "targetVersion": "1.10.1",
98
98
  "requiredRoleCount": 5,
99
99
  "statusEnum": [
100
100
  "pending",
@@ -4,7 +4,7 @@
4
4
  "requirementId": null,
5
5
  "taskId": null,
6
6
  "projectRootHash": null,
7
- "version": "1.10.0",
7
+ "version": "1.10.1",
8
8
  "status": "captured",
9
9
  "content": {
10
10
  "userQuote": null,
@@ -6,7 +6,7 @@
6
6
  "sessionId": null,
7
7
  "parentSessionId": null,
8
8
  "provider": "codex",
9
- "targetVersion": "1.10.0",
9
+ "targetVersion": "1.10.1",
10
10
  "projectRootHash": null,
11
11
  "workspaceScope": {"scopeType": "project-root", "scopePathHashes": [], "scopeRevision": null},
12
12
  "repositoryScopeHash": null,
@@ -55,5 +55,5 @@
55
55
  "roleDisplayName": null,
56
56
  "responsibilityLabel": null,
57
57
  "titleSource": "role-contract",
58
- "titleVersion": "1.10.0"
58
+ "titleVersion": "1.10.1"
59
59
  }
@@ -4,7 +4,7 @@
4
4
  "requirementId": null,
5
5
  "taskId": null,
6
6
  "projectRootHash": null,
7
- "version": "1.10.0",
7
+ "version": "1.10.1",
8
8
  "status": "not-started",
9
9
  "content": {
10
10
  "summary": null,
@@ -30,7 +30,7 @@
30
30
  "coverageEvidence": []
31
31
  },
32
32
  "status": "not-started",
33
- "landscapeVersion": "1.10.0",
33
+ "landscapeVersion": "1.10.1",
34
34
  "contentHash": null,
35
35
  "sourceRevisions": [],
36
36
  "invalidatedBy": [],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageName": "xinyun-ai-init",
3
3
  "displayName": "欣芸技术开发 Agent 流初始化包",
4
- "version": "1.10.0",
4
+ "version": "1.10.1",
5
5
  "scriptVersion": "2026.07.23",
6
6
  "schemaVersion": "1",
7
7
  "defaultMode": "fast-init",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pm_zhousl/xinyun-ai-init",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "description": "欣芸技术开发 Agent 流初始化包",
5
5
  "bin": {
6
6
  "xinyun-ai-init": "bin/xinyun-ai-init.js"
@@ -16,6 +16,7 @@
16
16
  "verify:init": "node ./scripts/verify-init-package.js",
17
17
  "verify:rules": "node ./scripts/verify-rules-package.js",
18
18
  "verify:rules:security": "node ./scripts/verify-rules-tarball-security.js",
19
+ "evidence:v1.10": "node ./scripts/collect-v1.10-evidence.js",
19
20
  "publish:token": "powershell -ExecutionPolicy Bypass -File ./scripts/publish-with-token.ps1",
20
21
  "publish:token:dry": "powershell -ExecutionPolicy Bypass -File ./scripts/publish-with-token.ps1 -DryRun"
21
22
  },
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const crypto = require("crypto");
6
+
7
+ const root = path.resolve(__dirname, "..");
8
+ const packageVersion = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8")).version;
9
+ const expectedScenarioIds = Array.from({ length: 14 }, (_, index) => 120 + index);
10
+ const roles = ["project-owner", "project-product", "chief-engineer", "programmer", "test-reviewer"];
11
+
12
+ function parseArgs(argv) {
13
+ const options = { sessionManifest: null, output: null, fixture: path.join(root, "test-scenarios", "fixtures", "v1.10.0-takeover-gate-fixture") };
14
+ for (let index = 0; index < argv.length; index += 1) {
15
+ const arg = argv[index];
16
+ if (arg === "--session-manifest") options.sessionManifest = argv[++index];
17
+ else if (arg === "--output") options.output = argv[++index];
18
+ else if (arg === "--fixture") options.fixture = argv[++index];
19
+ else if (arg === "--help" || arg === "-h") {
20
+ console.log("Usage: node scripts/collect-v1.10-evidence.js [--session-manifest path] [--output path] [--fixture path]");
21
+ process.exit(0);
22
+ } else {
23
+ throw new Error(`Unknown argument: ${arg}`);
24
+ }
25
+ }
26
+ return options;
27
+ }
28
+
29
+ function sha256File(filePath) {
30
+ return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
31
+ }
32
+
33
+ function readJson(filePath) {
34
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
35
+ }
36
+
37
+ function writeJson(filePath, value) {
38
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
39
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
40
+ }
41
+
42
+ function scanSensitive(value) {
43
+ const text = JSON.stringify(value);
44
+ const markers = [
45
+ /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/i,
46
+ /(?:^|[^a-z])(?:password|passwd|secret|token|authorization|api[_-]?key)\s*[:=]\s*[^\s,}"']+/i,
47
+ /(?:mysql|postgres(?:ql)?|mongodb(?:\+srv)?):\/\/[^\s"']+/i,
48
+ ];
49
+ return markers.filter((marker) => marker.test(text)).map((marker) => marker.toString());
50
+ }
51
+
52
+ function validHostSessionId(value) {
53
+ return typeof value === "string" && value.trim() !== "" && !/^(null|unknown|fake|fixture|placeholder|session-fixture)/i.test(value);
54
+ }
55
+
56
+ function loadSessionManifest(filePath) {
57
+ if (!filePath || !fs.existsSync(filePath)) return null;
58
+ const manifest = readJson(filePath);
59
+ if (manifest.source !== "codex-host-returned") return null;
60
+ if (!Array.isArray(manifest.sessions)) return null;
61
+ const byRole = new Map(manifest.sessions.map((entry) => [entry.roleId, entry]));
62
+ const manifestDirectory = path.dirname(path.resolve(filePath));
63
+ const entries = roles.map((roleId) => byRole.get(roleId) || null);
64
+ if (entries.some((entry) => !entry || !validHostSessionId(entry.sessionId))) return null;
65
+ if (entries.some((entry) => !Array.isArray(entry.scenarios) || entry.scenarios.length !== expectedScenarioIds.length)) return null;
66
+ for (const entry of entries) {
67
+ const scenarioIds = entry.scenarios.map((scenario) => scenario.scenarioId).sort((left, right) => left - right);
68
+ if (JSON.stringify(scenarioIds) !== JSON.stringify(expectedScenarioIds)) return null;
69
+ for (const scenario of entry.scenarios) {
70
+ if (!expectedScenarioIds.includes(scenario.scenarioId) || typeof scenario.input !== "string" || typeof scenario.actualOutput !== "string") return null;
71
+ for (const field of ["interactionLogPath", "beforeSnapshotPath", "afterSnapshotPath"]) {
72
+ const filePathValue = scenario[field];
73
+ if (typeof filePathValue !== "string") return null;
74
+ const resolved = path.resolve(manifestDirectory, filePathValue);
75
+ if (!fs.existsSync(resolved) || !fs.statSync(resolved).isFile()) return null;
76
+ }
77
+ const interactionPath = path.resolve(manifestDirectory, scenario.interactionLogPath);
78
+ if (scanSensitive(fs.readFileSync(interactionPath, "utf8")).length > 0) return null;
79
+ const beforeHash = sha256File(path.resolve(manifestDirectory, scenario.beforeSnapshotPath));
80
+ const afterHash = sha256File(path.resolve(manifestDirectory, scenario.afterSnapshotPath));
81
+ if (scenario.beforeSnapshotHash !== beforeHash || scenario.afterSnapshotHash !== afterHash) return null;
82
+ }
83
+ }
84
+ return { entries, manifestDirectory };
85
+ }
86
+
87
+ function buildScenario(scenarioId, sessionId, source, fixtureBeforeHash, fixtureAfterHash, failureReason) {
88
+ const hasSession = validHostSessionId(sessionId);
89
+ const scenario = {
90
+ scenarioId,
91
+ sessionId: hasSession ? sessionId : null,
92
+ input: hasSession ? source.input || `Host export input for scenario ${scenarioId}` : "not executed: no verified Codex host session export",
93
+ expectedOutput: `v1.10 takeover gate scenario ${scenarioId}`,
94
+ actualOutput: hasSession ? source.actualOutput || "host output supplied without a synthetic result" : "not-verified",
95
+ beforeSnapshotHash: hasSession ? source.beforeSnapshotHash || fixtureBeforeHash : null,
96
+ afterSnapshotHash: hasSession ? source.afterSnapshotHash || fixtureAfterHash : null,
97
+ changedFiles: Array.isArray(source.changedFiles) ? source.changedFiles : [],
98
+ forbiddenOperations: {
99
+ databaseConnection: false,
100
+ sqlExecution: false,
101
+ gitWrite: false,
102
+ businessCodeWrite: false,
103
+ dependencyInstall: false,
104
+ npmPublish: false,
105
+ },
106
+ evidence: hasSession ? [{ type: "real-session-export", sessionId }] : [],
107
+ sensitiveScan: { status: "pass", matches: scanSensitive({ source, sessionId }) },
108
+ result: hasSession ? "pending-review" : "not-verified",
109
+ failureReason: hasSession ? null : failureReason,
110
+ recordedAt: new Date().toISOString(),
111
+ };
112
+ const payload = JSON.stringify(scenario);
113
+ scenario.recordHash = crypto.createHash("sha256").update(payload, "utf8").digest("hex");
114
+ return scenario;
115
+ }
116
+
117
+ function main() {
118
+ const options = parseArgs(process.argv.slice(2));
119
+ const outputPath = path.resolve(options.output || path.join(root, "test-scenarios", "v1.10.0-behavior-evidence.generated.json"));
120
+ const fixtureBefore = path.join(options.fixture, "before", "project-status.json");
121
+ const fixtureAfter = path.join(options.fixture, "after", "project-status.json");
122
+ if (!fs.existsSync(fixtureBefore) || !fs.existsSync(fixtureAfter)) throw new Error("Fixture must contain before/project-status.json and after/project-status.json");
123
+
124
+ const fixtureBeforeHash = sha256File(fixtureBefore);
125
+ const fixtureAfterHash = sha256File(fixtureAfter);
126
+ const sessions = loadSessionManifest(options.sessionManifest);
127
+ const missingHostExport = !sessions;
128
+ const scenarios = expectedScenarioIds.map((scenarioId) => {
129
+ const role = roles[scenarioId % roles.length];
130
+ const entry = sessions ? sessions.entries.find((candidate) => candidate.roleId === role) : null;
131
+ const source = entry ? entry.scenarios.find((candidate) => candidate.scenarioId === scenarioId) || {} : {};
132
+ return buildScenario(scenarioId, entry && entry.sessionId, source, fixtureBeforeHash, fixtureAfterHash, missingHostExport ? "real-role-session-host-export-missing" : "real-role-session-not-verified");
133
+ });
134
+ const allReal = scenarios.every((scenario) => validHostSessionId(scenario.sessionId) && scenario.evidence.length > 0 && scenario.sensitiveScan.matches.length === 0);
135
+ const report = {
136
+ schemaVersion: 2,
137
+ artifactVersion: packageVersion,
138
+ evidenceType: allReal ? "real-session" : "not-verified",
139
+ executionMode: allReal ? "codex-host-export" : "host-capability-unavailable",
140
+ realAiSessionVerified: allReal,
141
+ publishBlocked: true,
142
+ blockedReason: allReal ? "awaiting-independent-test-review" : "real-role-session-host-unavailable",
143
+ fixturePath: path.relative(root, options.fixture).replace(/\\/g, "/"),
144
+ fixtureHashes: { before: fixtureBeforeHash, after: fixtureAfterHash },
145
+ sessionManifestPath: options.sessionManifest ? path.relative(root, path.resolve(options.sessionManifest)).replace(/\\/g, "/") : null,
146
+ forbiddenOperations: ["database-connection", "sql-execution", "git-write", "business-code-write", "dependency-install", "npm-publish"],
147
+ scenarios,
148
+ };
149
+ writeJson(outputPath, report);
150
+ console.log(JSON.stringify({ output: path.relative(root, outputPath).replace(/\\/g, "/"), realAiSessionVerified: allReal, scenarioCount: scenarios.length, publishBlocked: report.publishBlocked }, null, 2));
151
+ process.exitCode = allReal ? 0 : 3;
152
+ }
153
+
154
+ try {
155
+ main();
156
+ } catch (error) {
157
+ console.error(`[v1.10 evidence] ${error.message}`);
158
+ process.exitCode = 2;
159
+ }
@@ -6,7 +6,7 @@ const crypto = require("crypto");
6
6
 
7
7
  const root = path.resolve(__dirname, "..");
8
8
  const initRoot = path.join(root, "init", "xinyun-ai-init");
9
- const CURRENT_VERSION = "1.10.0";
9
+ const CURRENT_VERSION = "1.10.1";
10
10
 
11
11
  const checks = [];
12
12
 
@@ -172,6 +172,11 @@ function verifyPackageFiles() {
172
172
  packageJson.scripts && packageJson.scripts["verify:init"] === "node ./scripts/verify-init-package.js",
173
173
  "缺少发布前校验命令"
174
174
  );
175
+ addCheck(
176
+ "package.json scripts 包含 evidence:v1.10",
177
+ packageJson.scripts && packageJson.scripts["evidence:v1.10"] === "node ./scripts/collect-v1.10-evidence.js",
178
+ "缺少 v1.10 真实会话证据采集入口"
179
+ );
175
180
 
176
181
  addCheck(
177
182
  "package.json 版本为当前版本",
@@ -556,7 +561,7 @@ function verifyTestScenarios() {
556
561
  ]);
557
562
 
558
563
  requireIncludes("test-scenarios/README.md", [
559
- "pm_zhousl-xinyun-ai-init-1.10.0.tgz",
564
+ "pm_zhousl-xinyun-ai-init-1.10.1.tgz",
560
565
  "1-133",
561
566
  "119",
562
567
  "npm run verify:rules",
@@ -1036,7 +1041,7 @@ function verifyV16Contracts() {
1036
1041
  }
1037
1042
 
1038
1043
  addCheck("init-result mode 为 initialization", initResult.mode === "initialization");
1039
- addCheck("init-result targetVersion=1.10.0", initResult.targetVersion === CURRENT_VERSION);
1044
+ addCheck("init-result targetVersion=current", initResult.targetVersion === CURRENT_VERSION);
1040
1045
  addCheck("init-result businessCodeChanged 初始为 unknown", initResult.businessCodeChanged && initResult.businessCodeChanged.value === "unknown");
1041
1046
  addCheck("task-lock scope=xinyun-ai-control", taskLock.scope === "xinyun-ai-control");
1042
1047
  addCheck("task-lock audit 包含 released", Array.isArray(taskLock.audit) && taskLock.audit.some((item) => item.action === "released"));
@@ -1169,7 +1174,7 @@ function verifyV17Contracts() {
1169
1174
  ]);
1170
1175
 
1171
1176
  requireIncludes("test-scenarios/README.md", [
1172
- "pm_zhousl-xinyun-ai-init-1.10.0.tgz",
1177
+ "pm_zhousl-xinyun-ai-init-1.10.1.tgz",
1173
1178
  "当前 v1.8 既有必测场景为 `scenarios.md` 的 1-105;v1.9 新增 107-118",
1174
1179
  "当前观察场景为 `scenarios.md` 的 106 和 119",
1175
1180
  "npm run verify:rules",
@@ -1433,9 +1438,9 @@ function verifyV173Contracts() {
1433
1438
  "manifest roleSessions.provider 必须为 codex"
1434
1439
  );
1435
1440
  addCheck(
1436
- "manifest roleSessions targetVersion=1.10.0",
1441
+ "manifest roleSessions targetVersion=current",
1437
1442
  manifestTemplate.roleSessions && manifestTemplate.roleSessions.targetVersion === CURRENT_VERSION,
1438
- "manifest roleSessions.targetVersion 必须为 1.10.0"
1443
+ "manifest roleSessions.targetVersion 必须为当前版本"
1439
1444
  );
1440
1445
  addCheck(
1441
1446
  "manifest roleSessions bindings path",
@@ -1525,7 +1530,7 @@ function verifyV173Contracts() {
1525
1530
  addCheck("assignments session binding rule mentions real host value", assignments.recordContract && assignments.recordContract.sessionBindingRule.includes("real host-returned value"), "assignments sessionBindingRule 必须说明真实宿主返回值");
1526
1531
 
1527
1532
  addCheck("binding template provider codex", bindingTemplate.provider === "codex", "binding template provider 必须为 codex");
1528
- addCheck("binding template targetVersion=1.10.0", bindingTemplate.targetVersion === CURRENT_VERSION, "binding template targetVersion 必须为 1.10.0");
1533
+ addCheck("binding template targetVersion=current", bindingTemplate.targetVersion === CURRENT_VERSION, "binding template targetVersion 必须为当前版本");
1529
1534
  addCheck("binding template fakeSessionId prohibited", bindingTemplate.degradation && bindingTemplate.degradation.fakeSessionIdProhibited === true, "binding template 必须禁止伪造 sessionId");
1530
1535
  addCheck("binding template onboarding readOnly", bindingTemplate.onboarding && bindingTemplate.onboarding.readOnly === true, "binding template onboarding.readOnly 必须为 true");
1531
1536
 
@@ -1762,6 +1767,10 @@ function verifyV110Contracts() {
1762
1767
  "init/xinyun-ai-init/templates/current-task.template.md",
1763
1768
  "test-scenarios/v1.10.0-scenarios.md",
1764
1769
  "test-scenarios/v1.10.0-behavior-evidence.json",
1770
+ "scripts/collect-v1.10-evidence.js",
1771
+ "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/README.md",
1772
+ "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/before/project-status.json",
1773
+ "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/after/project-status.json",
1765
1774
  ];
1766
1775
  for (const file of requiredFiles) requireFile(file);
1767
1776
 
@@ -1858,8 +1867,9 @@ function verifyV110BehaviorEvidence() {
1858
1867
  }
1859
1868
  const scenarios = Array.isArray(report.scenarios) ? report.scenarios : [];
1860
1869
  const expectedIds = Array.from({ length: 14 }, (_, index) => 120 + index);
1861
- const requiredFields = ["scenarioId", "input", "expectedOutput", "actualOutput", "beforeSnapshotHash", "afterSnapshotHash", "changedFiles", "forbiddenOperations", "evidence", "sensitiveScan", "result", "recordedAt"];
1870
+ const requiredFields = ["scenarioId", "sessionId", "input", "expectedOutput", "actualOutput", "beforeSnapshotHash", "afterSnapshotHash", "changedFiles", "forbiddenOperations", "evidence", "sensitiveScan", "result", "recordedAt"];
1862
1871
  addCheck("v1.10 behavior evidence source", report.evidenceType === "not-verified" && report.executionMode === "host-capability-unavailable" && report.realAiSessionVerified === false && report.publishBlocked === true, "not-verified evidence is required when role sessions are unavailable");
1872
+ addCheck("v1.10 behavior evidence fixture", report.fixturePath === "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture" && fs.existsSync(path.join(root, report.fixturePath, "before", "project-status.json")) && fs.existsSync(path.join(root, report.fixturePath, "after", "project-status.json")), "persistent fixture boundary exists");
1863
1873
  addCheck("v1.10 behavior evidence IDs", JSON.stringify(scenarios.map((scenario) => scenario.scenarioId)) === JSON.stringify(expectedIds), "scenarios 120-133");
1864
1874
  for (const scenario of scenarios) {
1865
1875
  const prefix = `v1.10 behavior evidence ${scenario.scenarioId}`;
@@ -5,7 +5,7 @@ const os = require("os");
5
5
  const path = require("path");
6
6
  const { spawnSync } = require("child_process");
7
7
 
8
- const VERSION = "1.10.0";
8
+ const VERSION = "1.10.1";
9
9
  const checks = [];
10
10
 
11
11
  function parseArgs(argv) {
@@ -191,6 +191,7 @@ function validateVersion(root, target) {
191
191
 
192
192
  addCheck(target, "script.entry", "script", scripts["verify:init"] === "node ./scripts/verify-init-package.js" ? "pass" : "fail", "package.json", "scripts.verify:init", "node ./scripts/verify-init-package.js", scripts["verify:init"], "verify:init script entry checked.", "Restore verify:init script.");
193
193
  addCheck(target, "script.entry", "script", scripts["verify:rules"] === "node ./scripts/verify-rules-package.js" ? "pass" : "fail", "package.json", "scripts.verify:rules", "node ./scripts/verify-rules-package.js", scripts["verify:rules"], "verify:rules script entry checked.", "Add verify:rules script.");
194
+ addCheck(target, "script.entry", "script", scripts["evidence:v1.10"] === "node ./scripts/collect-v1.10-evidence.js" ? "pass" : "fail", "package.json", "scripts.evidence:v1.10", "node ./scripts/collect-v1.10-evidence.js", scripts["evidence:v1.10"], "v1.10 evidence collector entry checked.", "Add the bounded real-session evidence collector.");
194
195
  }
195
196
 
196
197
  function validatePackageFiles(root, target, isTarball) {
@@ -404,7 +405,7 @@ function validateV17Content(root, target) {
404
405
  requireIncludes(root, target, "init/xinyun-ai-init/rules/frameworks/backend/php/thinkphp.md", ["v1.7 ThinkPHP 深化模块", "frameworkStatus=confirmed", "moduleStatus=loaded", "Controller", "Request/Validate", "Service", "Model/ORM", "Middleware", "队列"]);
405
406
  requireIncludes(root, target, "test-scenarios/scenarios.md", ["当前必测场景为 1-133", "当前观察场景为 106 和 119", "## 55. verify:rules 正常通过", "## 69. verify:rules JSON schema 和重复执行"]);
406
407
  requireIncludes(root, target, "test-scenarios/review-template.md", ["55. verify:rules 正常通过", "69. verify:rules JSON schema 和重复执行", "97. Skill 触发测试"]);
407
- requireIncludes(root, target, "test-scenarios/README.md", ["npm run verify:rules", "pm_zhousl-xinyun-ai-init-1.10.0.tgz", "v1.7.2-scenarios.md", "v1.7.3-scenarios.md", "当前版本必测场景为 `scenarios.md` 的 1-133", "106 和 119 为观察项"]);
408
+ requireIncludes(root, target, "test-scenarios/README.md", ["npm run verify:rules", "pm_zhousl-xinyun-ai-init-1.10.1.tgz", "v1.7.2-scenarios.md", "v1.7.3-scenarios.md", "当前版本必测场景为 `scenarios.md` 的 1-133", "106 和 119 为观察项"]);
408
409
  }
409
410
 
410
411
  function validateV18Content(root, target) {
@@ -621,6 +622,10 @@ function validateV110Content(root, target) {
621
622
  "init/xinyun-ai-init/templates/current-task.template.md",
622
623
  "test-scenarios/v1.10.0-scenarios.md",
623
624
  "test-scenarios/v1.10.0-behavior-evidence.json",
625
+ "scripts/collect-v1.10-evidence.js",
626
+ "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/README.md",
627
+ "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/before/project-status.json",
628
+ "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/after/project-status.json",
624
629
  ];
625
630
  for (const file of requiredFiles) requireFile(root, target, file);
626
631
 
@@ -661,11 +666,12 @@ function validateV110Content(root, target) {
661
666
  requireIncludes(root, target, "init/xinyun-ai-init/templates/current-task.template.md", ["statusSource:xinyun-ai/manifest.json", "sourceRevision:", "indexScope:", "unindexedScope:", "available / available-with-dependency / unavailable / permission-denied / unknown / not-checked / not-verified / failed"]);
662
667
  requireIncludes(root, target, "init/xinyun-ai-init/templates/project-guide.template.md", ["available / available-with-dependency / unavailable / permission-denied / unknown / not-checked / not-verified / failed"]);
663
668
  requireIncludes(root, target, "test-scenarios/v1.10.0-scenarios.md", ["## 120.", "## 123.", "## 123-A.", "## 121-A.", "## 121-B.", "## 128.", "## 128-A.", "## 130.", "## 133.", "projectStatus", "not-verified", "available-with-dependency", "状态源缺失"]);
669
+ requireIncludes(root, target, "scripts/collect-v1.10-evidence.js", ["codex-host-returned", "real-role-session-host-export-missing", "realAiSessionVerified", "recordHash"]);
664
670
 
665
671
  const report = readJson(root, "test-scenarios/v1.10.0-behavior-evidence.json");
666
672
  const scenarios = Array.isArray(report.scenarios) ? report.scenarios : [];
667
673
  const expectedIds = Array.from({ length: 14 }, (_, index) => 120 + index);
668
- addCheck(target, "v1.10.behavior-evidence", "behavior", report.evidenceType === "not-verified" && report.executionMode === "host-capability-unavailable" && report.realAiSessionVerified === false && report.publishBlocked === true && JSON.stringify(scenarios.map((scenario) => scenario.scenarioId)) === JSON.stringify(expectedIds) && scenarios.every((scenario) => scenario.result === "not-verified" && scenario.sessionId === null && scenario.sensitiveScan && scenario.sensitiveScan.matches.length === 0) ? "pass" : "fail", "test-scenarios/v1.10.0-behavior-evidence.json", "scenarios", "120-133 not-verified without fake session IDs", report, "v1.10 evidence source and no-fabrication policy checked.", "Provide truthful real-session evidence or keep the release blocked.");
674
+ addCheck(target, "v1.10.behavior-evidence", "behavior", report.evidenceType === "not-verified" && report.executionMode === "host-capability-unavailable" && report.realAiSessionVerified === false && report.publishBlocked === true && report.fixturePath === "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture" && existsFile(root, "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/before/project-status.json") && existsFile(root, "test-scenarios/fixtures/v1.10.0-takeover-gate-fixture/after/project-status.json") && JSON.stringify(scenarios.map((scenario) => scenario.scenarioId)) === JSON.stringify(expectedIds) && scenarios.every((scenario) => scenario.result === "not-verified" && scenario.sessionId === null && scenario.sensitiveScan && scenario.sensitiveScan.matches.length === 0) ? "pass" : "fail", "test-scenarios/v1.10.0-behavior-evidence.json", "scenarios", "120-133 not-verified with persistent fixture boundary", report, "v1.10 evidence source and no-fabrication policy checked.", "Provide truthful real-session evidence or keep the release blocked.");
669
675
  }
670
676
 
671
677
  function validateV110CodeGraphContract(root, target, manifest, projectIndex, preflight, onboarding, initResult, currentTask) {
@@ -39,7 +39,7 @@ npm pack
39
39
  随后在临时项目中使用 tarball 测试。注意不要直接执行 `npx <tarball> --force`,该形式可能不会正确调用 bin。推荐:
40
40
 
41
41
  ```powershell
42
- npx --yes --package E:\ai-fabu-xiangmu\AI开发初始化脚本\xinyun-ai-init-npm\pm_zhousl-xinyun-ai-init-1.10.0.tgz xinyun-ai-init --force --no-version-check
42
+ npx --yes --package E:\ai-fabu-xiangmu\AI开发初始化脚本\xinyun-ai-init-npm\pm_zhousl-xinyun-ai-init-1.10.1.tgz xinyun-ai-init --force --no-version-check
43
43
  ```
44
44
 
45
45
  ### 3. 线上回归测试
@@ -74,7 +74,7 @@ v1.9.0 的 107-118 行为证据必须保存在 `v1.9.0-behavior-evidence.json`
74
74
  ```powershell
75
75
  npm run verify:rules
76
76
  npm run verify:rules -- --json
77
- npm run verify:rules -- --tarball .\pm_zhousl-xinyun-ai-init-1.10.0.tgz
77
+ npm run verify:rules -- --tarball .\pm_zhousl-xinyun-ai-init-1.10.1.tgz
78
78
  npm run verify:rules:security
79
79
  ```
80
80
 
@@ -0,0 +1,23 @@
1
+ # v1.10.0 Takeover Gate Fixture
2
+
3
+ This fixture is synthetic and isolated from any business project. It exists so
4
+ the v1.10 behavior material has a real, packageable fixture boundary.
5
+
6
+ It must only be used for rule replay and evidence-shape checks. It does not
7
+ contain a real Codex role session, a database, SQL, Git metadata, credentials,
8
+ or business source files. A replay result is never evidence of real AI
9
+ acceptance.
10
+
11
+ For real-session evidence, provide an external host export to
12
+ `scripts/collect-v1.10-evidence.js`. The export must contain host-returned
13
+ session IDs, interaction logs, and before/after control-plane snapshots. The
14
+ collector rejects missing or synthetic session IDs and otherwise records
15
+ `not-verified`.
16
+
17
+ Expected synthetic control-plane states:
18
+
19
+ - `before/project-status.json`: `blocked` with
20
+ `required-role-session-not-created`.
21
+ - `after/project-status.json`: remains `blocked` when any required role
22
+ session is absent.
23
+ - `before/after` contain no business files and no sensitive values.
@@ -0,0 +1,7 @@
1
+ {
2
+ "projectStatus": "blocked",
3
+ "executionEligible": false,
4
+ "blockedReason": "required-role-session-not-created",
5
+ "roleSessionCount": 0,
6
+ "businessCodeChanged": "unknown"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "projectStatus": "blocked",
3
+ "executionEligible": false,
4
+ "blockedReason": "required-role-session-not-created",
5
+ "roleSessionCount": 0,
6
+ "businessCodeChanged": "unknown"
7
+ }