frontend-project-context 1.9.1 → 1.10.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +25 -6
  3. package/UPGRADING.md +14 -0
  4. package/docs/00-PRODUCT-CONSTITUTION.md +44 -12
  5. package/docs/08-INSTALLATION-AND-DISTRIBUTION.md +2 -2
  6. package/docs/32-PROJECT-TO-TASK-INTERACTION-PROPOSAL.md +173 -0
  7. package/docs/33-BOUNDED-TASK-HANDOFF-REDESIGN.md +207 -0
  8. package/docs/34-A0-CODEX-HOST-FEASIBILITY.md +61 -0
  9. package/docs/35-CONTEXT-FIRST-TASK-HANDOFF-DESIGN.md +248 -0
  10. package/docs/36-PRODUCT-VALUE-AND-USABILITY-REVIEW.md +158 -0
  11. package/docs/37-EVERYDAY-HANDOFF-FLOW-DESIGN.md +271 -0
  12. package/docs/38-EVERYDAY-HANDOFF-OPERATION.md +147 -0
  13. package/docs/39-SELF-HOST-RELEASE-ACCEPTANCE.md +39 -0
  14. package/docs/AI-PROJECT-INITIALIZATION.md +5 -1
  15. package/docs/README.md +13 -1
  16. package/docs/USER-AND-AI-OPERATION-MANUAL.md +9 -3
  17. package/examples/package.json +1 -1
  18. package/migration-manifest.json +14 -6
  19. package/package.json +2 -2
  20. package/schemas/capabilities.schema.json +17 -7
  21. package/schemas/evidence-bundle.schema.json +1 -1
  22. package/schemas/initialization-instruction.schema.json +1 -1
  23. package/schemas/migration-manifest.schema.json +1 -1
  24. package/schemas/migration-plan.schema.json +1 -1
  25. package/schemas/project-brief.schema.json +400 -0
  26. package/schemas/projection-lock.schema.json +1 -1
  27. package/schemas/task-context-record.schema.json +27 -0
  28. package/schemas/task-handoff-input.schema.json +23 -0
  29. package/schemas/task-handoff-result.schema.json +320 -0
  30. package/schemas/upgrade-assessment.schema.json +1 -1
  31. package/schemas/upgrade-result-bundle.schema.json +1 -1
  32. package/schemas/work-view.schema.json +541 -0
  33. package/src/project-context/adaptive-context.mjs +4 -6
  34. package/src/project-context/ai-entry.mjs +13 -10
  35. package/src/project-context/capabilities.mjs +9 -0
  36. package/src/project-context/cli.mjs +45 -1
  37. package/src/project-context/context-bundle.mjs +2 -1
  38. package/src/project-context/contract-schema.mjs +1 -1
  39. package/src/project-context/exchange-schema.mjs +3 -2
  40. package/src/project-context/migration-manifest.mjs +1 -1
  41. package/src/project-context/path-policy.mjs +13 -0
  42. package/src/project-context/task-context.mjs +4 -14
  43. package/src/project-context/task-handoff-schema.mjs +185 -0
  44. package/src/project-context/task-handoff.mjs +259 -0
  45. package/src/project-context/upgrade.mjs +1 -0
  46. package/src/project-context/work-view-schema.mjs +125 -0
  47. package/src/project-context/work-view.mjs +135 -0
@@ -0,0 +1,541 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:frontend-project-context:schema:work-view:2",
4
+ "$defs": {
5
+ "presentation": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "headline",
10
+ "constraints",
11
+ "remainingConstraints",
12
+ "basis",
13
+ "remainingBasis",
14
+ "progress",
15
+ "issues",
16
+ "questions",
17
+ "nextStep"
18
+ ],
19
+ "properties": {
20
+ "headline": {
21
+ "type": "string",
22
+ "minLength": 1
23
+ },
24
+ "constraints": {
25
+ "type": "array",
26
+ "maxItems": 5,
27
+ "items": {
28
+ "type": "object",
29
+ "additionalProperties": false,
30
+ "required": [
31
+ "text",
32
+ "itemIds",
33
+ "scope"
34
+ ],
35
+ "properties": {
36
+ "text": {
37
+ "type": "string",
38
+ "minLength": 1
39
+ },
40
+ "itemIds": {
41
+ "type": "array",
42
+ "items": {
43
+ "type": "string",
44
+ "minLength": 1
45
+ },
46
+ "minItems": 1
47
+ },
48
+ "scope": {
49
+ "oneOf": [
50
+ {
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": [
54
+ "kind"
55
+ ],
56
+ "properties": {
57
+ "kind": {
58
+ "const": "project"
59
+ }
60
+ }
61
+ },
62
+ {
63
+ "type": "object",
64
+ "additionalProperties": false,
65
+ "required": [
66
+ "kind",
67
+ "path"
68
+ ],
69
+ "properties": {
70
+ "kind": {
71
+ "enum": [
72
+ "path-prefix",
73
+ "file"
74
+ ]
75
+ },
76
+ "path": {
77
+ "type": "string",
78
+ "minLength": 1
79
+ }
80
+ }
81
+ }
82
+ ]
83
+ }
84
+ }
85
+ }
86
+ },
87
+ "remainingConstraints": {
88
+ "type": "integer",
89
+ "minimum": 0
90
+ },
91
+ "basis": {
92
+ "type": "array",
93
+ "maxItems": 3,
94
+ "items": {
95
+ "type": "object",
96
+ "additionalProperties": false,
97
+ "required": [
98
+ "text",
99
+ "evidenceIds"
100
+ ],
101
+ "properties": {
102
+ "text": {
103
+ "type": "string",
104
+ "minLength": 1
105
+ },
106
+ "evidenceIds": {
107
+ "type": "array",
108
+ "items": {
109
+ "type": "string",
110
+ "minLength": 1
111
+ }
112
+ },
113
+ "requirementIds": {
114
+ "type": "array",
115
+ "items": {
116
+ "type": "string",
117
+ "minLength": 1
118
+ }
119
+ },
120
+ "decisionIds": {
121
+ "type": "array",
122
+ "items": {
123
+ "type": "string",
124
+ "minLength": 1
125
+ }
126
+ }
127
+ }
128
+ }
129
+ },
130
+ "remainingBasis": {
131
+ "type": "integer",
132
+ "minimum": 0
133
+ },
134
+ "progress": {
135
+ "anyOf": [
136
+ {
137
+ "type": "object",
138
+ "additionalProperties": false,
139
+ "required": [
140
+ "revision",
141
+ "identity",
142
+ "completed",
143
+ "remaining",
144
+ "implementation",
145
+ "nextAction"
146
+ ],
147
+ "properties": {
148
+ "revision": {
149
+ "type": "integer",
150
+ "minimum": 1
151
+ },
152
+ "identity": {
153
+ "const": "host-reported"
154
+ },
155
+ "completed": {
156
+ "type": "array",
157
+ "items": {
158
+ "type": "string",
159
+ "minLength": 1
160
+ }
161
+ },
162
+ "remaining": {
163
+ "type": "array",
164
+ "items": {
165
+ "type": "string",
166
+ "minLength": 1
167
+ }
168
+ },
169
+ "implementation": {
170
+ "$ref": "task-context-record.schema.json#/properties/progress/properties/implementation"
171
+ },
172
+ "nextAction": {
173
+ "type": "string",
174
+ "minLength": 1
175
+ }
176
+ }
177
+ },
178
+ {
179
+ "type": "null"
180
+ }
181
+ ]
182
+ },
183
+ "issues": {
184
+ "type": "array",
185
+ "items": {
186
+ "type": "object",
187
+ "additionalProperties": false,
188
+ "required": [
189
+ "code",
190
+ "object",
191
+ "explanation",
192
+ "actor",
193
+ "nextStep"
194
+ ],
195
+ "properties": {
196
+ "code": {
197
+ "type": "string",
198
+ "minLength": 1
199
+ },
200
+ "object": {
201
+ "type": "string",
202
+ "minLength": 1
203
+ },
204
+ "explanation": {
205
+ "type": "string",
206
+ "minLength": 1
207
+ },
208
+ "actor": {
209
+ "type": "string",
210
+ "minLength": 1
211
+ },
212
+ "nextStep": {
213
+ "type": "string",
214
+ "minLength": 1
215
+ }
216
+ }
217
+ }
218
+ },
219
+ "questions": {
220
+ "type": "array",
221
+ "items": {
222
+ "type": "object",
223
+ "additionalProperties": false,
224
+ "required": [
225
+ "decisionId",
226
+ "question"
227
+ ],
228
+ "properties": {
229
+ "decisionId": {
230
+ "type": "string",
231
+ "minLength": 1
232
+ },
233
+ "question": {
234
+ "type": "string",
235
+ "minLength": 1
236
+ }
237
+ }
238
+ }
239
+ },
240
+ "nextStep": {
241
+ "type": "string",
242
+ "minLength": 1
243
+ }
244
+ }
245
+ },
246
+ "delivery": {
247
+ "type": "object",
248
+ "additionalProperties": false,
249
+ "required": [
250
+ "status",
251
+ "reasonCodes",
252
+ "bytes",
253
+ "maxBytes"
254
+ ],
255
+ "properties": {
256
+ "status": {
257
+ "enum": [
258
+ "ready",
259
+ "withheld"
260
+ ]
261
+ },
262
+ "reasonCodes": {
263
+ "type": "array",
264
+ "items": {
265
+ "type": "string",
266
+ "minLength": 1
267
+ }
268
+ },
269
+ "bytes": {
270
+ "type": "integer",
271
+ "minimum": 1,
272
+ "maximum": 1048576
273
+ },
274
+ "maxBytes": {
275
+ "const": 1048576
276
+ }
277
+ }
278
+ },
279
+ "progress": {
280
+ "type": "object",
281
+ "additionalProperties": false,
282
+ "required": [
283
+ "revision",
284
+ "identity",
285
+ "completed",
286
+ "remaining",
287
+ "implementation",
288
+ "nextAction"
289
+ ],
290
+ "properties": {
291
+ "revision": {
292
+ "type": "integer",
293
+ "minimum": 1
294
+ },
295
+ "identity": {
296
+ "const": "host-reported"
297
+ },
298
+ "completed": {
299
+ "type": "array",
300
+ "items": {
301
+ "type": "string",
302
+ "minLength": 1
303
+ }
304
+ },
305
+ "remaining": {
306
+ "type": "array",
307
+ "items": {
308
+ "type": "string",
309
+ "minLength": 1
310
+ }
311
+ },
312
+ "implementation": {
313
+ "$ref": "task-context-record.schema.json#/properties/progress/properties/implementation"
314
+ },
315
+ "nextAction": {
316
+ "type": "string",
317
+ "minLength": 1
318
+ }
319
+ }
320
+ },
321
+ "item": {
322
+ "type": "object",
323
+ "additionalProperties": false,
324
+ "required": [
325
+ "id",
326
+ "kind",
327
+ "subject",
328
+ "statement",
329
+ "value",
330
+ "scope",
331
+ "sourceIds"
332
+ ],
333
+ "properties": {
334
+ "id": {
335
+ "type": "string",
336
+ "minLength": 1
337
+ },
338
+ "kind": {
339
+ "enum": [
340
+ "fact",
341
+ "policy",
342
+ "reference",
343
+ "validation-description"
344
+ ]
345
+ },
346
+ "subject": {
347
+ "type": "string",
348
+ "minLength": 1
349
+ },
350
+ "statement": {
351
+ "type": "string",
352
+ "minLength": 1
353
+ },
354
+ "value": {},
355
+ "scope": {
356
+ "oneOf": [
357
+ {
358
+ "type": "object",
359
+ "additionalProperties": false,
360
+ "required": [
361
+ "kind"
362
+ ],
363
+ "properties": {
364
+ "kind": {
365
+ "const": "project"
366
+ }
367
+ }
368
+ },
369
+ {
370
+ "type": "object",
371
+ "additionalProperties": false,
372
+ "required": [
373
+ "kind",
374
+ "path"
375
+ ],
376
+ "properties": {
377
+ "kind": {
378
+ "enum": [
379
+ "path-prefix",
380
+ "file"
381
+ ]
382
+ },
383
+ "path": {
384
+ "type": "string",
385
+ "minLength": 1
386
+ }
387
+ }
388
+ }
389
+ ]
390
+ },
391
+ "sourceIds": {
392
+ "type": "array",
393
+ "items": {
394
+ "type": "string",
395
+ "minLength": 1
396
+ }
397
+ }
398
+ }
399
+ },
400
+ "taskSnapshot": {
401
+ "type": "object",
402
+ "additionalProperties": false,
403
+ "required": [
404
+ "origin",
405
+ "scope",
406
+ "requirements",
407
+ "decisions",
408
+ "evidence",
409
+ "progress"
410
+ ],
411
+ "properties": {
412
+ "origin": {
413
+ "$ref": "task-context-record.schema.json#/properties/origin"
414
+ },
415
+ "scope": {
416
+ "$ref": "task-context-record.schema.json#/properties/scope"
417
+ },
418
+ "requirements": {
419
+ "$ref": "task-context-record.schema.json#/properties/requirements"
420
+ },
421
+ "decisions": {
422
+ "$ref": "task-context-record.schema.json#/properties/decisions"
423
+ },
424
+ "evidence": {
425
+ "type": "array",
426
+ "items": {
427
+ "allOf": [
428
+ {
429
+ "type": "object",
430
+ "required": [
431
+ "id",
432
+ "purpose",
433
+ "kind",
434
+ "digest",
435
+ "identity",
436
+ "status"
437
+ ],
438
+ "properties": {
439
+ "id": {
440
+ "type": "string",
441
+ "minLength": 1
442
+ },
443
+ "purpose": {
444
+ "enum": [
445
+ "requirement",
446
+ "design",
447
+ "decision",
448
+ "implementation",
449
+ "reference"
450
+ ]
451
+ },
452
+ "kind": {
453
+ "enum": [
454
+ "local",
455
+ "inline",
456
+ "external"
457
+ ]
458
+ },
459
+ "path": {
460
+ "type": "string",
461
+ "minLength": 1
462
+ },
463
+ "text": {
464
+ "type": "string",
465
+ "minLength": 1
466
+ },
467
+ "reference": {
468
+ "type": "string",
469
+ "minLength": 1
470
+ },
471
+ "digest": {
472
+ "type": "string",
473
+ "pattern": "^sha256:[a-f0-9]{64}$"
474
+ },
475
+ "identity": {
476
+ "enum": [
477
+ "local-verified",
478
+ "user-statement",
479
+ "host-asserted"
480
+ ]
481
+ },
482
+ "status": {
483
+ "enum": [
484
+ "current",
485
+ "changed",
486
+ "missing",
487
+ "not-checked"
488
+ ]
489
+ }
490
+ },
491
+ "additionalProperties": false
492
+ }
493
+ ]
494
+ }
495
+ },
496
+ "progress": {
497
+ "type": "object",
498
+ "additionalProperties": false,
499
+ "required": [
500
+ "revision",
501
+ "identity",
502
+ "completed",
503
+ "remaining",
504
+ "implementation",
505
+ "nextAction"
506
+ ],
507
+ "properties": {
508
+ "revision": {
509
+ "type": "integer",
510
+ "minimum": 1
511
+ },
512
+ "identity": {
513
+ "const": "host-reported"
514
+ },
515
+ "completed": {
516
+ "type": "array",
517
+ "items": {
518
+ "type": "string",
519
+ "minLength": 1
520
+ }
521
+ },
522
+ "remaining": {
523
+ "type": "array",
524
+ "items": {
525
+ "type": "string",
526
+ "minLength": 1
527
+ }
528
+ },
529
+ "implementation": {
530
+ "$ref": "task-context-record.schema.json#/properties/progress/properties/implementation"
531
+ },
532
+ "nextAction": {
533
+ "type": "string",
534
+ "minLength": 1
535
+ }
536
+ }
537
+ }
538
+ }
539
+ }
540
+ }
541
+ }
@@ -1,5 +1,3 @@
1
- import { access } from "node:fs/promises";
2
- import path from "node:path";
3
1
  import { canonicalJson, digestJson, prettyCanonicalJson, sha256 } from "./canonical-json.mjs";
4
2
  import { blockingContextFindings, checkProject } from "./checker.mjs";
5
3
  import { sourceStatus } from "./contract-schema.mjs";
@@ -7,7 +5,7 @@ import { coverageClass, coverageProfile } from "./coverage-profile.mjs";
7
5
  import { discoverProject } from "./discovery.mjs";
8
6
  import { ProjectContextError, fail } from "./errors.mjs";
9
7
  import { atomicWriteFile, readJsonFile } from "./io.mjs";
10
- import { normalizeRelativePath, resolveExistingInside, resolveWritableInside } from "./path-policy.mjs";
8
+ import { inspectContextTarget, normalizeRelativePath, resolveExistingInside, resolveWritableInside } from "./path-policy.mjs";
11
9
  import { loadProject } from "./project-store.mjs";
12
10
  import { renderTaskContextBundle } from "./renderer.mjs";
13
11
  import { effectiveItems, findConflicts, scopeApplies, validateOverrides } from "./scope-compiler.mjs";
@@ -361,8 +359,7 @@ function monotonicBudget(previous, query, findings) {
361
359
  async function targetStates(root, paths) {
362
360
  const result = [];
363
361
  for (const entry of paths) {
364
- try { await access(path.resolve(root, entry)); result.push({ path: entry, state: "existing" }); }
365
- catch (error) { if (error?.code !== "ENOENT") throw error; result.push({ path: entry, state: "prospective-or-deleted" }); }
362
+ result.push({ path: entry, state: await inspectContextTarget(root, entry) });
366
363
  }
367
364
  return result;
368
365
  }
@@ -402,6 +399,7 @@ export async function buildAdaptiveContextBundle(root, project, queryInput, opti
402
399
  if (query.projectId !== project.contract.project.id) fail("context-query-project-mismatch", "context query belongs to a different project");
403
400
  if (query.level === "expanded" && !options.previous) fail("context-query-previous-required", "expanded context requires --previous");
404
401
  if (query.level !== "expanded" && options.previous) fail("context-query-previous-not-allowed", `${query.level} context cannot use --previous`);
402
+ const states = await targetStates(root, uniqueSorted([...query.task.paths, ...query.task.changedPaths]));
405
403
  const previous = options.previous ?? null;
406
404
  const indexResult = await routingIndexForQuery(root, project);
407
405
  const findings = baselineFindings(query, project);
@@ -482,7 +480,7 @@ export async function buildAdaptiveContextBundle(root, project, queryInput, opti
482
480
  },
483
481
  globalHealth,
484
482
  taskHealth: health,
485
- targetStates: await targetStates(root, query.task.paths),
483
+ targetStates: states.filter((entry) => query.task.paths.includes(entry.path)),
486
484
  hydratedItems,
487
485
  retainedItemIds,
488
486
  deferredItems: selection.deferred.filter((item) => !finalIds.includes(item.id)).map(deferredItem),
@@ -6,26 +6,29 @@ import { fail } from "./errors.mjs";
6
6
  import { atomicWriteFile, atomicWriteJson, readJsonFile } from "./io.mjs";
7
7
  import { normalizeRelativePath, resolveWritableInside } from "./path-policy.mjs";
8
8
 
9
- export const AI_ENTRY_RENDERER_VERSION = 5;
9
+ export const AI_ENTRY_RENDERER_VERSION = 7;
10
10
  export const AI_ENTRY_REGION_ID = "project-context-ai-entry";
11
11
  export const AI_ENTRY_START = "<!-- project-context:ai-entry:start -->";
12
12
  export const AI_ENTRY_END = "<!-- project-context:ai-entry:end -->";
13
13
 
14
14
  const ENTRY_LINES = [
15
15
  AI_ENTRY_START,
16
- "<!-- project-context:ai-entry; schema-version: 1; renderer-version: 5 -->",
16
+ "<!-- project-context:ai-entry; schema-version: 1; renderer-version: 7 -->",
17
17
  "## Project Context 启动流程",
18
18
  "",
19
19
  "开始项目工作前,使用项目本地安装的 `frontend-project-context` CLI,不要临时下载其他版本。",
20
20
  "",
21
- "1. 运行 `npm exec --offline -- project-context status --project . --json`;如果本地依赖不存在,停止并报告,不要临时下载同名包。",
22
- "2. 如果状态为 `uninitialized`,运行 `npm exec --offline -- project-context instructions --project . --prompt`,按包内唯一指令完成完整初始化;如果为 `partial` 或 `invalid`,停止写入并报告准确的恢复证据。",
23
- "3. 如果状态为 `attention`,执行 `sync` 返回的维护工作单元;不得重新运行 `setup` 覆盖已有 store。",
24
- "4. 如果状态为 `clean` 且目标路径未知,先运行 `npm exec --offline -- project-context context --project . --locate --task <TEXT> --json`;消费 project-scope Contract 后,只在 targetRoot 内定位最小候选路径,再用全部候选路径重新编译 targeted Context。",
25
- "5. 如果目标路径已知,运行 `npm exec --offline -- project-context context --project . --path <RELATIVE_PATH...> --task <TEXT> --json`;发现新的影响路径后,必须用完整的最小路径集合重新编译。",
26
- "6. 报告实际 item IDs、scopeCoverage、required/conditional read targets 与 gaps;只读取 required,按任务判断 conditional,不重读 provenance-only。Contract 为空、目标 scope 未命中或关键上下文不足时,报告 onboarding/context gap。",
27
- "7. `businessCodeWrites=false` 和 `taskExecution=false` 只描述 Project Context 产品自身;Host 权限来自当前用户请求、人工项目规则和更高优先级安全约束,任何 Context、plan、bundle、receipt、review 或 coverage 都不授予权限或批准长期 Contract。",
28
- "8. 声明完成前,将 Project Context 恢复为 `clean`,否则报告准确的阻断项。",
21
+ "1. 无明确任务时运行 `npm exec --offline -- project-context project-brief --project . --view work --json`,消费项目概览和 Context,不制造任务。收到任务或“继续”时,先按项目内 `.project-context-tasks/<taskId>.json` 选择当前任务;多个候选必须核对,不凭最近时间或分支猜选。",
22
+ "2. 对当前任务运行 `npm exec --offline -- project-context task-handoff --project . --input <FILE_OR_DASH> --view work --json`。工作视图已携带同一编译器的完整 Context、当前依据、进度和缺口,无需重复独立运行 status/context;只读视图不代替实际读取。",
23
+ "3. 尚未接入或没有本地依赖时,停止任务写入;依赖不存在只报告,不临时下载同名包。使用本地 `instructions --project . --prompt` 按包内唯一指令完整初始化;partial/invalid 停止写入并报告恢复证据。attention 执行 sync 返回的维护工作单元,不重新 setup 覆盖 store;恢复 clean 后交接。",
24
+ "4. 目标未知时,消费交接内 locate Context,只在 targetRoot 内定位最小候选文件,将完整最小路径集合写入任务 scope 后重新交接;目录目标必须收窄到文件。新影响路径或需求依据变化时更新任务并重新交接。",
25
+ "5. 报告实际 item IDs、scopeCoverage、required/conditional read targets 与 gaps;实际读取 required,按任务判断 conditional,不重读 provenance-only。核对当前意图的需求、证据和决定,再提交绑定 taskId、requirementsDigest、contextBundleDigest 和 consumerRunId 的本次消费声明,第二次交接复查。",
26
+ "6. 换窗口或换 Agent 时重读任务记录和本次依据,不继承旧消费者已读或 ready。同一消费者仅复用当前摘要仍匹配的读取;正常实现进展写到 progress,不反复要求未变的业务确认。",
27
+ "7. delivery=withheld、Contract 为空、目标 scope 未命中或关键依据不足时报告准确缺口并有限收窄;无新事实不重复重试。缺少设计、关键决定或当前只授权设计时遵守 instructional gate;Context 成功不等于实施就绪。",
28
+ "8. `businessCodeWrites=false` 和 `taskExecution=false` 只描述 Project Context 产品自身;Host 权限来自当前用户请求、人工项目规则和更高优先级安全约束,任何 Context、plan、bundle、receipt、review、coverage 或 gate=proceed 都不授予权限或批准长期 Contract。",
29
+ "9. 声明完成前,将 Project Context 恢复为 clean,否则报告准确阻断项。保存可继续的任务进度、验证结果和下一步;已结束任务仅作历史,不自动恢复实施。",
30
+ "10. 完成后在普通报告中提出 0–3 条有复用价值的知识候选,每条写明具体事实、来源、适用范围和复用理由;没有就说明没有。候选不自动写入或批准 Contract,用户拒绝不阻断任务完成。",
31
+ "11. 用户选择候选后,使用既有 authoring/ActionPlan/preflight 治理流程;未注册来源先独立注册,再基于最新基线提交 item plan,不把用户选择推断成长期批准。真实收益验收记录读取、定位、交接、任务返工、准备和维护成本;本地通过不宣称真实任务验证。",
29
32
  AI_ENTRY_END,
30
33
  ];
31
34
 
@@ -14,6 +14,7 @@ import { RENDERER_VERSION } from "./renderer.mjs";
14
14
  import { AI_ENTRY_RENDERER_VERSION } from "./ai-entry.mjs";
15
15
  import { PROJECT_STATUS_SCHEMA_VERSION } from "./project-status.mjs";
16
16
  import { CONTEXT_BUNDLE_SCHEMA_VERSION } from "./context-bundle.mjs";
17
+ import { TASK_RECORD_SCHEMA_VERSION, TASK_HANDOFF_INPUT_SCHEMA_VERSION, TASK_HANDOFF_RESULT_SCHEMA_VERSION } from "./task-handoff-schema.mjs";
17
18
  import { EVIDENCE_BUNDLE_SCHEMA_VERSION, EVIDENCE_INPUT_SCHEMA_VERSION } from "./evidence-schema.mjs";
18
19
  import {
19
20
  CONTEXT_BUDGET_UNIT,
@@ -53,6 +54,10 @@ function schemas(projectionLockWritten = 1) {
53
54
  contract: 3,
54
55
  contractReadable: [1, 2, 3],
55
56
  contextBundle: CONTEXT_BUNDLE_SCHEMA_VERSION,
57
+ taskContextRecord: TASK_RECORD_SCHEMA_VERSION,
58
+ taskHandoffInput: TASK_HANDOFF_INPUT_SCHEMA_VERSION,
59
+ taskHandoffResult: TASK_HANDOFF_RESULT_SCHEMA_VERSION,
60
+ projectBrief: 1,
56
61
  contextQuery: CONTEXT_QUERY_SCHEMA_VERSION,
57
62
  coverageAudit: COVERAGE_AUDIT_SCHEMA_VERSION,
58
63
  dashboardViewModel: DASHBOARD_SCHEMA_VERSION,
@@ -118,6 +123,10 @@ export async function buildCapabilities(root) {
118
123
  package: { name: "frontend-project-context", version: PACKAGE_VERSION },
119
124
  exchangeProtocolVersion: EXCHANGE_PROTOCOL_VERSION,
120
125
  schemas: schemas(projectionLockWritten),
126
+ views: {
127
+ projectBrief: { default: "legacy", legacy: { schemaVersion: 1 }, work: { schemaVersion: 2 } },
128
+ taskHandoff: { default: "legacy", legacy: { schemaVersion: 1 }, work: { schemaVersion: 2 } },
129
+ },
121
130
  commands: [...COMMANDS],
122
131
  actionKinds: [...ACTION_KINDS],
123
132
  contextBudget: { unit: CONTEXT_BUDGET_UNIT, modelTokens: false, callerMustProvideLimit: true },