@givolt/i3-composer-agent 2.3.6 → 3.0.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 (94) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude/commands/i3-sop.md +19 -0
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/.claude-plugin/plugin.json +1 -1
  5. package/.codex-plugin/plugin.json +2 -2
  6. package/.gemini/commands/i3-sop.toml +19 -0
  7. package/README.md +37 -3
  8. package/commands/i3-sop.toml +19 -0
  9. package/docs/codebuddy-setup.md +3 -3
  10. package/docs/codex-setup.md +2 -2
  11. package/docs/other-hosts.md +2 -2
  12. package/docs/workbuddy-setup.md +3 -3
  13. package/evals/cases/i3-enterprise-sop.json +64 -0
  14. package/evals/fixtures/i3-enterprise-sop/brief.md +11 -0
  15. package/evals/zh-CN/cases/i3-enterprise-sop.json +61 -0
  16. package/hooks/PROTOTYPE.md +6 -2
  17. package/package.json +7 -1
  18. package/plugin.json +1 -1
  19. package/references/engineering-skeleton-resources/README.md +52 -0
  20. package/references/engineering-skeleton-resources/adoption.md +200 -0
  21. package/references/engineering-skeleton-resources/catalog.json +17 -0
  22. package/references/engineering-skeleton-resources/directory-standard.md +119 -0
  23. package/references/enterprise-sop-resources/README.md +165 -0
  24. package/references/enterprise-sop-resources/ad/README.md +70 -0
  25. package/references/enterprise-sop-resources/ad/assets-manifest.json +106 -0
  26. package/references/enterprise-sop-resources/ad/prompts/01-generate.md +58 -0
  27. package/references/enterprise-sop-resources/ad/prompts/02-review.md +54 -0
  28. package/references/enterprise-sop-resources/ad/prompts/03-revise.md +54 -0
  29. package/references/enterprise-sop-resources/ad/prompts/04-recheck.md +54 -0
  30. package/references/enterprise-sop-resources/ad/templates/AD.md +337 -0
  31. package/references/enterprise-sop-resources/assets-manifest.json +199 -0
  32. package/references/enterprise-sop-resources/brd/README.md +50 -0
  33. package/references/enterprise-sop-resources/brd/assets-manifest.json +94 -0
  34. package/references/enterprise-sop-resources/brd/prompts/01-generate.md +51 -0
  35. package/references/enterprise-sop-resources/brd/prompts/02-review.md +47 -0
  36. package/references/enterprise-sop-resources/brd/prompts/03-revise.md +47 -0
  37. package/references/enterprise-sop-resources/brd/prompts/04-recheck.md +47 -0
  38. package/references/enterprise-sop-resources/brd/templates/BRD.md +169 -0
  39. package/references/enterprise-sop-resources/codebuddy-project-guide.md +34 -0
  40. package/references/enterprise-sop-resources/controlled-handoff.md +41 -0
  41. package/references/enterprise-sop-resources/controlled_handoff.py +334 -0
  42. package/references/enterprise-sop-resources/handoff-contract.md +196 -0
  43. package/references/enterprise-sop-resources/handoff.py +277 -0
  44. package/references/enterprise-sop-resources/lifecycle-contract.md +91 -0
  45. package/references/enterprise-sop-resources/plan-handoff.md +73 -0
  46. package/references/enterprise-sop-resources/prd/README.md +137 -0
  47. package/references/enterprise-sop-resources/prd/assets-manifest.json +115 -0
  48. package/references/enterprise-sop-resources/prd/prompts/01-generate.md +64 -0
  49. package/references/enterprise-sop-resources/prd/prompts/02-review.md +49 -0
  50. package/references/enterprise-sop-resources/prd/prompts/03-revise.md +48 -0
  51. package/references/enterprise-sop-resources/prd/prompts/04-recheck.md +47 -0
  52. package/references/enterprise-sop-resources/prd/template-contracts.md +39 -0
  53. package/references/enterprise-sop-resources/prd/templates/AD.md +17 -0
  54. package/references/enterprise-sop-resources/prd/templates/PRD.md +257 -0
  55. package/references/enterprise-sop-resources/recovery-contract.md +65 -0
  56. package/references/enterprise-sop-resources/review-handoff.md +105 -0
  57. package/references/enterprise-sop-resources/selection-handoff.md +55 -0
  58. package/references/enterprise-sop-resources/selection_handoff.py +225 -0
  59. package/references/enterprise-sop-resources/stages.json +262 -0
  60. package/references/enterprise-sop-resources/technical-baseline/README.md +132 -0
  61. package/references/enterprise-sop-resources/technical-baseline/assets-manifest.json +101 -0
  62. package/references/enterprise-sop-resources/technical-baseline/baselines/PROVENANCE.md +40 -0
  63. package/references/enterprise-sop-resources/technical-baseline/baselines//344/274/201/344/270/232/345/272/224/347/224/250-/346/212/200/346/234/257/350/247/204/347/272/246_v0.0.2.md +295 -0
  64. package/references/enterprise-sop-resources/technical-baseline/references/engineering-directory-v0.2.0/adoption.md +112 -0
  65. package/references/enterprise-sop-resources/technical-baseline/references/engineering-directory-v0.2.0/directory-standard.md +119 -0
  66. package/references/enterprise-sop-resources/technical-baseline/templates/TECHNICAL-BASELINE.md +133 -0
  67. package/references/enterprise-sop-resources/template-contracts.md +142 -0
  68. package/references/enterprise-sop-resources/testcase/README.md +61 -0
  69. package/references/enterprise-sop-resources/testcase/assets-manifest.json +111 -0
  70. package/references/enterprise-sop-resources/testcase/prompts/01-generate.md +53 -0
  71. package/references/enterprise-sop-resources/testcase/prompts/02-review.md +51 -0
  72. package/references/enterprise-sop-resources/testcase/prompts/03-revise.md +49 -0
  73. package/references/enterprise-sop-resources/testcase/prompts/04-recheck.md +51 -0
  74. package/references/enterprise-sop-resources/testcase/templates/TestCase.md +269 -0
  75. package/references/enterprise-sop-resources/verification/README.md +149 -0
  76. package/references/enterprise-sop-resources/verification/check_execution.py +185 -0
  77. package/references/enterprise-sop-resources/verification/check_native_execution.py +282 -0
  78. package/references/enterprise-sop-resources/verification/check_reads.py +348 -0
  79. package/references/enterprise-sop-resources/verification/review-output.schema.json +155 -0
  80. package/references/enterprise-sop-resources/verification/review_handoff.py +329 -0
  81. package/scripts/ui-prototype-buddy-lifecycle-test.js +10 -5
  82. package/scripts/ui-prototype-codebuddy-hook-test.js +6 -0
  83. package/scripts/ui-prototype-recovery-test.js +11 -2
  84. package/skills/i3-enterprise-sop/SKILL.md +173 -0
  85. package/skills/i3-enterprise-sop/agents/openai.yaml +2 -0
  86. package/skills/i3-ui-prototype/SKILL.md +1 -1
  87. package/skills/i3-ui-prototype/references/execution-evidence.md +2 -2
  88. package/skills/i3-ui-prototype/scripts/codebuddy-context.cjs +18 -1
  89. package/skills/i3-ui-prototype/scripts/codebuddy-hook.cjs +27 -29
  90. package/skills/i3-ui-prototype/scripts/execution-diagnostics.cjs +24 -27
  91. package/skills/i3-ui-prototype/scripts/execution-gates.cjs +2 -3
  92. package/skills/i3-ui-prototype/scripts/execution-recovery.cjs +5 -5
  93. package/skills/i3-ui-prototype/scripts/execution-runtime.cjs +1 -2
  94. package/skills/i3-ui-prototype/scripts/native-command.cjs +1 -1
@@ -0,0 +1,225 @@
1
+ """One-topic path selection, used only after controlled readonly preflight.
2
+
3
+ Business documents and Plan are never written. Source quotes bind paths, not
4
+ business compatibility or approval. Existing handoff storage remains canonical.
5
+ """
6
+ import copy
7
+ import importlib.util
8
+ import json
9
+ from pathlib import Path
10
+ import re
11
+ import sys
12
+ import uuid
13
+
14
+ sys.dont_write_bytecode = True
15
+ RESOURCES = Path(__file__).resolve().parent
16
+
17
+
18
+ def _module(name, file):
19
+ spec = importlib.util.spec_from_file_location(name, file)
20
+ module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module)
21
+ return module
22
+
23
+
24
+ handoff = _module('selection_json', RESOURCES/'handoff.py')
25
+ native = _module('selection_native', RESOURCES/'verification/check_native_execution.py')
26
+ ROLES = {'prd', 'ad', 'testCase', 'prototype'}
27
+ PAIRS = {('ad', 'prd'), ('testCase', 'prd'), ('testCase', 'ad'), ('prototype', 'prd')}
28
+
29
+
30
+ def _file(root, raw):
31
+ if not isinstance(raw, str) or not raw.strip():
32
+ raise ValueError('selection requires an explicit file path')
33
+ path = (root/raw).resolve()
34
+ if not path.is_relative_to(root) or not path.is_file() or not path.read_text(encoding='utf-8').strip():
35
+ raise ValueError('selection source missing, empty or outside project: '+raw)
36
+ return str(path.relative_to(root))
37
+
38
+
39
+ def plan(project_root, request):
40
+ root = Path(project_root).resolve()
41
+ fields = {'schemaVersion', 'operation', 'work', 'manifest', 'capabilityId', 'prdId', 'target', 'links', 'inputs', 'task', 'preview'}
42
+ if not isinstance(request, dict) or set(request)-fields or type(request.get('schemaVersion')) is not int or request['schemaVersion'] != 1:
43
+ raise ValueError('selection request contract differs')
44
+ if request.get('operation') not in ('selection-preview', 'selection-switch'):
45
+ raise ValueError('explicit selection operation required')
46
+ if not all(isinstance(request.get(k), str) and request[k].strip() for k in ('work', 'capabilityId', 'prdId', 'task')):
47
+ raise ValueError('explicit work and selected topic identity required')
48
+ mf = handoff._manifest_path(root, request.get('manifest'))
49
+ before_bytes = mf.read_bytes(); raw = before_bytes.decode('utf-8')
50
+ before = handoff._load(before_bytes)
51
+ if before['scope']['work'] != request['work']:
52
+ raise ValueError('selection manifest belongs to another work')
53
+ matches = [t for t in before['selected'].get('topics', []) if all(t[k] == request[k] for k in ('capabilityId', 'prdId'))]
54
+ if len(matches) != 1:
55
+ raise ValueError('explicit topic is not uniquely selected; no latest-version fallback')
56
+ old_topic = matches[0]; topic = copy.deepcopy(old_topic)
57
+ target = request.get('target')
58
+ if not isinstance(target, dict) or set(target)-ROLES or not isinstance(target.get('prd'), str):
59
+ raise ValueError('target must explicitly name PRD and only local companion roles')
60
+ for role, path in target.items():
61
+ if path is None and role != 'prd': topic.pop(role, None)
62
+ else: topic[role] = _file(root, path)
63
+ expected = handoff._selected_only(before)
64
+ expected['selected']['topics'][before['selected']['topics'].index(old_topic)] = topic
65
+ # The selected scope supplies shared dependencies; no unrelated topic is loaded.
66
+ selected = handoff._resolve(root, before, request['capabilityId'], request['prdId'], ())['references']
67
+ paths = [_file(root, item['path']) for item in selected]
68
+ paths += [_file(root, topic[role]) for role in sorted(ROLES) if role in topic]
69
+ inputs = request.get('inputs', [])
70
+ if not isinstance(inputs, list): raise ValueError('inputs must be explicit paths')
71
+ paths += [_file(root, p) for p in inputs]
72
+ delivery = before.get('delivery', {})
73
+ if not isinstance(delivery, dict): raise ValueError('delivery must remain an object')
74
+ plan_paths = [_file(root, delivery[k]) for k in ('plan', 'taskTarget') if k in delivery]
75
+ plan_paths += [_file(root, p) for p in ('tasks/plan.md', 'tasks/todo.md') if (root/p).exists()]
76
+ paths = list(dict.fromkeys(paths+plan_paths))
77
+ links = request.get('links', [])
78
+ if not isinstance(links, list): raise ValueError('links must be a caller supplied source-evidence array')
79
+ by_pair = {}
80
+ for link in links:
81
+ if not isinstance(link, dict) or set(link) != {'role', 'upstreamRole', 'line', 'quote'}:
82
+ raise ValueError('source evidence needs role/upstreamRole/line/quote')
83
+ pair = (link['role'], link['upstreamRole'])
84
+ if pair not in PAIRS or pair in by_pair: raise ValueError('ambiguous or unsupported companion source evidence')
85
+ by_pair[pair] = link
86
+ gaps = []; checks = []
87
+ for role, upstream_role in sorted(PAIRS):
88
+ if role not in topic: continue
89
+ link = by_pair.get((role, upstream_role)); upstream = topic.get(upstream_role)
90
+ lines = (root/topic[role]).read_text().splitlines(); passed = False
91
+ if link and upstream and type(link['line']) is int and 1 <= link['line'] <= len(lines):
92
+ quote = lines[link['line']-1]
93
+ tokens = re.findall(r'`([^`]+)`|\]\(([^)]+)\)', quote)
94
+ passed = quote == link['quote'] and any(upstream == token for pair in tokens for token in pair if token)
95
+ check = {'role': role, 'path': topic[role], 'upstreamRole': upstream_role, 'upstreamPath': upstream,
96
+ 'passed': passed, 'evidence': link, 'semanticCompatibility': 'requires-human-review'}
97
+ checks.append(check)
98
+ if not passed: gaps.append({'code': 'companion_source_unconfirmed', **check})
99
+ diff = [{'role': role, 'before': old_topic.get(role), 'after': topic.get(role)}
100
+ for role in sorted(ROLES) if old_topic.get(role) != topic.get(role)]
101
+ tasks = []; mentions = []
102
+ changed_paths = {x[k] for x in diff for k in ('before', 'after') if x[k]}
103
+ for path in list(dict.fromkeys(plan_paths+[p for p in paths if p.startswith('tasks/')])):
104
+ for n, line in enumerate((root/path).read_text().splitlines(), 1):
105
+ checkbox = re.match(r'^\s*[-*]\s+\[([ xX])\]\s+(.+)', line)
106
+ if checkbox:
107
+ tasks.append({'path': path, 'line': n, 'state': 'completed' if checkbox[1].lower() == 'x' else 'unfinished', 'text': checkbox[2]})
108
+ found = sorted(p for p in changed_paths if p in line)
109
+ if found: mentions.append({'path': path, 'line': n, 'text': line, 'references': found})
110
+ base_request = {'schemaVersion': 1, 'operation': 'manual', 'work': request['work'],
111
+ 'manifest': str(mf.relative_to(root)), 'reference': {'role': 'prd', 'path': topic['prd'],
112
+ 'capabilityId': request['capabilityId'], 'prdId': request['prdId']},
113
+ 'inputs': paths, 'task': request['task']+' 仅只读改选预检;不得自行登记、改稿或调整Plan。'}
114
+ return {'projectRoot': str(root), 'manifest': str(mf.relative_to(root)), 'request': request,
115
+ 'beforeText': raw, 'expected': expected, 'beforeTopic': old_topic, 'afterTopic': topic,
116
+ 'diff': diff, 'sourceChecks': checks, 'gaps': gaps, 'preflightRequest': base_request,
117
+ 'sharedReferences': [x for x in selected if x['role'] not in ROLES],
118
+ 'planImpact': {'paths': list(dict.fromkeys(plan_paths)), 'tasks': tasks, 'mentions': mentions,
119
+ 'automaticallyUpdated': False, 'completionEvidence': 'checkbox text only; not execution proof',
120
+ 'nextAction': '将选定AD及准确来源显式交原Plan核影响;修改计划与开工认可另行处理。'},
121
+ 'engineeringReady': False, 'businessApproved': False}
122
+
123
+
124
+ def freeze(selection, files):
125
+ """Outside-project preview evidence, not an approval or business JSON field."""
126
+ return {'schemaVersion': 1, 'kind': 'i3-sop-selection-preview', 'id': str(uuid.uuid4()),
127
+ 'plan': copy.deepcopy(selection), 'files': copy.deepcopy(files)}
128
+
129
+
130
+ def _intent(selection):
131
+ request = selection['request']
132
+ return {'projectRoot': selection['projectRoot'], 'manifest': selection['manifest'],
133
+ **{k: request[k] for k in ('work', 'capabilityId', 'prdId', 'links', 'inputs') if k in request},
134
+ 'target': {k: selection['afterTopic'].get(k) for k in request['target']}}
135
+
136
+
137
+ def apply(project_root, selection, receipt, *, authorized=False, on_store=None):
138
+ if authorized is not True: raise ValueError('exact selection authorization required')
139
+ root = Path(project_root).resolve()
140
+ if (receipt.get('schemaVersion') != 1 or receipt.get('kind') != 'i3-sop-selection-preview'
141
+ or not isinstance(receipt.get('id'), str) or not isinstance(receipt.get('files'), dict)):
142
+ raise ValueError('valid saved selection preview required')
143
+ saved = receipt['plan']
144
+ if (_intent(saved) != _intent(selection) or saved['expected'] != selection['expected']
145
+ or saved['projectRoot'] != str(root)):
146
+ raise ValueError('preview does not name this exact selection')
147
+ if saved['gaps'] or selection['gaps']: raise ValueError('companion source evidence unresolved')
148
+ mf = handoff._manifest_path(root, selection['manifest'])
149
+ current = mf.read_bytes(); before_files = native.inventory(root)
150
+ delta = [p for p in set(before_files)|set(receipt['files']) if before_files.get(p) != receipt['files'].get(p)]
151
+ if delta:
152
+ # A repeated, already-applied exact switch is a no-op. No new business
153
+ # content or other topic change may ride along with the old preview.
154
+ history = [p for p in delta if p != selection['manifest']]
155
+ history_parent = mf.parent/'history'
156
+ repeated = (handoff._load(current) == saved['expected'] and len(history) == 1
157
+ and selection['manifest'] in delta and history[0] not in receipt['files'])
158
+ if repeated:
159
+ hp = handoff._manifest_path(root, history[0])
160
+ repeated = (hp.parent == history_parent and hp.name.startswith(mf.stem+'-')
161
+ and hp.suffix == '.json' and hp.read_bytes() == saved['beforeText'].encode('utf-8'))
162
+ if repeated: return {'ok': True, 'changed': False, 'readbackPassed': True, 'changedFiles': []}
163
+ raise ValueError('project changed since preview; re-read and create a new preview')
164
+ if current != saved['beforeText'].encode('utf-8'):
165
+ raise ValueError('manifest changed since preview')
166
+ if on_store: on_store()
167
+ result = handoff._store(root, mf, current, saved['expected'])
168
+ after_files = native.inventory(root)
169
+ changed = sorted(p for p in set(before_files)|set(after_files) if before_files.get(p) != after_files.get(p))
170
+ allowed = [selection['manifest'], result['history']] if result['changed'] else []
171
+ if (set(changed) != set(allowed) or handoff._load(mf.read_bytes()) != saved['expected']
172
+ or (result['changed'] and (root/result['history']).read_bytes() != current)):
173
+ raise ValueError('selection postcheck failed; retain actual files for human review, no automatic rollback')
174
+ return {**result, 'readbackPassed': True, 'changedFiles': changed}
175
+
176
+
177
+ def finish(prepared, evidence, *, authorized, response):
178
+ """Called after real native receipts and current file boundaries pass."""
179
+ root = Path(prepared['root']); proposal = prepared['selection']; request = prepared['request']
180
+ summary = {k: proposal[k] for k in ('diff', 'sourceChecks', 'gaps', 'sharedReferences', 'planImpact', 'engineeringReady')}
181
+ out = response('needs_confirmation', 'selection_confirmation_required',
182
+ '改选预检完成;请核配套及Plan影响,再明确选择该组路径。',
183
+ recommendation='核对预览;配套未确认先补证据或明确解除引用,保留文档原件。')
184
+ out['selection'] = summary
185
+ out['options'] = [{'id': 'keep-selection', 'label': '保留当前选择'},
186
+ {'id': 'prepare-companions', 'label': '补齐配套或明确解除引用后重新预览'},
187
+ {'id': 'manual-handoff', 'label': '本次手动交接路径'},
188
+ {'id': 'stop', 'label': '暂停并保留现场'}]
189
+ if request['operation'] == 'selection-preview':
190
+ preview = freeze(proposal, prepared['scope']['files'])
191
+ (evidence/'selection-preview.json').write_text(json.dumps(preview, ensure_ascii=False, indent=2)+'\n')
192
+ out['preview'] = {'id': preview['id'], 'path': str(evidence/'selection-preview.json')}
193
+ else:
194
+ preview = prepared['selectionReceipt']
195
+ if native.loads(Path(request['preview']).read_text()) != preview:
196
+ return response('blocked', 'selection_preview_changed', '预览证据已改变;保留现场并重新预览。')
197
+ out['preview'] = {'id': preview.get('id'), 'path': request['preview']}
198
+ if proposal['gaps']:
199
+ out['reason']['code'] = 'selection_companions_unconfirmed'
200
+ out['reason']['message'] = '现有配套或调用方原文证据不能绑定目标上游;本次不改选。'
201
+ out['recommendation']['id'] = 'prepare-companions'
202
+ return out
203
+ out['options'].insert(1, {'id': 'authorize-selection', 'label': '明确委托切换到此预览的准确组合'})
204
+ out['recommendation']['id'] = 'authorize-selection'
205
+ if request['operation'] != 'selection-switch' or not authorized:
206
+ return out
207
+ registration = {'attempted': False, 'attempts': 0, 'kind': 'direct-python-api',
208
+ 'entry': 'selection_handoff.apply -> handoff._store', 'shell': False, 'previewId': preview.get('id')}
209
+ def on_store():
210
+ registration.update(attempted=True, attempts=1)
211
+ (evidence/'selection-registration.json').write_text(json.dumps(registration, indent=2)+'\n')
212
+ try:
213
+ result = apply(root, proposal, preview, authorized=True, on_store=on_store)
214
+ registration['result'] = result
215
+ (evidence/'selection-readback.json').write_text(json.dumps(result, ensure_ascii=False, indent=2)+'\n')
216
+ out = response('selected' if result['changed'] else 'unchanged', 'selection_applied',
217
+ '准确组合及差量已回读;业务稿、其他主题和原Plan保持,后续规划认可另行处理。')
218
+ except (OSError, ValueError, KeyError, TypeError) as exc:
219
+ registration['error'] = str(exc)
220
+ out = response('blocked', 'selection_not_applied', str(exc),
221
+ recommendation='保留当前内容;核对变化或锁后用新预览处理,不自动重试或回滚。')
222
+ out['registration'] = registration
223
+ out['selection'] = summary
224
+ (evidence/'selection-registration.json').write_text(json.dumps(registration, ensure_ascii=False, indent=2)+'\n')
225
+ return out
@@ -0,0 +1,262 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "resourceId": "i3-enterprise-sop",
4
+ "resourceVersion": "0.16.2",
5
+ "status": "local-short-command-plan-candidate",
6
+ "activation": "explicit-enterprise-task-or-applicable-recorded-selection",
7
+ "ordinaryInstallEnablesEnterpriseWorkflow": false,
8
+ "sharedContract": "template-contracts.md",
9
+ "integrityManifest": "assets-manifest.json",
10
+ "stagePathBase": "this-index-directory",
11
+ "stageFilePathBase": "selected-stage-manifest-directory",
12
+ "stages": {
13
+ "brd": {
14
+ "documentType": "BRD",
15
+ "resourceRoot": "brd",
16
+ "manifest": "brd/assets-manifest.json",
17
+ "resourceVersion": "0.2.3",
18
+ "templateVersion": "v0.0.3",
19
+ "templateRole": "complete-document-template",
20
+ "actions": [
21
+ "generate",
22
+ "review",
23
+ "revise",
24
+ "recheck"
25
+ ]
26
+ },
27
+ "prd": {
28
+ "documentType": "PRD",
29
+ "resourceRoot": "prd",
30
+ "manifest": "prd/assets-manifest.json",
31
+ "resourceVersion": "0.3.3",
32
+ "templateVersion": "v0.0.4",
33
+ "templateRole": "complete-document-template",
34
+ "actions": [
35
+ "generate",
36
+ "review",
37
+ "revise",
38
+ "recheck"
39
+ ]
40
+ },
41
+ "ad": {
42
+ "documentType": "AD",
43
+ "resourceRoot": "ad",
44
+ "manifest": "ad/assets-manifest.json",
45
+ "resourceVersion": "0.3.3",
46
+ "templateVersion": "v0.0.4",
47
+ "templateRole": "complete-document-template",
48
+ "actions": [
49
+ "generate",
50
+ "review",
51
+ "revise",
52
+ "recheck"
53
+ ]
54
+ },
55
+ "testcase": {
56
+ "documentType": "TestCase",
57
+ "resourceRoot": "testcase",
58
+ "manifest": "testcase/assets-manifest.json",
59
+ "resourceVersion": "0.3.4",
60
+ "templateVersion": "v0.0.4",
61
+ "templateRole": "complete-document-template",
62
+ "actions": [
63
+ "generate",
64
+ "review",
65
+ "revise",
66
+ "recheck"
67
+ ]
68
+ }
69
+ },
70
+ "existingPrdSubtreePreserved": false,
71
+ "sopCommandImplemented": true,
72
+ "autoSupported": false,
73
+ "engineeringAssetsIncluded": false,
74
+ "projectModifiedCopiesPreserved": true,
75
+ "handoffContract": "handoff-contract.md",
76
+ "projectGuide": "codebuddy-project-guide.md",
77
+ "auxiliaryResources": {
78
+ "technical-baseline": {
79
+ "resourceRoot": "technical-baseline",
80
+ "manifest": "technical-baseline/assets-manifest.json",
81
+ "resourceVersion": "0.2.0",
82
+ "templateVersion": "v0.0.1",
83
+ "businessStage": false,
84
+ "role": "shared-engineering-guidance",
85
+ "baselineCatalog": "technical-baseline/assets-manifest.json",
86
+ "explicitAdoptionRequired": true
87
+ }
88
+ },
89
+ "manualHandoffSupported": true,
90
+ "jsonRegistrationImplemented": true,
91
+ "lifecycleContract": "lifecycle-contract.md",
92
+ "existingPrdTemplatePreserved": true,
93
+ "candidateRevision": "20261021-plan-gates-r4",
94
+ "readEvidenceChecker": {
95
+ "entry": "verification/README.md",
96
+ "script": "verification/check_reads.py",
97
+ "traceFormat": "codebuddy-stream-json",
98
+ "automaticActivation": false,
99
+ "writesProjectFiles": false,
100
+ "version": "0.3.1",
101
+ "reviewOutputContract": "verification/review-output.schema.json",
102
+ "roleBindings": "caller-verification-scope-only",
103
+ "schemaBuilder": {
104
+ "module": "verification/check_reads.py",
105
+ "function": "build_review_schema"
106
+ },
107
+ "reportContentChecker": "check_report"
108
+ },
109
+ "sopSkillImplemented": true,
110
+ "sopSkillScope": "explicit-single-stage-native-spec-or-planning-and-reference-handoff",
111
+ "handoffHelper": {
112
+ "script": "handoff.py",
113
+ "version": "0.2.0",
114
+ "operations": [
115
+ "init",
116
+ "select",
117
+ "resolve"
118
+ ],
119
+ "selection": "initial-or-same-only; exact same-topic replacement via controlled preview",
120
+ "manualSupported": true,
121
+ "python": "3.9+",
122
+ "semanticOrApprovalValidation": false,
123
+ "originalPlanBuildConsumptionVerified": false,
124
+ "manifestFields": [
125
+ "schemaVersion",
126
+ "scope",
127
+ "selected"
128
+ ]
129
+ },
130
+ "executionEvidenceChecker": {
131
+ "script": "verification/check_execution.py",
132
+ "version": "0.1.0",
133
+ "automaticActivation": false,
134
+ "writesProjectFiles": false,
135
+ "reportContract": "handoff-contract.md#9-真实调用与执行报告",
136
+ "profile": "CodeBuddy stream-json/direct-python3-helper",
137
+ "verdictDoesNotApproveBusiness": true
138
+ },
139
+ "generation": {
140
+ "requiredSkill": "i3-spec-driven-development",
141
+ "wrapperCommandUnchanged": true,
142
+ "nativeStopPreserved": true
143
+ },
144
+ "businessDocuments": {
145
+ "defaultRoot": "spec",
146
+ "layout": "one-capability-one-directory",
147
+ "existingAdoptedPathsPreserved": true,
148
+ "resourceRootUnchanged": true,
149
+ "engineeringEntry": "selected AD plus explicitly referenced selected sources",
150
+ "context": "selected topic and required shared dependencies"
151
+ },
152
+ "nativeHandoff": {
153
+ "plan": "SPEC.md or equivalent; original outputs and approval unchanged",
154
+ "build": "approved next task",
155
+ "buildAuto": "original spec, git, plan approval and per-task loop unchanged",
156
+ "manifestAutomaticallyConsumedByOriginalCommands": false,
157
+ "manualSupported": true,
158
+ "verification": "see current independent evidence; not inferred from index"
159
+ },
160
+ "nativeExecutionEvidenceChecker": {
161
+ "script": "verification/check_native_execution.py",
162
+ "version": "0.1.1",
163
+ "profiles": [
164
+ "generation",
165
+ "status",
166
+ "plan",
167
+ "auto-preflight",
168
+ "standard"
169
+ ],
170
+ "automaticActivation": false,
171
+ "writesProjectFiles": false,
172
+ "helperCheckerUnchanged": true,
173
+ "createsApproval": false,
174
+ "reportContract": "verification/README.md#原生方法与执行报告"
175
+ },
176
+ "recoveryContract": "recovery-contract.md",
177
+ "minimalRecovery": {
178
+ "implemented": "owned skill procedure reusing handoff.py",
179
+ "documentWrites": false,
180
+ "newHelperOperations": false,
181
+ "draftCompletionValidation": "caller actual task and final full read; not helper nonempty-path check",
182
+ "supports": [
183
+ "readonly-partial-draft-assessment",
184
+ "explicit-selected-reference-backfill",
185
+ "idempotent-registration",
186
+ "human-edit-protection"
187
+ ],
188
+ "selectionReplacementImplemented": true,
189
+ "crossEditorTransactionGuaranteed": false,
190
+ "selectionReplacementScope": "one-existing-topic PRD and explicit local companions; shared sources unchanged",
191
+ "topicCancellationImplemented": false
192
+ },
193
+ "controlledHandoff": {
194
+ "script": "controlled_handoff.py",
195
+ "contract": "controlled-handoff.md",
196
+ "version": "0.4.0",
197
+ "host": "codebuddy-cli-project",
198
+ "activation": "explicit-single-task",
199
+ "nativeReadOnlyPreflight": true,
200
+ "automaticHook": false,
201
+ "businessApproval": false,
202
+ "enterpriseAuto": false,
203
+ "selection": {
204
+ "module": "selection_handoff.py",
205
+ "contract": "selection-handoff.md",
206
+ "operations": [
207
+ "selection-preview",
208
+ "selection-switch"
209
+ ],
210
+ "exactPreviewRequired": true,
211
+ "topicScope": "one-existing-topic",
212
+ "changesSharedSources": false,
213
+ "writesBusinessDocumentsOrPlan": false,
214
+ "semanticCompatibility": "caller-source-quotes-and-human-review"
215
+ },
216
+ "auditBeforeSelectedWrite": true
217
+ },
218
+ "independentReview": {
219
+ "contract": "review-handoff.md",
220
+ "script": "verification/review_handoff.py",
221
+ "version": "0.2.0",
222
+ "host": "codebuddy-cli",
223
+ "activation": "explicit-single-review-or-recheck",
224
+ "freshSession": true,
225
+ "projectWrites": false,
226
+ "businessApproval": false,
227
+ "missingHost": "new-session-task",
228
+ "selectedOnlyRegistrationValidation": "pending-S10",
229
+ "contextProfile": "fixed-review-context-v1",
230
+ "modelReads": "full stage README, template, unique action, review contract and necessary actual project/business sources; full selected fallback for unknown/custom combinations",
231
+ "outerChecks": "metadata resolution and source snapshots retained; never model-read evidence"
232
+ },
233
+ "planHandoff": {
234
+ "contract": "plan-handoff.md",
235
+ "requiredSkill": "i3-planning-and-task-breakdown",
236
+ "originalCommandObligationsPreserved": true,
237
+ "defaultOutputs": [
238
+ "tasks/plan.md",
239
+ "tasks/todo.md"
240
+ ],
241
+ "writesBusinessJson": false,
242
+ "manualSupported": true,
243
+ "buildAutomaticallyInvoked": false,
244
+ "requiredResourceReads": [
245
+ "README.md",
246
+ "stages.json",
247
+ "template-contracts.md",
248
+ "handoff-contract.md",
249
+ "plan-handoff.md"
250
+ ],
251
+ "identityOrUpstreamConflict": "stop-before-native-planning-and-plan-todo-writes"
252
+ },
253
+ "operations": [
254
+ "brd",
255
+ "prd",
256
+ "ad",
257
+ "testcase",
258
+ "plan",
259
+ "review",
260
+ "status"
261
+ ]
262
+ }
@@ -0,0 +1,132 @@
1
+ # 公共技术规约:采用说明
2
+
3
+ <!-- i3:zh-guide:start -->
4
+ ## 中文使用说明
5
+
6
+ 按下文完整工程步骤、检查项与验证条件执行。根据任务选择适用步骤,保留证据、风险和退出条件;正文示例中的英文标签在面向用户输出时译为中文。
7
+
8
+ 默认使用简体中文解释、追问及生成报告;用户明确要求其他语言时可切换。原方法正文、引用、阈值和审批条件完整保留。代码标识、路径、命令、工具参数、JSON 键/枚举与原文引用保持原样。
9
+ <!-- i3:zh-guide:end -->
10
+
11
+ 资源版本:0.2.0;通用模板内容版本:v0.0.1;可选企业应用技术规约:v0.0.2。状态:自有分发资源本地候选,尚未发布。实际打包、安装和宿主使用以对应轮次证据为准。
12
+
13
+ 本资源帮助项目固定共用工程约束及其来源。已有规范优先,新项目缺少规范时才起草最小候选。它不是第五个业务阶段、总AD、项目配置或批准记录;不新增Skill、命令、路由和执行器。
14
+
15
+ ## 0. 模板与可选技术规约
16
+
17
+ | 资料 | 用途与采用边界 |
18
+ | --- | --- |
19
+ | [公共技术规约模板](templates/TECHNICAL-BASELINE.md) v0.0.1 | 根据项目真实资料起草规约,或核对已有规范的覆盖;不默认技术栈 |
20
+ | [企业应用公共技术规约](baselines/企业应用-技术规约_v0.0.2.md) v0.0.2 | 包含已确认的Java/Spring Boot、Vue/TypeScript/Antdv Next、MaxKey/OIDC等技术方向及按需工程约定;项目明确选择后才生效 |
21
+ | [来源与固定依赖说明](baselines/PROVENANCE.md) | 区分来源追溯与运行时资料;附带该规约引用的目录规范/采用说明0.2.0,不自动采用其他会话的新版本 |
22
+
23
+ 随包提供不等于所有项目默认采用。项目已有适用规范时先复用;选择本规约时记录准确路径、文内版本、适用范围及必要差异。多个版本或来源并存且未明确选择时先确认,不按目录最大版本猜选。
24
+
25
+ 项目需要调整时,沿用项目现有规范位置或明确维护项目副本;发行原件与项目规范分别定位。项目自改副本优先,不用发行摘要恢复它,不在升级时覆盖项目规范;不可读或存在冲突时如实报告,不静默切换。
26
+
27
+ 最短任务示例:
28
+
29
+ ```text
30
+ /i3-sop ad
31
+ 为当前选定的PRD生成AD,采用随包提供的《企业应用公共技术规约 v0.0.2》。先核项目已有规范和适用范围,按索引定位并完整读取规约及必要目录资料;保留项目自改内容和未决项,生成后交我审阅,暂不进入Plan或Build。
32
+ ```
33
+
34
+ 资料由现有入口按阶段索引的auxiliaryResources定位,读取本清单的baselines条目,不要求使用者填写安装内部路径。原版Skill/命令和标准流程保持;本例不构成已完成的宿主生成测试。
35
+
36
+ ## 1. 先核对来源,再选择采用方式
37
+
38
+ 只在用户明确采用企业SOP或明确要求本项技术资料任务时使用。安装、出现PRD字样或发现本文件,不代表项目已启用企业SOP;标准任务继续使用原方法。
39
+
40
+ 先实际读取项目说明、明确提供的规范和已有采用记录;目录列表和自动上下文只能作线索。不扫描全部项目、宿主、历史样例或备份来猜规范。
41
+
42
+ 资源位置与项目规范来源分开判断:
43
+
44
+ - 对本资源,实际读取本次选定目录的README、清单和所选模板;明确采用的项目自改副本优先,已选根不可读或损坏时报告缺项,不换发行原件或全局新版。
45
+ - 对项目规范,优先复用项目已明确采用且适用的集团/平台/工程规范、CONSTRAINTS、ADR及正式契约。已有代码和锁文件提供实现事实,不自动成为替换规范的决定。
46
+ - 用户本次明确材料与既有采用发生冲突时,同时保留并核对适用范围;本次提供文件不自动授权覆盖原规范、取消约束或切换全项目采用。
47
+ - “规范未提供/未读取”与“项目确认没有规范”分开。不可读、无适用版本或存在冲突时,记录准确缺口及影响;不能从缺文件推断不存在。
48
+
49
+ ## 2. 路径一:已有适用规范
50
+
51
+ 1. 读已有规范及采用记录,固定可回读内容与本项目适用条款。可使用准确版本加固定提交、不可变快照或实际计算的摘要;未计算就明确说明。只有版本标签和可变链接不足以区分内容时,补固定依据。
52
+ 2. 用模板核对覆盖,沿用已有位置、身份和格式。内容已完整时,只在现有采用说明或本次唯一明确目标中记录引用及真实缺口;不复制全文、迁移文件或要求填一份同构大文档。
53
+ 3. 公共规则直接引用唯一权威。仅当实际存在项目特定约束时补充有来源的差异,注明维护位置和适用范围;有冲突先列Q,不悄悄覆盖。
54
+ 4. 记录本次AD如何引用这些规则的方式即可,不自动生成或修改AD。每份AD仍需自己的三图和完整工程设计。
55
+
56
+ 最小采用记录可以使用项目现有表格表达,无需新的registry:
57
+
58
+ | 记录项 | 需要的实际内容 |
59
+ | --- | --- |
60
+ | 来源与固定内容 | 规范身份、权威位置、版本/固定提交或真实摘要、实际读取范围 |
61
+ | 本次适用 | 项目/工程/主题范围、准确条款、实际采用依据;阅读不等于采用或批准 |
62
+ | 落实与差异 | 项目补充或AD引用位置、例外及真实决定;无差异就直接引用 |
63
+ | 项目本地修改 | 当前副本与发行来源分别记录;同名同版本改变后旧证据不自动沿用 |
64
+ | 缺口与交接 | 未读、未知、冲突、需何答复、只影响哪些动作和独立可继续部分 |
65
+
66
+ 已有文件或人工修改先读并保留,不用发行摘要恢复项目副本。已有采用说明已足够时,可以只提出只读核对结果;是否写入及唯一目标由本次实际授权决定。
67
+
68
+ ## 3. 路径二:缺少规范时起草最小候选
69
+
70
+ 先确认已取得的项目事实与已查范围;未知保持Q。按模板涵盖共用架构、技术工程、身份安全、契约通则、共享数据、工程质量、交付恢复、维护例外八个领域。可以直接固定引用,不强制拆出八份文档或重复已有材料。
71
+
72
+ 沿用项目既有位置;没有约定时,可建议 `docs/engineering/{项目名称}-技术规约_v0.0.1.md` 作为共用辅助文档。建议路径不是已经存在、已采用或可覆盖的事实。核心业务文档的一能力一目录和主题命名保持。
73
+
74
+ 没有事实时,不默认框架、数据库、消息中间件、部署平台、权限、责任人、保留期限、质量数字或命令。项目已明确采用的公共平台约束应引用保留,准确版本和工程细节未取得时列Q,不重新选另一套默认。项目尚未建成时,命令、目录、风格示例和环境可以待定,不编造已运行证据。
75
+
76
+ 最小候选不要求全项目技术问题先清零。AD可先起草独立部分,原型按需并行;共同定义未决时,只限制依赖范围。交原Plan前补齐当前有效规格六项、依赖范围的共用定义和必要真实认可;Plan形成、获准逐任务Build及真实工程验收分别核对,不要求起草规范前已有构建通过。
77
+
78
+ ## 4. 规约、契约、AD与版本
79
+
80
+ | 内容 | 唯一维护责任与交接 |
81
+ | --- | --- |
82
+ | 公共技术规约 | 维护共用原则或准确权威引用;不替代产品规则、CONSTRAINTS或ADR |
83
+ | 正式接口/事件/数据定义 | 每项一个权威位置,字段与行为分担时明确范围;可先用提供方AD固定章节,不强制新协议或拆文件 |
84
+ | 主题AD | 对应选定PRD完整设计,固定规范版本、条款、提供/消费契约及落实/例外;不包办另一主题PRD |
85
+ | TestCase/实际报告 | 预期直接核PRD,技术判据核AD及契约;候选、真实执行和人工认可分开 |
86
+ | 工程登记与锁 | 记录实际选择、正式采用、应用及验证事实;不另建架构权威或任务tracker |
87
+
88
+ 同一PBC多份主题PRD各自独立版本,每份配套逻辑AD及TestCase;文档不要求同号。规范版本、契约版本、代码/制品和环境分别固定。兼容核实际消费者、字段及语义、迁移和运行组合,不能靠版本号或Schema通过下结论。
89
+
90
+ 共享数据、状态及文件明确唯一逻辑维护责任与受控写入;前端、后端、Agent及jobs各自状态不能代替正式业务结果。具体角色、事务和数据保留必须有产品/规范依据。
91
+
92
+ 变更先固定旧/新内容及来源,定位直接和必要传递的契约、AD、AC、TestCase及真实任务,区分不受影响范围。人可人工修改、明确委托修订、有据不采纳或保持Q;不自动重写全项目、自动升版或承接旧批准。外部契约正式采用与模板实际应用并验证的锁分别留证,本作业不自动创建锁。
93
+
94
+ ## 5. 写入、审查与退出
95
+
96
+ 写前列明项目根、已读资料、已有规范/采用记录、固定来源、假设/Q、唯一目标和本次权限。先读现稿,保留人工内容和原报告;仅写明确获准目标,未知权限或覆盖风险时先说明。
97
+
98
+ 最后编辑后实际回读:新增要求逐条回查来源,规范与权限描述一致,逐表检查表头列数和列义。摘要、版本与内容相符,不要求文档写自身摘要。
99
+
100
+ 审查只标注问题、来源、位置、影响与建议,保留人工修改空间。只有真实独立新上下文才称独立审查,无隔离能力时提供新会话任务;自查不冒称独立。修订另行明确,不为清零代答业务或技术决定。
101
+
102
+ 完成后报告来源/目标、复用方式、补充与Q、实际验证和未执行事项,交人工审阅并停轮,不自动进入AD、Plan、Build、测试执行、提交或发布。
103
+
104
+ ## 6. 可复制任务说明
105
+
106
+ 可明确提供本资源目录或项目已采用副本,也可在明确企业任务后按[上层入口](../README.md)及其索引定位本辅助资源。源码登记不等于宿主自动发现,以下均为明确任务,没有新增slash命令。
107
+
108
+ 已有规范:
109
+
110
+ ```text
111
+ 本次只做公共技术规约采用核对。使用我明确提供的公共技术规约资源,先实际读取该目录README、清单和模板,再读取当前项目说明、已有规范及采用记录。
112
+ 优先复用项目已采用规范,固定来源、内容与适用条款;已有资料完整时只记录引用和真实缺口,不复制一份新规范,不覆盖原规范或人工修改。
113
+ 写前说明事实、假设、未读取项和唯一获准目标。位置按项目已有约定选择;若存在歧义或覆盖风险,先说明,不新建另一套registry。
114
+ 不把阅读当采用、把采用当批准;冲突按影响保留Q,不自行改选型或权限。最后回读候选,新增要求逐条回源,权限描述一致,表格逐行核列数与列义。完成后交我审阅并停轮。
115
+ ```
116
+
117
+ 新项目或资料不足:
118
+
119
+ ```text
120
+ 本次只起草项目公共技术规约候选。先读取我明确提供的资源README、清单、模板及当前项目资料,确认已有规范、已查范围和未取得内容;如果找到适用规范,优先采用它。
121
+ 确实缺少规范时,按模板只写当前有依据的最小候选,可用固定引用代替重复正文。框架、版本、责任、权限、质量数字、命令和运行结果没有来源就列Q,不填默认答案。
122
+ 沿用项目已有位置和命名,只写本次明确的唯一目标,保护人工内容。草拟不冒充可计划或获准Build;每份主题AD仍须三图及完整设计,原型按需。
123
+ 最后实际回读,逐条核新增要求来源、权限一致性及表格列数/列义,列出缺口和未执行事项,交我审阅并停轮。原版技能和命令不动,不写AD、Plan、工程或测试结果,不提交发布。
124
+ ```
125
+
126
+ ## 7. 资源范围与后续接入
127
+
128
+ 本子目录包含采用说明、通用模板、可选企业技术基线、其必要的定版目录依赖及局部清单。辅助manifest的entry、template、baselines[].path和files[].path均相对该manifest;基线requiredSources的path也相对同一manifest。来源追溯页不是额外业务阶段或统一必读业务输入。
129
+
130
+ 上层stages.json登记辅助资源根与清单,局部baselines条目列出可选规约的身份、版本和必要来源;不设置默认采用,不增加配置系统、审批字段或自动调度。清单的文件摘要固定发行资料,本轮变化检查不用于恢复或覆盖项目副本。
131
+
132
+ B01—B05和原S10记录保留各自版本与验证范围。本次只整理分发资源及引用,打包/安装可读性另取新证据;静态、安装、真实模型行为、项目采用与正式发布分别判断。原型仍按需,TestCase不作为Plan统一必需输入,原Spec及Plan/Build停点不变。