@pm_zhousl/xinyun-ai-init 1.11.0 → 1.12.0

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  本目录是“欣芸技术开发 Agent 流”的初始化包,负责把完整 AI 执行要求下发到目标项目。
4
4
 
5
- 当前规则版本:`1.11.0`。
5
+ 当前规则版本:`1.12.0`。
6
6
 
7
7
  ## Codex 一句话入口
8
8
 
@@ -34,6 +34,10 @@
34
34
  - `framework-profile.json` 和 `migration-record.json` 创建后必须确认 JSON 可解析,并同步 `xinyun-ai/index/project-index.json`。
35
35
  - 首次极速初始化不强制创建上述目录;普通咨询也不创建迁移或 profile 记录。
36
36
 
37
+ ## v1.12 接管恢复目录
38
+
39
+ When takeover initialization is authorized, create `host-preflight.json`, `index/initialization-recovery.json`, `sessions/manual-bindings.json`, `index/shared-project-snapshot.json`, and `index/initialization-timing.json` under `xinyun-ai/`. Use atomic writes and preserve blocked state on host or permission failure.
40
+
37
41
  ## v1.7.1 任务树、归档与 CodeGraph 目录
38
42
 
39
43
  - 初始化或升级流程必须补齐 `xinyun-ai/tasks/task-index.json`、`xinyun-ai/tasks/archive/`、`xinyun-ai/tasks/.archive-transactions/`、`xinyun-ai/tasks/.archive-tmp/`。
@@ -56,6 +56,10 @@
56
56
  - CodeGraph 必需任务失败时进入 `blocked`;只有用户明确授权限定范围降级时才允许 `partial`。
57
57
  - 不自动安装 CodeGraph,不修改系统环境、业务代码、数据库、API、配置、依赖或 Git。
58
58
 
59
+ ## v1.12 initialization gate recovery
60
+
61
+ Run the seven-capability host preflight before role sessions. Materialize the main task and five role tasks first; on failure preserve `sessionId=null`, `blockedReason`, and `nextAction`. Explicit `确认执行` or `确认继续初始化` reuses task IDs and increments `attempt` without duplicates.
62
+
59
63
  ## v1.10.2 and v1.11.0 gate
60
64
 
61
65
  - Keep `hostThreadId`, `hostSessionId`, `projectSessionId`, and `orchestratorSessionId` separate. Any value without host evidence remains `null`.
@@ -285,6 +285,10 @@ HTML 迁移只允许评估和单页面 / 区块试点计划;实际代码迁移
285
285
 
286
286
  任何跨会话冲突、状态源缺失、预算超限、权限失败或敏感信息无法确认时暂停或阻塞,不自动重试、合并、覆盖或释放。
287
287
 
288
+ ## v1.12 host preflight and resumable sessions
289
+
290
+ Record all seven host capabilities before role sessions. `available-with-dependency` is not ready until authorized. Manual binding requires a real host-returned session ID and interaction evidence; host thread IDs cannot substitute for project session IDs.
291
+
288
292
  ## v1.10 接管 preflight 与交接
289
293
 
290
294
  交接必须记录 host capability、真实 sessionId、executionEligible 和阻塞原因;宿主不支持时保持 sessionId=null,不得伪造 sessionId。
@@ -116,6 +116,10 @@
116
116
 
117
117
  升级先校验共享事实、状态源和 coordination transaction;再校验 Skill registry、`assignmentStatus`/`usageStatus` 映射;然后处理前端 audit-only 或已确认的单页面试点;最后才创建临时程序员会话。已有用户修改的控制文件不得静默覆盖,冲突或哈希不一致进入 `blocked`/`recovery-required`。
118
118
 
119
+ ## v1.12 recovery and host preflight
120
+
121
+ Before upgrade role-session work, read `xinyun-ai/index/initialization-recovery.json` and `xinyun-ai/host-preflight.json`. Only explicit `确认执行` or `确认继续初始化` resumes the original task IDs with an incremented attempt; missing host sessions remain `sessionId=null` and blocked.
122
+
119
123
  ## v1.10 接管状态升级与恢复
120
124
 
121
125
  升级前读取 `projectStatus` 和全部 preflight 控制文件;冲突进入 blocked/recovery-required,不覆盖用户修改。
@@ -0,0 +1,34 @@
1
+ # v1.12.0 initialization gate recovery contract
2
+
3
+ v1.12 keeps the v1.10 takeover gate and v1.11 acceleration boundary. It adds a bounded host preflight, task-first initialization, resumable role-session binding, CodeGraph reuse, one shared project snapshot, and stage timing. The npm CLI still creates only `xinyun-ai-init/`.
4
+
5
+ ## Host preflight
6
+
7
+ - Before creating or reusing role sessions, check `createRealSession`, `reuseExistingSession`, `sendTask`, `receiveResult`, `recoverSession`, `closeSession`, and `controlFileReadWrite`.
8
+ - Every capability record uses `capabilityId`, `detectionMethod`, `status`, `evidence`, `dependencyStatus`, `fallbackPlan`, `usedTools`, `unusedTools`, `unverifiedScope`, `failureReason`, and `checkedAt`.
9
+ - `available-with-dependency` requires dependency authorization. `unknown`, `unavailable`, `permission-denied`, `failed`, `not-checked`, `not-verified`, and an unauthorized dependency block `ready`.
10
+ - A host thread ID is not a project session ID. Without a real host-returned session ID, keep `sessionId=null`, record the blocker, and do not fabricate an ID.
11
+
12
+ ## Task first and resume
13
+
14
+ - The first initialization write creates one named main task and five role task records before attempting role sessions. The task records remain when host preflight fails.
15
+ - A failed preflight records `sessionId=null`, `blockedReason`, `failureReason`, and `nextAction`; it does not delete tasks or write an idle current task while active tasks exist.
16
+ - Explicit `确认执行` or `确认继续初始化` resumes the same `taskId` and role task IDs from the recorded stage, increments `attempt`, and creates no duplicate tasks.
17
+ - Recovery uses atomic temp-file, fsync, rename, and recovery evidence. Conflicts, user-edited control files, or lock failures pause or block without overwrite or forced unlock.
18
+
19
+ ## Manual binding
20
+
21
+ - A user may bind a real role session through `manual-session-bindings.json`. The record must contain role/task IDs, a host-returned `sessionId`, `boundBy`, `boundAt`, interaction and before/after snapshot evidence, and an audit entry.
22
+ - No evidence means `bindingStatus=blocked` or `pending` and `executionEligible=false`. A bound session becomes eligible only after evidence verification, role onboarding, responsibility confirmation, and all existing gates pass.
23
+
24
+ ## CodeGraph and shared snapshot
25
+
26
+ - Reuse a healthy or initialized CodeGraph index by matching `codeGraphRecordId`, index hash, and source revision. Otherwise run the existing `codegraph init -i` boundary when authorized and available; do not install CodeGraph or repair business code.
27
+ - Record version, index hash, source revision, parse failures, unindexed scope, and failure reason. A required failure cannot claim complete understanding.
28
+ - Build one `shared-project-snapshot.json` for the five roles. Reuse it while business baseline, control-plane hash, CodeGraph index hash, and source revision are unchanged. Rebuild only when a refresh trigger is recorded.
29
+
30
+ ## Timing and safety
31
+
32
+ - Record each stage's attempt, status, start/end, duration, cache hit, failure reason, bottleneck, and recovery action. Stage timing is evidence, not permission to skip a gate.
33
+ - Git none, no test framework, and missing optional toolchains are recorded as limited coverage and do not alone block. Database defaults remain `authorization=not-requested`, `executionStatus=needs-confirmation`, `redactionStatus=verified`; do not connect or execute SQL.
34
+ - Sensitive values never enter tasks, logs, handoffs, JSON, Markdown, stdout, or stderr. No business code, database, API, dependency, system environment, Git write, or npm publish operation is authorized by initialization.
@@ -431,6 +431,8 @@ A single-role write failure records `status=blocked` and `blockedReason=write-fa
431
431
  v1.7.3 Codex role session orchestration is host-level only; CLI still only creates `xinyun-ai-init/`.
432
432
  v1.7.3 fixed Codex role session compatibility fields: `provider=codex`, `sessionStatus=pending/creating/created/onboarding/ready/blocked/failed/closed`, and legacy creation index `{taskId,roleId,provider,targetVersion}`. The v1.9 project-isolated role session reuse contract is authoritative.
433
433
 
434
+ v1.12 host preflight and recovery are authoritative for initialization gating: materialize the main task and five role tasks first, preserve `sessionId=null` when the host is unavailable, resume only after `确认执行` or `确认继续初始化`, reuse task IDs while incrementing attempt, and require real evidence for manual session binding. Reuse healthy CodeGraph and one shared project snapshot only when their hashes and source revision remain stable. Record stage duration, cache hit, bottleneck, failure reason, and recovery action.
435
+
434
436
  ## v1.7.3 Codex 角色会话自动创建与绑定
435
437
 
436
438
  - v1.7.3 只在 5 个 `role-execution` 本地任务已经创建或恢复后,才由 Codex 主会话尝试创建 5 个真实角色子会话:`project-owner`、`project-product`、`chief-engineer`、`programmer`、`test-reviewer`。
@@ -0,0 +1,31 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "preflightId": "host-preflight-template",
4
+ "status": "not-checked",
5
+ "statusEnum": ["not-checked", "running", "passed", "partial", "blocked", "failed", "unknown"],
6
+ "requiredCapabilities": [
7
+ "createRealSession",
8
+ "reuseExistingSession",
9
+ "sendTask",
10
+ "receiveResult",
11
+ "recoverSession",
12
+ "closeSession",
13
+ "controlFileReadWrite"
14
+ ],
15
+ "capabilityStatusEnum": ["available", "available-with-dependency", "unavailable", "permission-denied", "unknown", "not-checked", "not-verified", "failed"],
16
+ "dependencyStatusEnum": ["not-required", "required", "authorized", "not-authorized", "unknown"],
17
+ "capabilities": {
18
+ "createRealSession": {"capabilityId": "createRealSession", "detectionMethod": "host-api", "status": "not-checked", "evidence": [], "dependencyStatus": "unknown", "fallbackPlan": "blocked; keep sessionId=null", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null},
19
+ "reuseExistingSession": {"capabilityId": "reuseExistingSession", "detectionMethod": "host-api", "status": "not-checked", "evidence": [], "dependencyStatus": "unknown", "fallbackPlan": "blocked; query existing binding only", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null},
20
+ "sendTask": {"capabilityId": "sendTask", "detectionMethod": "host-api", "status": "not-checked", "evidence": [], "dependencyStatus": "unknown", "fallbackPlan": "blocked; preserve task for resume", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null},
21
+ "receiveResult": {"capabilityId": "receiveResult", "detectionMethod": "host-api", "status": "not-checked", "evidence": [], "dependencyStatus": "unknown", "fallbackPlan": "blocked; preserve task for resume", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null},
22
+ "recoverSession": {"capabilityId": "recoverSession", "detectionMethod": "host-api", "status": "not-checked", "evidence": [], "dependencyStatus": "unknown", "fallbackPlan": "manual binding with evidence", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null},
23
+ "closeSession": {"capabilityId": "closeSession", "detectionMethod": "host-api", "status": "not-checked", "evidence": [], "dependencyStatus": "unknown", "fallbackPlan": "manual host close", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null},
24
+ "controlFileReadWrite": {"capabilityId": "controlFileReadWrite", "detectionMethod": "filesystem", "status": "not-checked", "evidence": [], "dependencyStatus": "not-required", "fallbackPlan": "blocked on control-file write failure", "usedTools": [], "unusedTools": [], "unverifiedScope": [], "failureReason": null, "checkedAt": null}
25
+ },
26
+ "realSessionIdEvidence": {"required": true, "sessionIds": [], "source": null, "verified": false},
27
+ "readyGate": {"allRequiredCapabilitiesPassed": false, "dependencyAuthorizationRequired": true, "unknownBlocksReady": true, "fakeSessionIdProhibited": true},
28
+ "nextAction": "Run host capability preflight before starting role sessions.",
29
+ "checkedAt": null,
30
+ "updatedAt": null
31
+ }
@@ -9,7 +9,7 @@
9
9
  "statusEnum": ["pending", "initializing", "completed", "partial", "blocked", "unknown", "failed", "cancelled"],
10
10
  "statusSource": "xinyun-ai/current-task.md",
11
11
  "currentVersion": null,
12
- "targetVersion": "1.11.0",
12
+ "targetVersion": "1.12.0",
13
13
  "idempotencyKey": null,
14
14
  "createdFiles": [],
15
15
  "updatedFiles": [],
@@ -59,6 +59,23 @@
59
59
  "hostCapability": "unknown",
60
60
  "degradationReason": null
61
61
  },
62
+ "v112": {
63
+ "hostPreflightPath": "xinyun-ai/host-preflight.json",
64
+ "initializationRecoveryPath": "xinyun-ai/index/initialization-recovery.json",
65
+ "manualSessionBindingsPath": "xinyun-ai/sessions/manual-bindings.json",
66
+ "sharedProjectSnapshotPath": "xinyun-ai/index/shared-project-snapshot.json",
67
+ "initializationTimingPath": "xinyun-ai/index/initialization-timing.json",
68
+ "resumeStatus": "not-started",
69
+ "resumeStatusEnum": ["not-started", "ready-to-resume", "resuming", "completed", "blocked", "failed"],
70
+ "attempt": 1,
71
+ "reusedTaskIds": [],
72
+ "reusedRoleTaskIds": [],
73
+ "duplicateTasksCreated": 0,
74
+ "realSessionIdRequired": true,
75
+ "manualBindingEvidenceRequired": true,
76
+ "projectSnapshotReuse": "not-checked",
77
+ "stageTimingRecorded": false
78
+ },
62
79
  "v19": {
63
80
  "projectIdentityPath": "xinyun-ai/project-identity.json",
64
81
  "technicalLandscapePath": "xinyun-ai/technical-landscape.json",
@@ -0,0 +1,29 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "recoveryId": "initialization-recovery-template",
4
+ "taskId": null,
5
+ "mainTaskId": null,
6
+ "roleTaskIds": [],
7
+ "attempt": 1,
8
+ "status": "not-started",
9
+ "statusEnum": ["not-started", "ready-to-resume", "resuming", "completed", "blocked", "failed"],
10
+ "resumeTriggers": ["确认执行", "确认继续初始化"],
11
+ "resumeFromStage": null,
12
+ "stageIdEnum": ["preflight", "task-materialization", "role-sessions", "codegraph", "snapshot", "onboarding", "final-gate"],
13
+ "reuseContract": {
14
+ "reuseTaskId": true,
15
+ "reuseRoleTaskIds": true,
16
+ "incrementAttempt": true,
17
+ "createDuplicateTasks": false,
18
+ "idempotencyKey": null,
19
+ "keyAlgorithm": "RFC8785-JCS-SHA-256"
20
+ },
21
+ "blockedRoles": [],
22
+ "blockedReason": null,
23
+ "nextAction": "Wait for explicit confirmation or repair the recorded blocker.",
24
+ "lastRecoveryAction": null,
25
+ "recoveryEvidence": [],
26
+ "atomicWrite": {"tempFileRequired": true, "fsyncBeforeRename": true, "rename": true, "recoveryOnFailure": true},
27
+ "createdAt": null,
28
+ "updatedAt": null
29
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "timingId": "initialization-timing-template",
4
+ "taskId": null,
5
+ "attempt": 1,
6
+ "status": "not-started",
7
+ "stageStatusEnum": ["pending", "running", "completed", "skipped", "partial", "blocked", "failed", "recovery-required"],
8
+ "stages": [],
9
+ "stageRequiredFields": ["stageId", "attempt", "status", "startedAt", "finishedAt", "durationMs", "cacheHit", "failureReason", "bottleneck", "recoveryAction"],
10
+ "cacheSummary": {"hitCount": 0, "missCount": 0, "reusedSnapshot": false, "reusedCodeGraph": false, "reusedSessions": 0},
11
+ "bottlenecks": [],
12
+ "recoveryActions": [],
13
+ "totalDurationMs": null,
14
+ "createdAt": null,
15
+ "updatedAt": null
16
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "projectName": "",
3
- "xinyunAiVersion": "1.11.0",
3
+ "xinyunAiVersion": "1.12.0",
4
4
  "scriptVersion": "2026.07.23",
5
5
  "schemaVersion": "1",
6
6
  "initializationMode": "fast",
@@ -56,6 +56,11 @@
56
56
  ,"technicalLandscapeCoordination": true
57
57
  ,"databaseSqlOnlyAuthorization": true
58
58
  ,"projectAiTakeoverGate": true
59
+ ,"hostPreflightRecovery": true
60
+ ,"manualRoleSessionBinding": true
61
+ ,"codeGraphIncrementalReuse": true
62
+ ,"sharedProjectSnapshot": true
63
+ ,"initializationTiming": true
59
64
  ,"hostCapabilityPreflight": true
60
65
  ,"projectStatusGate": true
61
66
  ,"takeoverBaseline": true
@@ -94,7 +99,7 @@
94
99
  "bindings": "xinyun-ai/sessions/role-session-bindings.json",
95
100
  "bindingTemplate": "xinyun-ai-init/templates/role-session-binding.template.json",
96
101
  "parentSessionId": null,
97
- "targetVersion": "1.11.0",
102
+ "targetVersion": "1.12.0",
98
103
  "requiredRoleCount": 5,
99
104
  "statusEnum": [
100
105
  "pending",
@@ -250,6 +255,21 @@
250
255
  "databaseDefault": { "authorization": "not-requested", "executionStatus": "needs-confirmation", "redactionStatus": "verified" },
251
256
  "readyRequires": ["projectIdentity", "codeGraph", "baseline", "teamResponsibility", "roleSessions", "taskTree", "localControlPlane", "legacyHandoff", "hostCapabilities", "sensitiveScan", "noHighRiskBlocker"]
252
257
  },
258
+ "v112": {
259
+ "status": "implemented-in-package",
260
+ "capability": "initializationGateRecovery",
261
+ "hostPreflight": "xinyun-ai/host-preflight.json",
262
+ "initializationRecovery": "xinyun-ai/index/initialization-recovery.json",
263
+ "manualSessionBindings": "xinyun-ai/sessions/manual-bindings.json",
264
+ "sharedProjectSnapshot": "xinyun-ai/index/shared-project-snapshot.json",
265
+ "initializationTiming": "xinyun-ai/index/initialization-timing.json",
266
+ "hostCapabilityStatusEnum": ["available", "available-with-dependency", "unavailable", "permission-denied", "unknown", "not-checked", "not-verified", "failed"],
267
+ "preflightRequiredCapabilities": ["createRealSession", "reuseExistingSession", "sendTask", "receiveResult", "recoverSession", "closeSession", "controlFileReadWrite"],
268
+ "resumeConfirmationPhrases": ["确认执行", "确认继续初始化"],
269
+ "codeGraphReuseStatuses": ["healthy", "initialized"],
270
+ "projectSnapshotReusePolicy": "reuse-until-business-or-codegraph-hash-changes",
271
+ "stageTimingRequiredFields": ["stageId", "attempt", "status", "startedAt", "finishedAt", "durationMs", "cacheHit", "failureReason", "bottleneck", "recoveryAction"]
272
+ },
253
273
  "v111": {
254
274
  "status": "implemented-in-package",
255
275
  "capability": "initializationAcceleration",
@@ -0,0 +1,23 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "bindingId": "manual-session-binding-template",
4
+ "taskId": null,
5
+ "roleTaskId": null,
6
+ "roleId": null,
7
+ "sessionId": null,
8
+ "sessionIdType": "host-returned-real-session",
9
+ "provider": "codex",
10
+ "boundBy": null,
11
+ "boundAt": null,
12
+ "evidence": [],
13
+ "evidenceRequiredFields": ["evidenceType", "source", "sessionId", "interactionHash", "beforeSnapshotHash", "afterSnapshotHash", "recordedAt"],
14
+ "bindingStatus": "pending",
15
+ "bindingStatusEnum": ["pending", "bound", "rejected", "blocked", "released"],
16
+ "executionEligible": false,
17
+ "eligibilityRule": "bound + real sessionId + evidence verified + role onboarding ready",
18
+ "fakeSessionIdProhibited": true,
19
+ "rejectionReason": null,
20
+ "audit": [],
21
+ "createdAt": null,
22
+ "updatedAt": null
23
+ }
@@ -273,6 +273,21 @@
273
273
  "databaseDefault": { "authorization": "not-requested", "executionStatus": "needs-confirmation", "redactionStatus": "verified" },
274
274
  "readyRequires": ["projectIdentity", "codeGraph", "baseline", "teamResponsibility", "roleSessions", "taskTree", "localControlPlane", "legacyHandoff", "hostCapabilities", "sensitiveScan", "noHighRiskBlocker"]
275
275
  },
276
+ "v112": {
277
+ "status": "implemented-in-package",
278
+ "capability": "initializationGateRecovery",
279
+ "hostPreflight": "xinyun-ai/host-preflight.json",
280
+ "initializationRecovery": "xinyun-ai/index/initialization-recovery.json",
281
+ "manualSessionBindings": "xinyun-ai/sessions/manual-bindings.json",
282
+ "sharedProjectSnapshot": "xinyun-ai/index/shared-project-snapshot.json",
283
+ "initializationTiming": "xinyun-ai/index/initialization-timing.json",
284
+ "hostCapabilityStatusEnum": ["available", "available-with-dependency", "unavailable", "permission-denied", "unknown", "not-checked", "not-verified", "failed"],
285
+ "preflightRequiredCapabilities": ["createRealSession", "reuseExistingSession", "sendTask", "receiveResult", "recoverSession", "closeSession", "controlFileReadWrite"],
286
+ "resumeConfirmationPhrases": ["确认执行", "确认继续初始化"],
287
+ "codeGraphReuseStatuses": ["healthy", "initialized"],
288
+ "projectSnapshotReusePolicy": "reuse-until-business-or-codegraph-hash-changes",
289
+ "stageTimingRequiredFields": ["stageId", "attempt", "status", "startedAt", "finishedAt", "durationMs", "cacheHit", "failureReason", "bottleneck", "recoveryAction"]
290
+ },
276
291
  "v111": {
277
292
  "status": "implemented-in-package",
278
293
  "capability": "initializationAcceleration",
@@ -16,7 +16,7 @@
16
16
  "identityEvidence": [],
17
17
  "creationEvidence": []
18
18
  },
19
- "targetVersion": "1.11.0",
19
+ "targetVersion": "1.12.0",
20
20
  "projectRootHash": null,
21
21
  "workspaceScope": {"scopeType": "project-root", "scopePathHashes": [], "scopeRevision": null},
22
22
  "repositoryScopeHash": null,
@@ -66,5 +66,5 @@
66
66
  "roleDisplayName": null,
67
67
  "responsibilityLabel": null,
68
68
  "titleSource": "role-contract",
69
- "titleVersion": "1.11.0"
69
+ "titleVersion": "1.12.0"
70
70
  }
@@ -0,0 +1,24 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "snapshotId": "shared-project-snapshot-template",
4
+ "projectRootHash": null,
5
+ "businessBaselineHash": null,
6
+ "controlPlaneHash": null,
7
+ "codeGraphRecordId": null,
8
+ "codeGraphIndexHash": null,
9
+ "sourceRevision": null,
10
+ "snapshotStatus": "not-checked",
11
+ "snapshotStatusEnum": ["not-checked", "building", "ready", "stale", "partial", "blocked", "failed"],
12
+ "reuseDecision": "unknown",
13
+ "reuseDecisionEnum": ["reuse", "rebuild", "unknown", "blocked"],
14
+ "reusedByRoleIds": [],
15
+ "generatedOnce": false,
16
+ "refreshTriggers": ["business-baseline-changed", "control-plane-conflict", "codegraph-index-hash-changed", "source-revision-changed", "snapshot-corrupt"],
17
+ "coverage": "unknown",
18
+ "unverifiedScope": [],
19
+ "evidence": [],
20
+ "snapshotHash": null,
21
+ "sensitiveScan": {"status": "not-run", "matches": []},
22
+ "createdAt": null,
23
+ "updatedAt": null
24
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageName": "xinyun-ai-init",
3
3
  "displayName": "欣芸技术开发 Agent 流初始化包",
4
- "version": "1.11.0",
4
+ "version": "1.12.0",
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.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "欣芸技术开发 Agent 流初始化包",
5
5
  "bin": {
6
6
  "xinyun-ai-init": "bin/xinyun-ai-init.js"
@@ -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.11.0";
9
+ const CURRENT_VERSION = "1.12.0";
10
10
 
11
11
  const checks = [];
12
12
 
@@ -1901,6 +1901,78 @@ function verifyV110BehaviorEvidence() {
1901
1901
  }
1902
1902
  }
1903
1903
 
1904
+ function verifyV112Contracts() {
1905
+ const requiredFiles = [
1906
+ "init/xinyun-ai-init/rules/v1.12.0-recovery.md",
1907
+ "init/xinyun-ai-init/templates/host-preflight.template.json",
1908
+ "init/xinyun-ai-init/templates/initialization-recovery.template.json",
1909
+ "init/xinyun-ai-init/templates/manual-session-binding.template.json",
1910
+ "init/xinyun-ai-init/templates/shared-project-snapshot.template.json",
1911
+ "init/xinyun-ai-init/templates/initialization-timing.template.json",
1912
+ "test-scenarios/v1.12.0-scenarios.md",
1913
+ "test-scenarios/v1.12.0-behavior-evidence.json",
1914
+ ];
1915
+ for (const file of requiredFiles) requireFile(file);
1916
+
1917
+ let manifest;
1918
+ let projectIndex;
1919
+ let host;
1920
+ let recovery;
1921
+ let binding;
1922
+ let snapshot;
1923
+ let timing;
1924
+ let initResult;
1925
+ try {
1926
+ manifest = JSON.parse(readText("init/xinyun-ai-init/templates/manifest.template.json"));
1927
+ projectIndex = JSON.parse(readText("init/xinyun-ai-init/templates/project-index.template.json"));
1928
+ host = JSON.parse(readText("init/xinyun-ai-init/templates/host-preflight.template.json"));
1929
+ recovery = JSON.parse(readText("init/xinyun-ai-init/templates/initialization-recovery.template.json"));
1930
+ binding = JSON.parse(readText("init/xinyun-ai-init/templates/manual-session-binding.template.json"));
1931
+ snapshot = JSON.parse(readText("init/xinyun-ai-init/templates/shared-project-snapshot.template.json"));
1932
+ timing = JSON.parse(readText("init/xinyun-ai-init/templates/initialization-timing.template.json"));
1933
+ initResult = JSON.parse(readText("init/xinyun-ai-init/templates/init-result.template.json"));
1934
+ } catch (error) {
1935
+ addCheck("v1.12 template JSON parse", false, error.message);
1936
+ return;
1937
+ }
1938
+
1939
+ const paths = ["hostPreflight", "initializationRecovery", "manualSessionBindings", "sharedProjectSnapshot", "initializationTiming"];
1940
+ addCheck("v1.12 manifest/project-index registration", manifest.v112 && projectIndex.v112 && paths.every((key) => manifest.v112[key] === projectIndex.v112[key]), "v1.12 paths must match across index files");
1941
+ addCheck("v1.12 capability flags", ["hostPreflightRecovery", "manualRoleSessionBinding", "codeGraphIncrementalReuse", "sharedProjectSnapshot", "initializationTiming"].every((key) => manifest.capabilities && manifest.capabilities[key] === true), "v1.12 manifest capabilities");
1942
+ addCheck("v1.12 capability enum consistency", JSON.stringify(manifest.v112.hostCapabilityStatusEnum) === JSON.stringify(projectIndex.v112.hostCapabilityStatusEnum) && host.capabilityStatusEnum.every((status) => manifest.v112.hostCapabilityStatusEnum.includes(status)), "host capability statuses are consistent");
1943
+ addCheck("v1.12 required host capabilities", JSON.stringify(host.requiredCapabilities) === JSON.stringify(manifest.v112.preflightRequiredCapabilities) && host.capabilities && manifest.v112.preflightRequiredCapabilities.every((id) => host.capabilities[id]), "all seven host capabilities are required");
1944
+ const capabilityFields = ["capabilityId", "detectionMethod", "status", "evidence", "dependencyStatus", "fallbackPlan", "usedTools", "unusedTools", "unverifiedScope", "failureReason", "checkedAt"];
1945
+ addCheck("v1.12 host capability evidence fields", Object.values(host.capabilities).every((capability) => capabilityFields.every((field) => Object.prototype.hasOwnProperty.call(capability, field))), "host capability minimum evidence fields");
1946
+ addCheck("v1.12 conservative preflight default", host.status === "not-checked" && host.readyGate && host.readyGate.allRequiredCapabilitiesPassed === false && host.readyGate.unknownBlocksReady === true && host.readyGate.fakeSessionIdProhibited === true && host.realSessionIdEvidence.verified === false, "preflight cannot default to ready");
1947
+ addCheck("v1.12 task-first recovery", recovery.status === "not-started" && recovery.reuseContract.reuseTaskId === true && recovery.reuseContract.reuseRoleTaskIds === true && recovery.reuseContract.incrementAttempt === true && recovery.reuseContract.createDuplicateTasks === false && recovery.resumeTriggers.every((trigger) => manifest.v112.resumeConfirmationPhrases.includes(trigger)), "resume reuses IDs and prevents duplicate tasks");
1948
+ addCheck("v1.12 atomic recovery", recovery.atomicWrite && recovery.atomicWrite.tempFileRequired === true && recovery.atomicWrite.fsyncBeforeRename === true && recovery.atomicWrite.rename === true && recovery.atomicWrite.recoveryOnFailure === true, "recovery writes are atomic");
1949
+ addCheck("v1.12 manual binding gate", binding.sessionId === null && binding.bindingStatus === "pending" && binding.executionEligible === false && binding.fakeSessionIdProhibited === true && binding.evidenceRequiredFields.includes("sessionId") && binding.evidenceRequiredFields.includes("interactionHash"), "manual binding requires real evidence");
1950
+ addCheck("v1.12 snapshot reuse", snapshot.generatedOnce === false && snapshot.snapshotStatus === "not-checked" && snapshot.reuseDecision === "unknown" && snapshot.reusedByRoleIds.length === 0 && manifest.v112.projectSnapshotReusePolicy === "reuse-until-business-or-codegraph-hash-changes", "one shared snapshot with explicit refresh triggers");
1951
+ addCheck("v1.12 timing schema", JSON.stringify(timing.stageRequiredFields) === JSON.stringify(manifest.v112.stageTimingRequiredFields) && timing.attempt === 1 && timing.stages.length === 0, "stage duration and recovery evidence fields");
1952
+ addCheck("v1.12 init-result links", initResult.targetVersion === CURRENT_VERSION && initResult.v112 && paths.every((key) => initResult.v112[`${key}Path`] === manifest.v112[key]) && initResult.v112.duplicateTasksCreated === 0 && initResult.v112.realSessionIdRequired === true, "init-result links v1.12 control files");
1953
+ const scenarioText = readText("test-scenarios/v1.12.0-scenarios.md");
1954
+ addCheck("v1.12 scenarios", Array.from({ length: 12 }, (_, index) => 134 + index).every((id) => scenarioText.includes(`## ${id}.`)) && scenarioText.includes("sessionId=null") && scenarioText.includes("确认继续初始化"), "v1.12 scenarios 134-145");
1955
+ let behaviorEvidence;
1956
+ try {
1957
+ behaviorEvidence = JSON.parse(readText("test-scenarios/v1.12.0-behavior-evidence.json"));
1958
+ } catch (error) {
1959
+ addCheck("v1.12 behavior evidence JSON", false, error.message);
1960
+ behaviorEvidence = null;
1961
+ }
1962
+ const behaviorScenarios = behaviorEvidence && Array.isArray(behaviorEvidence.scenarios) ? behaviorEvidence.scenarios : [];
1963
+ addCheck("v1.12 behavior evidence honest gate", behaviorEvidence && behaviorEvidence.evidenceType === "not-verified" && behaviorEvidence.realAiSessionVerified === false && behaviorEvidence.publishBlocked === true && behaviorEvidence.sessionIdPolicy.includes("sessionId remains null"), "real host behavior is not fabricated");
1964
+ addCheck("v1.12 behavior evidence IDs", JSON.stringify(behaviorScenarios.map((scenario) => scenario.scenarioId)) === JSON.stringify(Array.from({ length: 12 }, (_, index) => 134 + index)), "behavior evidence covers 134-145");
1965
+ addCheck("v1.12 behavior evidence not-verified", behaviorScenarios.length === 12 && behaviorScenarios.every((scenario) => scenario.sessionId === null && scenario.result === "not-verified" && scenario.actualOutput === "not-verified" && scenario.sensitiveScan && scenario.sensitiveScan.status === "pass" && scenario.sensitiveScan.matches.length === 0), "unavailable host remains blocked without fake IDs");
1966
+ const releasePath = path.join(root, "version-plans/releases/v1.12.0.md");
1967
+ if (fs.existsSync(releasePath)) {
1968
+ const releaseText = readText("version-plans/releases/v1.12.0.md");
1969
+ addCheck("v1.12 release exclusions", releaseText.includes("No automatic host login") && releaseText.includes("no database connection") && releaseText.includes("no npm publish"), "v1.12 safety and scope exclusions");
1970
+ } else {
1971
+ addCheck("v1.12 release exclusions", true, "source-only release material is not required in tarball");
1972
+ }
1973
+ addCheck("v1.12 rule contract", readText("init/xinyun-ai-init/rules/v1.12.0-recovery.md").includes("available-with-dependency") && readText("init/xinyun-ai-init/rules/v1.12.0-recovery.md").includes("shared-project-snapshot.json"), "v1.12 recovery rule is present");
1974
+ }
1975
+
1904
1976
  function main() {
1905
1977
  requireFile("bin/xinyun-ai-init.js");
1906
1978
  requireFile("init/xinyun-ai-init/README.md");
@@ -1920,6 +1992,7 @@ function main() {
1920
1992
  verifyV19Contracts();
1921
1993
  verifyV19SessionReuseText();
1922
1994
  verifyV110Contracts();
1995
+ verifyV112Contracts();
1923
1996
  verifyTestScenarios();
1924
1997
  verifyJsonAndMarkdown();
1925
1998
 
@@ -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.11.0";
8
+ const VERSION = "1.12.0";
9
9
  const checks = [];
10
10
 
11
11
  function parseArgs(argv) {
@@ -257,12 +257,20 @@ function validatePackageFiles(root, target, isTarball) {
257
257
  "test-scenarios/v1.9.0-behavior-evidence.json",
258
258
  "test-scenarios/v1.10.0-scenarios.md",
259
259
  "test-scenarios/v1.10.0-behavior-evidence.json",
260
+ "test-scenarios/v1.12.0-scenarios.md",
261
+ "test-scenarios/v1.12.0-behavior-evidence.json",
260
262
  "init/xinyun-ai-init/templates/project-identity.template.json",
261
263
  "init/xinyun-ai-init/templates/session-candidates.template.json",
262
264
  "init/xinyun-ai-init/templates/technical-landscape.template.json",
263
265
  "init/xinyun-ai-init/templates/requirement-packet.template.json",
264
266
  "init/xinyun-ai-init/templates/technical-impact-packet.template.json",
265
267
  "init/xinyun-ai-init/templates/database-authorization.template.json",
268
+ "init/xinyun-ai-init/templates/host-preflight.template.json",
269
+ "init/xinyun-ai-init/templates/initialization-recovery.template.json",
270
+ "init/xinyun-ai-init/templates/manual-session-binding.template.json",
271
+ "init/xinyun-ai-init/templates/shared-project-snapshot.template.json",
272
+ "init/xinyun-ai-init/templates/initialization-timing.template.json",
273
+ "init/xinyun-ai-init/rules/v1.12.0-recovery.md",
266
274
  ];
267
275
 
268
276
  for (const file of requiredFiles) requireFile(root, target, file);
@@ -730,6 +738,46 @@ function validateV111Content(root, target) {
730
738
  requireIncludes(root, target, "init/xinyun-ai-init/rules/init-rules.md", ["v1.10.2 and v1.11.0 gate", "fixed-materialization", "bootstrap-snapshot"]);
731
739
  }
732
740
 
741
+ function validateV112Content(root, target) {
742
+ const requiredFiles = [
743
+ "init/xinyun-ai-init/rules/v1.12.0-recovery.md",
744
+ "init/xinyun-ai-init/templates/host-preflight.template.json",
745
+ "init/xinyun-ai-init/templates/initialization-recovery.template.json",
746
+ "init/xinyun-ai-init/templates/manual-session-binding.template.json",
747
+ "init/xinyun-ai-init/templates/shared-project-snapshot.template.json",
748
+ "init/xinyun-ai-init/templates/initialization-timing.template.json",
749
+ "test-scenarios/v1.12.0-scenarios.md",
750
+ "test-scenarios/v1.12.0-behavior-evidence.json",
751
+ ];
752
+ for (const file of requiredFiles) requireFile(root, target, file);
753
+ const manifest = readJson(root, "init/xinyun-ai-init/templates/manifest.template.json");
754
+ const projectIndex = readJson(root, "init/xinyun-ai-init/templates/project-index.template.json");
755
+ const host = readJson(root, "init/xinyun-ai-init/templates/host-preflight.template.json");
756
+ const recovery = readJson(root, "init/xinyun-ai-init/templates/initialization-recovery.template.json");
757
+ const binding = readJson(root, "init/xinyun-ai-init/templates/manual-session-binding.template.json");
758
+ const snapshot = readJson(root, "init/xinyun-ai-init/templates/shared-project-snapshot.template.json");
759
+ const timing = readJson(root, "init/xinyun-ai-init/templates/initialization-timing.template.json");
760
+ const initResult = readJson(root, "init/xinyun-ai-init/templates/init-result.template.json");
761
+ const behaviorEvidence = readJson(root, "test-scenarios/v1.12.0-behavior-evidence.json");
762
+ const paths = ["hostPreflight", "initializationRecovery", "manualSessionBindings", "sharedProjectSnapshot", "initializationTiming"];
763
+ const statuses = ["available", "available-with-dependency", "unavailable", "permission-denied", "unknown", "not-checked", "not-verified", "failed"];
764
+ addCheck(target, "v1.12.registration", "registry", manifest.v112 && projectIndex.v112 && paths.every((key) => manifest.v112[key] === projectIndex.v112[key]) ? "pass" : "fail", "manifest/project-index.v112", "paths", "same", {manifest: manifest.v112, projectIndex: projectIndex.v112}, "v1.12 paths are registered consistently.", "Synchronize v1.12 paths.");
765
+ addCheck(target, "v1.12.capabilities", "manifest", manifest.capabilities && ["hostPreflightRecovery", "manualRoleSessionBinding", "codeGraphIncrementalReuse", "sharedProjectSnapshot", "initializationTiming"].every((key) => manifest.capabilities[key] === true) ? "pass" : "fail", "manifest.template.json", "capabilities", "v1.12 flags", manifest.capabilities, "v1.12 capabilities are registered.", "Register all v1.12 capabilities.");
766
+ addCheck(target, "v1.12.host-enum", "schema", JSON.stringify(host.capabilityStatusEnum) === JSON.stringify(statuses) && JSON.stringify(manifest.v112.hostCapabilityStatusEnum) === JSON.stringify(statuses) && JSON.stringify(projectIndex.v112.hostCapabilityStatusEnum) === JSON.stringify(statuses) ? "pass" : "fail", "host-preflight/manifest/project-index", "capabilityStatusEnum", statuses, {host: host.capabilityStatusEnum, manifest: manifest.v112 && manifest.v112.hostCapabilityStatusEnum, projectIndex: projectIndex.v112 && projectIndex.v112.hostCapabilityStatusEnum}, "Host capability enum is shared.", "Use one complete host capability enum.");
767
+ addCheck(target, "v1.12.host-fields", "schema", host.requiredCapabilities.length === 7 && Object.values(host.capabilities).length === 7 && Object.values(host.capabilities).every((capability) => ["capabilityId", "detectionMethod", "status", "evidence", "dependencyStatus", "fallbackPlan", "usedTools", "unusedTools", "unverifiedScope", "failureReason", "checkedAt"].every((field) => Object.prototype.hasOwnProperty.call(capability, field))) ? "pass" : "fail", "host-preflight.template.json", "capabilities", "seven records with minimum fields", host.capabilities, "Host preflight evidence fields are complete.", "Complete host preflight evidence fields.");
768
+ addCheck(target, "v1.12.ready-gate", "schema", host.readyGate && host.readyGate.allRequiredCapabilitiesPassed === false && host.readyGate.unknownBlocksReady === true && host.readyGate.fakeSessionIdProhibited === true ? "pass" : "fail", "host-preflight.template.json", "readyGate", "conservative default", host.readyGate, "Preflight cannot default to ready.", "Block ready until host evidence is verified.");
769
+ addCheck(target, "v1.12.recovery", "schema", recovery.reuseContract && recovery.reuseContract.reuseTaskId === true && recovery.reuseContract.reuseRoleTaskIds === true && recovery.reuseContract.incrementAttempt === true && recovery.reuseContract.createDuplicateTasks === false && recovery.atomicWrite && recovery.atomicWrite.rename === true ? "pass" : "fail", "initialization-recovery.template.json", "reuse/atomicWrite", "reuse IDs, no duplicate, atomic", recovery, "Recovery contract checked.", "Restore task reuse and atomic recovery.");
770
+ addCheck(target, "v1.12.manual-binding", "schema", binding.sessionId === null && binding.executionEligible === false && binding.fakeSessionIdProhibited === true && binding.evidenceRequiredFields.includes("interactionHash") ? "pass" : "fail", "manual-session-binding.template.json", "binding", "real evidence required", binding, "Manual binding gate checked.", "Require real session evidence.");
771
+ addCheck(target, "v1.12.snapshot", "schema", snapshot.generatedOnce === false && snapshot.snapshotStatus === "not-checked" && snapshot.refreshTriggers.length >= 4 ? "pass" : "fail", "shared-project-snapshot.template.json", "reuse", "conservative snapshot default", snapshot, "Shared snapshot reuse contract checked.", "Record snapshot refresh triggers.");
772
+ addCheck(target, "v1.12.timing", "schema", timing.stageRequiredFields.length === 10 && timing.attempt === 1 && timing.stages.length === 0 ? "pass" : "fail", "initialization-timing.template.json", "stageRequiredFields", "10 fields", timing.stageRequiredFields, "Stage timing contract checked.", "Record all timing fields.");
773
+ addCheck(target, "v1.12.init-result", "schema", initResult.targetVersion === VERSION && initResult.v112 && paths.every((key) => initResult.v112[`${key}Path`] === manifest.v112[key]) && initResult.v112.duplicateTasksCreated === 0 ? "pass" : "fail", "init-result.template.json", "v112", "registered links and zero duplicates", initResult.v112, "Init-result v1.12 links checked.", "Synchronize init-result links.");
774
+ const scenarioText = readText(root, "test-scenarios/v1.12.0-scenarios.md");
775
+ addCheck(target, "v1.12.scenarios", "scenario", Array.from({ length: 12 }, (_, index) => 134 + index).every((id) => scenarioText.includes(`## ${id}.`)) && scenarioText.includes("sessionId=null") ? "pass" : "fail", "test-scenarios/v1.12.0-scenarios.md", "scenarioIds", "134-145", "scanned", "v1.12 scenarios are registered.", "Add all v1.12 scenarios.");
776
+ const behaviorIds = Array.from({ length: 12 }, (_, index) => 134 + index);
777
+ addCheck(target, "v1.12.behavior-evidence", "evidence", behaviorEvidence.evidenceType === "not-verified" && behaviorEvidence.realAiSessionVerified === false && behaviorEvidence.publishBlocked === true && JSON.stringify(behaviorEvidence.scenarios.map((scenario) => scenario.scenarioId)) === JSON.stringify(behaviorIds) && behaviorEvidence.scenarios.every((scenario) => scenario.sessionId === null && scenario.result === "not-verified" && scenario.actualOutput === "not-verified" && scenario.sensitiveScan && scenario.sensitiveScan.status === "pass" && scenario.sensitiveScan.matches.length === 0) ? "pass" : "fail", "v1.12.0-behavior-evidence.json", "realAiSessionVerified/result", "not-verified with null session IDs", behaviorEvidence, "Unavailable host evidence is honest and complete.", "Do not fabricate real session evidence.");
778
+ addCheck(target, "v1.12.rule", "content", readText(root, "init/xinyun-ai-init/rules/v1.12.0-recovery.md").includes("available-with-dependency") && readText(root, "init/xinyun-ai-init/rules/v1.12.0-recovery.md").includes("sessionId=null") ? "pass" : "fail", "v1.12.0-recovery.md", "contract", "preflight and no fake IDs", "scanned", "v1.12 rule contract checked.", "Restore the v1.12 rule contract.");
779
+ }
780
+
733
781
  function validateJsonFiles(root, target) {
734
782
  const jsonFiles = [
735
783
  "package.json",
@@ -747,6 +795,11 @@ function validateJsonFiles(root, target) {
747
795
  "init/xinyun-ai-init/templates/requirement-packet.template.json",
748
796
  "init/xinyun-ai-init/templates/technical-impact-packet.template.json",
749
797
  "init/xinyun-ai-init/templates/database-authorization.template.json",
798
+ "init/xinyun-ai-init/templates/host-preflight.template.json",
799
+ "init/xinyun-ai-init/templates/initialization-recovery.template.json",
800
+ "init/xinyun-ai-init/templates/manual-session-binding.template.json",
801
+ "init/xinyun-ai-init/templates/shared-project-snapshot.template.json",
802
+ "init/xinyun-ai-init/templates/initialization-timing.template.json",
750
803
  ];
751
804
 
752
805
  for (const file of jsonFiles) {
@@ -779,6 +832,7 @@ function validateRoot(root, target, isTarball = false) {
779
832
  validateV19Content(root, target);
780
833
  validateV110Content(root, target);
781
834
  validateV111Content(root, target);
835
+ validateV112Content(root, target);
782
836
  validateJsonFiles(root, target);
783
837
  }
784
838
 
@@ -0,0 +1,29 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "1.12.0",
4
+ "evidenceType": "not-verified",
5
+ "executionMode": "host-capability-unavailable",
6
+ "realAiSessionVerified": false,
7
+ "publishBlocked": true,
8
+ "sessionIdPolicy": "sessionId remains null when the host cannot provide a real project role session",
9
+ "fixturePath": null,
10
+ "businessBaseline": {"beforeHash": null, "afterHash": null, "unchanged": null},
11
+ "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false},
12
+ "blockedReason": "real-role-session-host-unavailable",
13
+ "nextAction": "Run scenarios 134-145 in a host that can return and verify real project role session IDs.",
14
+ "recordedAt": "2026-07-27T00:00:00.000Z",
15
+ "scenarios": [
16
+ {"scenarioId": 134, "sessionId": null, "input": "not executed: host preflight cannot create a real project role session", "expectedOutput": "all seven host capabilities are checked before role sessions", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
17
+ {"scenarioId": 135, "sessionId": null, "input": "not executed: host capability failure matrix requires a real role session", "expectedOutput": "unknown and dependency-gated capabilities block ready", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
18
+ {"scenarioId": 136, "sessionId": null, "input": "not executed: task-first initialization requires a real host interaction", "expectedOutput": "main and five role tasks persist before session creation", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
19
+ {"scenarioId": 137, "sessionId": null, "input": "not executed: confirmation resume requires a real host interaction", "expectedOutput": "same task IDs are reused and attempt increments without duplicates", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
20
+ {"scenarioId": 138, "sessionId": null, "input": "not executed: recovery write failure requires a real host interaction", "expectedOutput": "control state is preserved and recovery-required or blocked is recorded", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
21
+ {"scenarioId": 139, "sessionId": null, "input": "not executed: manual binding requires a real host-returned session ID", "expectedOutput": "binding is blocked without real evidence and executionEligible remains false", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
22
+ {"scenarioId": 140, "sessionId": null, "input": "not executed: CodeGraph reuse requires a real host interaction", "expectedOutput": "healthy index is reused when record, hash, and revision match", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
23
+ {"scenarioId": 141, "sessionId": null, "input": "not executed: CodeGraph incremental initialization requires a real host interaction", "expectedOutput": "missing or unusable index records init evidence and unverified scope", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
24
+ {"scenarioId": 142, "sessionId": null, "input": "not executed: shared project snapshot requires a real host interaction", "expectedOutput": "one snapshot is reused by five roles until a refresh trigger", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
25
+ {"scenarioId": 143, "sessionId": null, "input": "not executed: stage timing requires a real host interaction", "expectedOutput": "each stage records duration, cache hit, bottleneck, failure, and recovery", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
26
+ {"scenarioId": 144, "sessionId": null, "input": "not executed: optional capability degradation requires a real host interaction", "expectedOutput": "Git none and missing optional tools reduce coverage without false pass", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"},
27
+ {"scenarioId": 145, "sessionId": null, "input": "not executed: database and safety boundary requires a real host interaction", "expectedOutput": "database remains not-requested and no forbidden operation runs", "actualOutput": "not-verified", "beforeSnapshotHash": null, "afterSnapshotHash": null, "changedFiles": [], "controlFilesChanged": [], "forbiddenOperations": {"databaseConnection": false, "sqlExecution": false, "gitWrite": false, "businessCodeWrite": false, "dependencyInstall": false, "npmPublish": false}, "evidence": [], "sensitiveScan": {"status": "pass", "matches": []}, "result": "not-verified", "recordedAt": "2026-07-27T00:00:00.000Z"}
28
+ ]
29
+ }
@@ -0,0 +1,51 @@
1
+ # v1.12.0 Behavior Scenarios
2
+
3
+ Every scenario records input, expected output, actual output, before/after control-plane snapshots, changed business files, control files changed, forbidden operations, evidence, and sensitive-scan status. A host thread ID is never accepted as a project session ID.
4
+
5
+ ## 134. Host preflight success
6
+
7
+ Check all seven required capabilities and real session ID evidence before role-session creation. Only a complete, verified matrix may continue.
8
+
9
+ ## 135. Host preflight blocked
10
+
11
+ Simulate unavailable, permission-denied, unknown, failed, and available-with-dependency capabilities. The result is blocked or partial with failure reason and next action; it is never ready.
12
+
13
+ ## 136. Task-first initialization
14
+
15
+ Create the named main task and five role tasks before session creation. When the host is unavailable, each role `sessionId=null` and active tasks remain visible.
16
+
17
+ ## 137. Resume after confirmation
18
+
19
+ After `确认执行` or `确认继续初始化`, reuse the original task and role task IDs, increment attempt, resume from the recorded stage, and create zero duplicate tasks.
20
+
21
+ ## 138. Recovery and atomic write failure
22
+
23
+ Simulate a failed write, lock conflict, user-edited control file, and recovery. Preserve prior state, record recovery-required/blocked, and do not force unlock or overwrite.
24
+
25
+ ## 139. Manual real-session binding
26
+
27
+ Bind a real host-returned session with actor, time, interaction evidence, before/after snapshot hashes, and audit. Missing evidence keeps the binding blocked and executionEligible=false.
28
+
29
+ ## 140. CodeGraph healthy reuse
30
+
31
+ Reuse a healthy index when record ID, index hash, and source revision match. No second initialization is performed.
32
+
33
+ ## 141. CodeGraph incremental initialization
34
+
35
+ When the index is missing or unusable, run the existing `codegraph init -i` boundary only when available and authorized. Record version, hash, parse failures, unindexed scope, and failure reason.
36
+
37
+ ## 142. Shared project snapshot
38
+
39
+ Generate one snapshot and reference its hash from all five role records. Reuse it without rescanning while hashes are unchanged; rebuild after a recorded refresh trigger.
40
+
41
+ ## 143. Stage timing
42
+
43
+ Record stage status, attempt, start/end, duration, cache hit, failure reason, bottleneck, and recovery action. Timing must not bypass gates.
44
+
45
+ ## 144. Optional capability degradation
46
+
47
+ Git none, missing test framework, or an undetected optional toolchain is recorded as limited coverage and unverified scope, without falsely claiming tests passed or unnecessarily blocking takeover.
48
+
49
+ ## 145. Database and safety boundary
50
+
51
+ Keep `authorization=not-requested`, `executionStatus=needs-confirmation`, and `redactionStatus=verified`. The AI must not connect, execute SQL, install dependencies, modify business files, write Git, or publish.