@heretek-ai/epistemic-swarm 0.7.13 → 0.7.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +5 -1
- package/package.json +2 -1
- package/plugins/factory/skills/factory/scripts/factory.py +68 -14
- package/plugins/socratic-grilling/skills/grilling/SKILL.md +14 -1
- package/plugins/socratic-grilling/skills/grilling/socratic_tree.py +88 -16
- package/runner/__pycache__/__init__.cpython-311.pyc +0 -0
- package/runner/__pycache__/auctioneer.cpython-311.pyc +0 -0
- package/runner/__pycache__/auditor_engine.cpython-311.pyc +0 -0
- package/runner/__pycache__/claim_store.cpython-311.pyc +0 -0
- package/runner/__pycache__/claim_witness.cpython-311.pyc +0 -0
- package/runner/__pycache__/darkharvest_claims.cpython-311.pyc +0 -0
- package/runner/__pycache__/errors.cpython-311.pyc +0 -0
- package/runner/__pycache__/living_dossiers.cpython-311.pyc +0 -0
- package/runner/__pycache__/mcp_protocol.cpython-311.pyc +0 -0
- package/runner/__pycache__/mcp_server.cpython-311.pyc +0 -0
- package/runner/__pycache__/path_safety.cpython-311.pyc +0 -0
- package/runner/__pycache__/pcrb.cpython-311.pyc +0 -0
- package/runner/__pycache__/pcrb_verify.cpython-311.pyc +0 -0
- package/runner/__pycache__/preflight.cpython-311.pyc +0 -0
- package/runner/__pycache__/refinement.cpython-311.pyc +0 -0
- package/runner/__pycache__/research_swarm.cpython-311.pyc +0 -0
- package/runner/__pycache__/retrieval_log.cpython-311.pyc +0 -0
- package/runner/__pycache__/schema_validate.cpython-311.pyc +0 -0
- package/runner/__pycache__/schemas.cpython-311.pyc +0 -0
- package/runner/__pycache__/state_machine.cpython-311.pyc +0 -0
- package/runner/errors.py +51 -0
- package/runner/mcp_server.py +132 -8
- package/runner/preflight.py +157 -0
- package/runner/research_swarm.py +148 -4
- package/runner/schema_validate.py +93 -0
- package/runner/schemas.py +270 -0
- package/runner/state_machine.py +96 -10
- package/runner/tests/__pycache__/test_auction_order.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_backends.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_bet1_spike.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claim_store.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claim_witness.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claude_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_contract_tooling.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_darkharvest_audit.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_domain_packs.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_dossier_contract.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_factory.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_fleet_seam.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_grounding.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_living_dossiers.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_manifest_concurrency.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_mcp_server.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_opencode_ux.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_opencode_v2_registrars.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_pcrb.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_refinement.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_swarm.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_swarm_config.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_sweep_regressions.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_webcache.cpython-311.pyc +0 -0
- package/runner/tests/test_contract_tooling.py +312 -0
- package/runner/tests/test_mcp_server.py +2 -0
- package/schemas/alpha_dossier.schema.json +204 -0
- package/schemas/audit_report.schema.json +76 -0
- package/schemas/beta_dossier.schema.json +214 -0
- package/schemas/frontier.schema.json +61 -0
- package/schemas/manifest.schema.json +43 -0
- package/schemas/scope_manifest.schema.json +47 -0
- package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
- package/scripts/__pycache__/build_adapters.cpython-311.pyc +0 -0
- package/scripts/__pycache__/check_docs.cpython-311.pyc +0 -0
- package/scripts/__pycache__/divergence_experiment.cpython-311.pyc +0 -0
- package/scripts/__pycache__/gen_schemas.cpython-311.pyc +0 -0
- package/scripts/check_docs.py +66 -0
- package/scripts/gen_schemas.py +69 -0
- package/skills/epistemic_search/scripts/__pycache__/search.cpython-311.pyc +0 -0
- package/skills/factory/scripts/factory.py +68 -14
- package/skills/grilling/SKILL.md +14 -1
- package/skills/grilling/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/grilling/__pycache__/socratic_tree.cpython-311.pyc +0 -0
- package/skills/grilling/socratic_tree.py +88 -16
- package/skills/research_cache/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/research_cache/__pycache__/hasher.cpython-311.pyc +0 -0
- package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "beta_dossier",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"scope_id"
|
|
7
|
+
],
|
|
8
|
+
"properties": {
|
|
9
|
+
"scope_id": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"agent": {
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"mode": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"timestamp": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"negative_knowledge": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"required": [
|
|
26
|
+
"query",
|
|
27
|
+
"finding"
|
|
28
|
+
],
|
|
29
|
+
"properties": {
|
|
30
|
+
"query": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
33
|
+
"finding": {
|
|
34
|
+
"type": "string"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"candidate_repositories": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"required": [
|
|
44
|
+
"name"
|
|
45
|
+
],
|
|
46
|
+
"properties": {
|
|
47
|
+
"repo_id": {
|
|
48
|
+
"type": "string"
|
|
49
|
+
},
|
|
50
|
+
"name": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"url": {
|
|
54
|
+
"type": "string"
|
|
55
|
+
},
|
|
56
|
+
"source_hash": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
},
|
|
59
|
+
"verbatim_quote": {
|
|
60
|
+
"type": "string"
|
|
61
|
+
},
|
|
62
|
+
"license": {
|
|
63
|
+
"type": "string"
|
|
64
|
+
},
|
|
65
|
+
"license_risk": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"enum": [
|
|
68
|
+
"SAFE",
|
|
69
|
+
"COPYLEFT_WARNING",
|
|
70
|
+
"PROHIBITIVE"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"harvest_policy": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"enum": [
|
|
76
|
+
"depend-or-vendor",
|
|
77
|
+
"clean-room-rebuild-only"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"verdicts": {
|
|
81
|
+
"type": "array",
|
|
82
|
+
"items": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"required": [
|
|
85
|
+
"feature",
|
|
86
|
+
"verdict"
|
|
87
|
+
],
|
|
88
|
+
"properties": {
|
|
89
|
+
"feature": {
|
|
90
|
+
"type": "string"
|
|
91
|
+
},
|
|
92
|
+
"verdict": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"enum": [
|
|
95
|
+
"depend",
|
|
96
|
+
"vendor",
|
|
97
|
+
"clean-room-rebuild",
|
|
98
|
+
"skip"
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"reason": {
|
|
102
|
+
"type": "string"
|
|
103
|
+
},
|
|
104
|
+
"verbatim_quote": {
|
|
105
|
+
"type": "string"
|
|
106
|
+
},
|
|
107
|
+
"effort": {
|
|
108
|
+
"type": "string"
|
|
109
|
+
},
|
|
110
|
+
"impact": {
|
|
111
|
+
"type": "integer"
|
|
112
|
+
},
|
|
113
|
+
"differentiation": {
|
|
114
|
+
"type": "integer"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"warnings": {
|
|
120
|
+
"type": "array",
|
|
121
|
+
"items": {
|
|
122
|
+
"type": "string"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"attribution": {
|
|
126
|
+
"type": "object"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"falsification_claims": {
|
|
132
|
+
"type": "array",
|
|
133
|
+
"items": {
|
|
134
|
+
"type": "object",
|
|
135
|
+
"required": [
|
|
136
|
+
"claim_id",
|
|
137
|
+
"statement"
|
|
138
|
+
],
|
|
139
|
+
"properties": {
|
|
140
|
+
"claim_id": {
|
|
141
|
+
"type": "string"
|
|
142
|
+
},
|
|
143
|
+
"tag": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"enum": [
|
|
146
|
+
"VERIFIED",
|
|
147
|
+
"INFERRED",
|
|
148
|
+
"HYPOTHESIS",
|
|
149
|
+
"NEGATIVE_KNOWLEDGE"
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
"statement": {
|
|
153
|
+
"type": "string"
|
|
154
|
+
},
|
|
155
|
+
"source_hash": {
|
|
156
|
+
"type": "string"
|
|
157
|
+
},
|
|
158
|
+
"source_url": {
|
|
159
|
+
"type": "string"
|
|
160
|
+
},
|
|
161
|
+
"verbatim_quote": {
|
|
162
|
+
"type": "string"
|
|
163
|
+
},
|
|
164
|
+
"severity": {
|
|
165
|
+
"type": "string"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"methodological_critiques": {
|
|
171
|
+
"type": "array",
|
|
172
|
+
"items": {
|
|
173
|
+
"type": "object",
|
|
174
|
+
"properties": {
|
|
175
|
+
"target_assertion": {
|
|
176
|
+
"type": "string"
|
|
177
|
+
},
|
|
178
|
+
"critique": {
|
|
179
|
+
"type": "string"
|
|
180
|
+
},
|
|
181
|
+
"evidence_hash": {
|
|
182
|
+
"type": "string"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"hypotheses": {
|
|
188
|
+
"type": "array",
|
|
189
|
+
"items": {
|
|
190
|
+
"type": "object",
|
|
191
|
+
"required": [
|
|
192
|
+
"statement"
|
|
193
|
+
],
|
|
194
|
+
"properties": {
|
|
195
|
+
"hypothesis_id": {
|
|
196
|
+
"type": "string"
|
|
197
|
+
},
|
|
198
|
+
"claim_id": {
|
|
199
|
+
"type": "string"
|
|
200
|
+
},
|
|
201
|
+
"tag": {
|
|
202
|
+
"type": "string"
|
|
203
|
+
},
|
|
204
|
+
"statement": {
|
|
205
|
+
"type": "string"
|
|
206
|
+
},
|
|
207
|
+
"falsification": {
|
|
208
|
+
"type": "string"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "frontier",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"objective"
|
|
7
|
+
],
|
|
8
|
+
"properties": {
|
|
9
|
+
"objective": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"is_complete": {
|
|
13
|
+
"type": "boolean"
|
|
14
|
+
},
|
|
15
|
+
"nodes": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"additionalProperties": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"required": [
|
|
20
|
+
"node_id",
|
|
21
|
+
"question"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"node_id": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"title": {
|
|
28
|
+
"type": "string"
|
|
29
|
+
},
|
|
30
|
+
"question": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
33
|
+
"recommended": {
|
|
34
|
+
"type": "string"
|
|
35
|
+
},
|
|
36
|
+
"options": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"prerequisites": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"items": {
|
|
45
|
+
"type": "string"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"settled_answer": {
|
|
49
|
+
"type": [
|
|
50
|
+
"string",
|
|
51
|
+
"null"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"settled_constraints": {
|
|
58
|
+
"type": "object"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "manifest",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"session_id",
|
|
7
|
+
"objective",
|
|
8
|
+
"status",
|
|
9
|
+
"scopes"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"session_id": {
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"objective": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"status": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"created_at": {
|
|
22
|
+
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
"updated_at": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"plugin_version": {
|
|
28
|
+
"type": "string"
|
|
29
|
+
},
|
|
30
|
+
"backend": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
33
|
+
"preflight": {
|
|
34
|
+
"type": "object"
|
|
35
|
+
},
|
|
36
|
+
"scopes": {
|
|
37
|
+
"type": "array"
|
|
38
|
+
},
|
|
39
|
+
"telemetry": {
|
|
40
|
+
"type": "object"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "scope_manifest",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"scope_id",
|
|
7
|
+
"status"
|
|
8
|
+
],
|
|
9
|
+
"properties": {
|
|
10
|
+
"scope_id": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"title": {
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
"objective": {
|
|
17
|
+
"type": "string"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "string"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"status": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"alpha_completed": {
|
|
29
|
+
"type": "boolean"
|
|
30
|
+
},
|
|
31
|
+
"beta_completed": {
|
|
32
|
+
"type": "boolean"
|
|
33
|
+
},
|
|
34
|
+
"audit_completed": {
|
|
35
|
+
"type": "boolean"
|
|
36
|
+
},
|
|
37
|
+
"created_at": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"outputs": {
|
|
41
|
+
"type": "array"
|
|
42
|
+
},
|
|
43
|
+
"self_reported_epistemic_audit": {
|
|
44
|
+
"type": "object"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Fail CI when a documentation reference points at a file that does not exist.
|
|
3
|
+
|
|
4
|
+
Only *repo-relative* paths are checked (a leading known source directory); bare
|
|
5
|
+
names like `manifest.json` or `hasher.py` are workspace-relative and must not be
|
|
6
|
+
flagged. This is the guard for drifts like the recorded
|
|
7
|
+
`skills/grilling/SKILL.md` `--export` reference (issue #6 item 3.11).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import re
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
15
|
+
DOC_FILES = ["README.md", "AGENTS.md", "MARKETPLACE.md"]
|
|
16
|
+
DOC_FILES += [
|
|
17
|
+
str(p.relative_to(PROJECT_ROOT)) for p in (PROJECT_ROOT / "docs").glob("*.md")
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
REPO_PREFIXES = (
|
|
21
|
+
"runner/",
|
|
22
|
+
"skills/",
|
|
23
|
+
"scripts/",
|
|
24
|
+
"plugins/",
|
|
25
|
+
"prompts/",
|
|
26
|
+
"config/",
|
|
27
|
+
"schemas/",
|
|
28
|
+
"docs/",
|
|
29
|
+
"extensions/",
|
|
30
|
+
"hooks/",
|
|
31
|
+
".claude-plugin/",
|
|
32
|
+
".omp/",
|
|
33
|
+
".agents/",
|
|
34
|
+
)
|
|
35
|
+
PATH_RE = re.compile(r"`([A-Za-z0-9_./-]+/[A-Za-z0-9_./-]+)`")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def missing_references() -> list:
|
|
39
|
+
missing = []
|
|
40
|
+
for rel in DOC_FILES:
|
|
41
|
+
path = PROJECT_ROOT / rel
|
|
42
|
+
if not path.exists():
|
|
43
|
+
continue
|
|
44
|
+
text = path.read_text(encoding="utf-8")
|
|
45
|
+
for ref in set(PATH_RE.findall(text)):
|
|
46
|
+
if any(ch in ref for ch in "{}*"):
|
|
47
|
+
continue
|
|
48
|
+
if not ref.startswith(REPO_PREFIXES):
|
|
49
|
+
continue
|
|
50
|
+
if not (PROJECT_ROOT / ref.split("#")[0]).exists():
|
|
51
|
+
missing.append((rel, ref))
|
|
52
|
+
return sorted(set(missing))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main() -> int:
|
|
56
|
+
missing = missing_references()
|
|
57
|
+
if missing:
|
|
58
|
+
for doc, ref in missing:
|
|
59
|
+
print(f"❌ {doc}: references missing path `{ref}`", file=sys.stderr)
|
|
60
|
+
return 1
|
|
61
|
+
print(f"✅ {len(DOC_FILES)} docs: all repo-relative references resolve.")
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render `schemas/*.schema.json` from `runner/schemas.py`.
|
|
3
|
+
|
|
4
|
+
Generated, never hand-edited. `--check` regenerates in memory and diffs against
|
|
5
|
+
disk so CI fails on drift (issue #6 item 2.1).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
14
|
+
if str(PROJECT_ROOT) not in sys.path:
|
|
15
|
+
sys.path.insert(0, str(PROJECT_ROOT))
|
|
16
|
+
|
|
17
|
+
from runner.schemas import SCHEMAS # noqa: E402
|
|
18
|
+
|
|
19
|
+
SCHEMA_DIR = PROJECT_ROOT / "schemas"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def render() -> dict:
|
|
23
|
+
return {name: schema for name, schema in SCHEMAS.items()}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def write_all() -> int:
|
|
27
|
+
SCHEMA_DIR.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
for name, schema in SCHEMAS.items():
|
|
29
|
+
(SCHEMA_DIR / f"{name}.schema.json").write_text(
|
|
30
|
+
json.dumps(schema, indent=2) + "\n", encoding="utf-8"
|
|
31
|
+
)
|
|
32
|
+
return len(SCHEMAS)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def check() -> int:
|
|
36
|
+
errors = []
|
|
37
|
+
for name, schema in SCHEMAS.items():
|
|
38
|
+
path = SCHEMA_DIR / f"{name}.schema.json"
|
|
39
|
+
expected = json.dumps(schema, indent=2) + "\n"
|
|
40
|
+
if not path.exists():
|
|
41
|
+
errors.append(f"MISSING schema: {path.relative_to(PROJECT_ROOT)}")
|
|
42
|
+
elif path.read_text(encoding="utf-8") != expected:
|
|
43
|
+
errors.append(f"OUT OF SYNC: {path.relative_to(PROJECT_ROOT)}")
|
|
44
|
+
stray = {p.name for p in SCHEMA_DIR.glob("*.schema.json")} - {
|
|
45
|
+
f"{n}.schema.json" for n in SCHEMAS
|
|
46
|
+
}
|
|
47
|
+
for name in sorted(stray):
|
|
48
|
+
errors.append(f"STRAY schema (delete or add to runner/schemas.py): {name}")
|
|
49
|
+
if errors:
|
|
50
|
+
for e in errors:
|
|
51
|
+
print(f"❌ {e}", file=sys.stderr)
|
|
52
|
+
return 1
|
|
53
|
+
print(f"✅ {len(SCHEMAS)} schemas in sync with runner/schemas.py.")
|
|
54
|
+
return 0
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def main() -> int:
|
|
58
|
+
parser = argparse.ArgumentParser(description="Generate IUMBTEMS JSON schemas")
|
|
59
|
+
parser.add_argument("--check", action="store_true", help="fail on drift")
|
|
60
|
+
args = parser.parse_args()
|
|
61
|
+
if args.check:
|
|
62
|
+
return check()
|
|
63
|
+
count = write_all()
|
|
64
|
+
print(f"✅ Wrote {count} schemas to {SCHEMA_DIR.relative_to(PROJECT_ROOT)}/.")
|
|
65
|
+
return 0
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
raise SystemExit(main())
|
|
Binary file
|
|
@@ -55,7 +55,10 @@ def run_dir(run):
|
|
|
55
55
|
def load_state(run):
|
|
56
56
|
p = run_dir(run) / "state.json"
|
|
57
57
|
if not p.exists():
|
|
58
|
-
raise SystemExit(
|
|
58
|
+
raise SystemExit(
|
|
59
|
+
f"No factory run '{run}'. Pass --run <name> (or run "
|
|
60
|
+
f"`factory.py init --run <name>` first)."
|
|
61
|
+
)
|
|
59
62
|
return json.loads(p.read_text(encoding="utf-8"))
|
|
60
63
|
|
|
61
64
|
|
|
@@ -82,6 +85,19 @@ def cmd_phase_add(args):
|
|
|
82
85
|
state = load_state(args.run)
|
|
83
86
|
if args.phase in state["phases"]:
|
|
84
87
|
raise SystemExit(f"Phase '{args.phase}' already exists.")
|
|
88
|
+
# Phase output goes to phase.json — a run-state helper must never clobber the
|
|
89
|
+
# author-written GOAL.md / dossier.json it is meant to track (#6 item 2.3).
|
|
90
|
+
# This check runs BEFORE any state mutation so a refusal leaves no trace.
|
|
91
|
+
phase_dir = ROADMAP_DIR / args.phase
|
|
92
|
+
authored = [
|
|
93
|
+
name for name in ("GOAL.md", "dossier.json") if (phase_dir / name).exists()
|
|
94
|
+
]
|
|
95
|
+
if authored and not getattr(args, "force", False):
|
|
96
|
+
raise SystemExit(
|
|
97
|
+
f"Refusing to touch author-written file(s) in {phase_dir}: "
|
|
98
|
+
f"{', '.join(authored)}. phase-add now writes phase.json only; "
|
|
99
|
+
f"re-run with --force to overwrite."
|
|
100
|
+
)
|
|
85
101
|
state["phases"][args.phase] = {
|
|
86
102
|
"goal": args.goal,
|
|
87
103
|
"acceptance": [a.strip() for a in args.accept.split(";") if a.strip()],
|
|
@@ -90,30 +106,52 @@ def cmd_phase_add(args):
|
|
|
90
106
|
"qa_reports": [],
|
|
91
107
|
}
|
|
92
108
|
save_state(args.run, state)
|
|
93
|
-
# Phase output: GOAL.md + dossier.json skeleton (evidence filled by manager).
|
|
94
|
-
phase_dir = ROADMAP_DIR / args.phase
|
|
95
109
|
phase_dir.mkdir(parents=True, exist_ok=True)
|
|
96
|
-
(phase_dir / "
|
|
97
|
-
f"# {args.phase}: {args.goal}\n\n## Acceptance\n"
|
|
98
|
-
+ "".join(f"- [ ] {a}\n" for a in state["phases"][args.phase]["acceptance"]),
|
|
99
|
-
encoding="utf-8",
|
|
100
|
-
)
|
|
101
|
-
(phase_dir / "dossier.json").write_text(
|
|
110
|
+
(phase_dir / "phase.json").write_text(
|
|
102
111
|
json.dumps(
|
|
103
112
|
{
|
|
104
113
|
"phase": args.phase,
|
|
105
114
|
"goal": args.goal,
|
|
106
|
-
"evidence": [],
|
|
107
115
|
"acceptance": state["phases"][args.phase]["acceptance"],
|
|
108
|
-
"
|
|
109
|
-
"verdict": "briefed",
|
|
110
|
-
"hashes": [],
|
|
116
|
+
"status": "briefed",
|
|
111
117
|
},
|
|
112
118
|
indent=2,
|
|
113
119
|
),
|
|
114
120
|
encoding="utf-8",
|
|
115
121
|
)
|
|
116
|
-
print(f"✅ Phase '{args.phase}' briefed → {phase_dir}")
|
|
122
|
+
print(f"✅ Phase '{args.phase}' briefed → {phase_dir / 'phase.json'}")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def cmd_gate(args):
|
|
126
|
+
"""First-class gate bookkeeping (open/settle/approve/waive/escalate/count)."""
|
|
127
|
+
state = load_state(args.run)
|
|
128
|
+
gates = state.setdefault("gates", {})
|
|
129
|
+
gate = gates.setdefault(
|
|
130
|
+
args.phase, {"status": "closed", "cycles": 0, "waivers": [], "history": []}
|
|
131
|
+
)
|
|
132
|
+
action = (args.action or "").lower()
|
|
133
|
+
if action == "open":
|
|
134
|
+
gate["status"] = "open"
|
|
135
|
+
gate["cycles"] = gate.get("cycles", 0) + 1
|
|
136
|
+
state["gate_cycles"] = state.get("gate_cycles", 0) + 1
|
|
137
|
+
elif action == "settle":
|
|
138
|
+
gate["status"] = "settled"
|
|
139
|
+
elif action == "approve":
|
|
140
|
+
gate["status"] = "approved"
|
|
141
|
+
elif action == "waive":
|
|
142
|
+
gate["status"] = "waived"
|
|
143
|
+
gate["waivers"].append(args.reason or "")
|
|
144
|
+
elif action == "escalate":
|
|
145
|
+
gate["status"] = "escalated"
|
|
146
|
+
gate["cycles"] = gate.get("cycles", 0) + 1
|
|
147
|
+
state["gate_cycles"] = state.get("gate_cycles", 0) + 1
|
|
148
|
+
elif action != "count":
|
|
149
|
+
raise SystemExit(
|
|
150
|
+
"gate --action must be one of: open, settle, approve, waive, escalate, count"
|
|
151
|
+
)
|
|
152
|
+
gate["history"].append({"action": action, "at": now(), "reason": args.reason or ""})
|
|
153
|
+
save_state(args.run, state)
|
|
154
|
+
print(json.dumps({"phase": args.phase, "gate": gate}, indent=2))
|
|
117
155
|
|
|
118
156
|
|
|
119
157
|
def cmd_qa_record(args):
|
|
@@ -211,6 +249,11 @@ def main():
|
|
|
211
249
|
p.add_argument("--phase", required=True)
|
|
212
250
|
p.add_argument("--goal", required=True)
|
|
213
251
|
p.add_argument("--accept", default="")
|
|
252
|
+
p.add_argument(
|
|
253
|
+
"--force",
|
|
254
|
+
action="store_true",
|
|
255
|
+
help="Overwrite author-written GOAL.md/dossier.json if present",
|
|
256
|
+
)
|
|
214
257
|
_add_common(p)
|
|
215
258
|
p = sub.add_parser("qa-record")
|
|
216
259
|
p.add_argument("--run", required=True)
|
|
@@ -227,6 +270,16 @@ def main():
|
|
|
227
270
|
p = sub.add_parser("stop")
|
|
228
271
|
p.add_argument("--run", required=True)
|
|
229
272
|
_add_common(p)
|
|
273
|
+
p = sub.add_parser("gate")
|
|
274
|
+
p.add_argument("--run", required=True)
|
|
275
|
+
p.add_argument("--phase", required=True)
|
|
276
|
+
p.add_argument(
|
|
277
|
+
"--action",
|
|
278
|
+
required=True,
|
|
279
|
+
choices=["open", "settle", "approve", "waive", "escalate", "count"],
|
|
280
|
+
)
|
|
281
|
+
p.add_argument("--reason", default="")
|
|
282
|
+
_add_common(p)
|
|
230
283
|
|
|
231
284
|
args = ap.parse_args()
|
|
232
285
|
root = resolve_project_root(args.project_dir)
|
|
@@ -238,6 +291,7 @@ def main():
|
|
|
238
291
|
"qa-record": cmd_qa_record,
|
|
239
292
|
"expansion": cmd_expansion,
|
|
240
293
|
"stop": cmd_stop,
|
|
294
|
+
"gate": cmd_gate,
|
|
241
295
|
}[args.command](args)
|
|
242
296
|
sys.exit(code if isinstance(code, int) else 0)
|
|
243
297
|
|
package/skills/grilling/SKILL.md
CHANGED
|
@@ -42,7 +42,20 @@ Always challenge default premises in Round 1:
|
|
|
42
42
|
|
|
43
43
|
## 5. FRONTIER RESOLUTION & FREEZING
|
|
44
44
|
|
|
45
|
+
The frontier is fully tool-drivable (no hand-written JSON):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# author a node (prerequisites gate when it appears on the frontier)
|
|
49
|
+
python3 skills/grilling/socratic_tree.py --add-node --id N1 \
|
|
50
|
+
--question "L1 or L2 for state verification?" --depends-on ""
|
|
51
|
+
# settle a node
|
|
52
|
+
python3 skills/grilling/socratic_tree.py --settle N1 "L1 for finality"
|
|
53
|
+
# inspect / freeze
|
|
54
|
+
python3 skills/grilling/socratic_tree.py --show-frontier
|
|
55
|
+
python3 skills/grilling/socratic_tree.py --export
|
|
56
|
+
```
|
|
57
|
+
|
|
45
58
|
When every branch of the design tree has been visited and the frontier is empty:
|
|
46
59
|
1. Summarize the settled constraints.
|
|
47
|
-
2.
|
|
60
|
+
2. Freeze the settled state to `.research/frontier.json` (`--export`, default path).
|
|
48
61
|
3. Hand off the settled frontier to the **Swarm Orchestrator** to begin empirical dialectic execution.
|
|
Binary file
|
|
Binary file
|