@quolu/lattice 0.57.3 → 0.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -67,6 +67,38 @@ lattice todo show --plan <key> --task <id> --json
67
67
  後続工程それぞれの状態(未着手/作業中/完了/ブロック中)と、その工程の並列可否を示します。
68
68
  note本文はHTMLを描くすべての面へ載ります。project別HTMLの生成や再生成は不要です。
69
69
 
70
+ ### ToDoのdataflowを実装前と実装後で照合する
71
+
72
+ codeを変更するplanだけ、plan定義後に論理dataflow検査を明示的に有効化できます。出版や運用など
73
+ code-dataflowを持たないplanへは適用しません。入力schemaはCLIから取得でき、planned sourceを保存しても
74
+ まだ有効化されません。clean worktreeでのauthoritative compileが`consistent`になった時だけ、
75
+ そのplan version専用のimmutable bindingが発行されます。
76
+
77
+ ```bash
78
+ lattice todo structure --schema --json
79
+ lattice todo structure input --plan <key> --input structure.json --dry-run --json
80
+ lattice todo structure input --plan <key> --input structure.json
81
+ lattice todo structure compile --plan <key> --input .lattice/todo/structure/<key>.json
82
+ lattice todo structure --plan <key> --json
83
+ ```
84
+
85
+ verdictは`consistent | inconsistent | unknown`の三値です。`unknown`を問題なしへ丸めず、findingはtask、
86
+ data port、code anchor、commitと次の操作を返します。plannedは不変で、実装後の形はtaskごとの
87
+ append-only realizationとして記録します。有効化済みplanのgraph taskはfresh realizationなしに
88
+ `todo done`できません。全task完了後は最終HEADで再compileし、freshかつconsistentなfinalizationが
89
+ できてからterminalを閉じます。
90
+
91
+ ```bash
92
+ lattice todo structure realize --plan <key> --task <id> --input realization.json
93
+ lattice todo done --plan <key> --task <id> --evidence evidence.json
94
+ lattice todo structure finalize --plan <key> --json
95
+ ```
96
+
97
+ 動的dashboardの「構造検査」は工程依存図とは別の面です。task/data/code/external/commit provenance、
98
+ planned/realized/effective、findingと鮮度を表示します。工程依存線へdataflow edgeを混ぜません。
99
+ 通常読取とdashboardは保存artifactだけを読み、暗黙にsensorを再実行しません。構造未適用planの
100
+ lifecycleとdashboardには、このgateも構造panelも追加されません。
101
+
70
102
  ### 変換の受入五条件
71
103
 
72
104
  **5つすべて**を満たしたときだけ採用します。1つでも欠ければ棄却です。
package/README.md CHANGED
@@ -82,6 +82,39 @@ can run in parallel. Note bodies are carried by every rendered surface, includin
82
82
  repository. Static per-project HTML is not generated; `lattice todo gantt serve` and the shared dashboard
83
83
  read the store dynamically.
84
84
 
85
+ ### Check a ToDo's dataflow before and after implementation
86
+
87
+ A code-changing plan can explicitly opt into logical dataflow inspection after the plan is defined.
88
+ Non-code plans such as publishing or operations are left unchanged. Saving a planned source does not
89
+ enable the feature. Only an authoritative compile on a clean worktree that returns `consistent` emits
90
+ an immutable binding for that exact plan version.
91
+
92
+ ```bash
93
+ lattice todo structure --schema --json
94
+ lattice todo structure input --plan <key> --input structure.json --dry-run --json
95
+ lattice todo structure input --plan <key> --input structure.json
96
+ lattice todo structure compile --plan <key> --input .lattice/todo/structure/<key>.json
97
+ lattice todo structure --plan <key> --json
98
+ ```
99
+
100
+ The verdict is three-valued: `consistent | inconsistent | unknown`. Unknown is never treated as success.
101
+ Findings identify the relevant task, data port, code anchor, and commit, and include the next action.
102
+ The planned form remains immutable; implementation changes are appended as per-task realizations. A graph
103
+ task in an enabled plan cannot complete without a fresh realization. After every task is done, Lattice
104
+ recompiles the final HEAD and requires a fresh, consistent finalization before the terminal phase can close.
105
+
106
+ ```bash
107
+ lattice todo structure realize --plan <key> --task <id> --input realization.json
108
+ lattice todo done --plan <key> --task <id> --evidence evidence.json
109
+ lattice todo structure finalize --plan <key> --json
110
+ ```
111
+
112
+ The dynamic dashboard exposes this as a separate **Structure inspection** pane. It shows task, data, code,
113
+ external contract, and commit-provenance nodes; planned, realized, and effective forms; findings; and
114
+ freshness. Dataflow edges are never mixed into the process-dependency diagram. Normal reads and dashboard
115
+ renders use saved artifacts without silently running the sensor. Plans that do not opt in retain their
116
+ existing lifecycle and do not gain a structure pane.
117
+
85
118
  ### The five acceptance conditions
86
119
 
87
120
  A transform is adopted only when **all five** hold. One missing condition rejects it:
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.todo_structure_binding.v1.schema.json",
4
+ "title": "lattice.todo_structure_binding.v1",
5
+ "description": "Immutable activation binding emitted by a successful authoritative planned compile.",
6
+ "$comment": "Runtime validation additionally enforces exact keys, strict timestamps, actor identity, and the canonical self-digest.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": [
10
+ "schema", "project_id", "plan_key", "plan_version", "topology_digest", "profile",
11
+ "baseline_sha", "structure_set_digest", "compiled_head_sha", "compile_artifact_digest",
12
+ "activated_at", "actor", "binding_digest"
13
+ ],
14
+ "properties": {
15
+ "schema": { "const": "lattice.todo_structure_binding.v1" },
16
+ "project_id": { "$ref": "#/$defs/identifier" },
17
+ "plan_key": { "$ref": "#/$defs/identifier" },
18
+ "plan_version": { "$ref": "#/$defs/identifier" },
19
+ "topology_digest": { "$ref": "#/$defs/digest" },
20
+ "profile": { "const": "code-dataflow" },
21
+ "baseline_sha": { "$ref": "#/$defs/gitSha" },
22
+ "structure_set_digest": { "$ref": "#/$defs/digest" },
23
+ "compiled_head_sha": { "$ref": "#/$defs/gitSha" },
24
+ "compile_artifact_digest": { "$ref": "#/$defs/digest" },
25
+ "activated_at": { "$ref": "#/$defs/strictTimestamp" },
26
+ "actor": { "$ref": "#/$defs/actor" },
27
+ "binding_digest": { "$ref": "#/$defs/digest" }
28
+ },
29
+ "$defs": {
30
+ "identifier": { "type": "string", "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$" },
31
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
32
+ "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
33
+ "strictTimestamp": {
34
+ "type": "string",
35
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$"
36
+ },
37
+ "actor": {
38
+ "type": "object", "additionalProperties": false,
39
+ "required": ["host", "session", "agent"],
40
+ "properties": {
41
+ "host": { "$ref": "#/$defs/identifier" },
42
+ "session": { "$ref": "#/$defs/identifier" },
43
+ "agent": { "$ref": "#/$defs/identifier" }
44
+ }
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.todo_structure_realization.v1.schema.json",
4
+ "title": "lattice.todo_structure_realization.v1",
5
+ "description": "Append-only realized logical dataflow for one applicable task.",
6
+ "$comment": "Runtime validation additionally enforces canonical ordering, chain continuity, supersedes membership, structure-set identity, planned digest, UTF-8 byte bounds, and the canonical self-digest.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": [
10
+ "schema", "project_id", "plan_key", "plan_version", "task_id", "sequence",
11
+ "previous_digest", "structure_set_digest", "planned_digest", "head_sha", "commit_oids",
12
+ "realized", "supersedes", "actor", "recorded_at", "realization_digest"
13
+ ],
14
+ "properties": {
15
+ "schema": { "const": "lattice.todo_structure_realization.v1" },
16
+ "project_id": { "$ref": "#/$defs/identifier" },
17
+ "plan_key": { "$ref": "#/$defs/identifier" },
18
+ "plan_version": { "$ref": "#/$defs/identifier" },
19
+ "task_id": { "$ref": "#/$defs/identifier" },
20
+ "sequence": { "type": "integer", "minimum": 1 },
21
+ "previous_digest": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/digest" }] },
22
+ "structure_set_digest": { "$ref": "#/$defs/digest" },
23
+ "planned_digest": { "$ref": "#/$defs/digest" },
24
+ "head_sha": { "$ref": "#/$defs/gitSha" },
25
+ "commit_oids": {
26
+ "type": "array", "minItems": 1, "maxItems": 256, "uniqueItems": true,
27
+ "items": { "$ref": "#/$defs/gitSha" }
28
+ },
29
+ "realized": {
30
+ "$ref": "lattice.todo_structure_set.v1.schema.json#/$defs/transform"
31
+ },
32
+ "supersedes": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/digest" }] },
33
+ "actor": { "$ref": "#/$defs/actor" },
34
+ "recorded_at": { "$ref": "#/$defs/strictTimestamp" },
35
+ "realization_digest": { "$ref": "#/$defs/digest" }
36
+ },
37
+ "$defs": {
38
+ "identifier": { "type": "string", "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$" },
39
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
40
+ "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
41
+ "strictTimestamp": {
42
+ "type": "string",
43
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$"
44
+ },
45
+ "actor": {
46
+ "type": "object", "additionalProperties": false,
47
+ "required": ["host", "session", "agent"],
48
+ "properties": {
49
+ "host": { "$ref": "#/$defs/identifier" },
50
+ "session": { "$ref": "#/$defs/identifier" },
51
+ "agent": { "$ref": "#/$defs/identifier" }
52
+ }
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,264 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.todo_structure_set.v1.schema.json",
4
+ "title": "lattice.todo_structure_set.v1",
5
+ "description": "AI-authored logical dataflow overlay for one registered Lattice plan version.",
6
+ "$comment": "Runtime validation additionally enforces UTF-8 byte bounds, strict canonical ordering, referential integrity, exact plan task coverage when supplied, unique data IDs, constant canonical-byte limits, the canonical self-digest, and plan-wide totals of at most 512 anchors, 4096 ports, 2048 operations, and 4096 sinks.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": [
10
+ "schema", "project_id", "plan_key", "plan_version", "topology_digest", "profile",
11
+ "baseline_sha", "external_contracts", "tasks", "structure_set_digest"
12
+ ],
13
+ "properties": {
14
+ "schema": { "const": "lattice.todo_structure_set.v1" },
15
+ "project_id": { "$ref": "#/$defs/identifier" },
16
+ "plan_key": { "$ref": "#/$defs/identifier" },
17
+ "plan_version": { "$ref": "#/$defs/identifier" },
18
+ "topology_digest": { "$ref": "#/$defs/digest" },
19
+ "profile": { "const": "code-dataflow" },
20
+ "baseline_sha": { "$ref": "#/$defs/gitSha" },
21
+ "external_contracts": {
22
+ "type": "array", "maxItems": 256, "uniqueItems": true,
23
+ "items": { "$ref": "#/$defs/externalContract" }
24
+ },
25
+ "tasks": {
26
+ "type": "array", "minItems": 1, "maxItems": 512, "uniqueItems": true,
27
+ "items": { "oneOf": [{ "$ref": "#/$defs/graphTask" }, { "$ref": "#/$defs/excludedTask" }] }
28
+ },
29
+ "structure_set_digest": { "$ref": "#/$defs/digest" }
30
+ },
31
+ "$defs": {
32
+ "identifier": {
33
+ "type": "string", "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$"
34
+ },
35
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
36
+ "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
37
+ "repoRef": {
38
+ "type": "string", "minLength": 1, "maxLength": 1024,
39
+ "pattern": "^(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*\\\\)(?!.*[\\u0000-\\u001f\\u007f])[^/]+(?:/[^/]+)*$"
40
+ },
41
+ "text": {
42
+ "type": "string", "minLength": 1, "maxLength": 4096,
43
+ "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
44
+ },
45
+ "schemaRef": {
46
+ "type": "object", "additionalProperties": false,
47
+ "required": ["path", "symbol", "json_pointer"],
48
+ "properties": {
49
+ "path": { "$ref": "#/$defs/repoRef" },
50
+ "symbol": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/text" }] },
51
+ "json_pointer": {
52
+ "oneOf": [
53
+ { "type": "null" },
54
+ { "type": "string", "pattern": "^(?:/(?:[^~/]|~[01])*)*$" }
55
+ ]
56
+ }
57
+ }
58
+ },
59
+ "dataContract": {
60
+ "type": "object", "additionalProperties": false,
61
+ "required": [
62
+ "shape_id", "schema_ref", "identity_fields", "lifecycle", "cardinality",
63
+ "compatible_shape_ids"
64
+ ],
65
+ "properties": {
66
+ "shape_id": { "$ref": "#/$defs/identifier" },
67
+ "schema_ref": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/schemaRef" }] },
68
+ "identity_fields": {
69
+ "type": "array", "maxItems": 256, "uniqueItems": true,
70
+ "items": { "$ref": "#/$defs/identifier" }
71
+ },
72
+ "lifecycle": {
73
+ "enum": ["snapshot", "event", "stream", "mutable_state", "immutable_artifact"]
74
+ },
75
+ "cardinality": { "enum": ["one", "optional", "many"] },
76
+ "compatible_shape_ids": {
77
+ "type": "array", "maxItems": 256, "uniqueItems": true,
78
+ "items": { "$ref": "#/$defs/identifier" }
79
+ }
80
+ }
81
+ },
82
+ "codeAnchor": {
83
+ "type": "object", "additionalProperties": false,
84
+ "required": ["anchor_id", "effect", "path", "symbol", "expected_at"],
85
+ "properties": {
86
+ "anchor_id": { "$ref": "#/$defs/identifier" },
87
+ "effect": { "enum": ["read", "modify", "create", "delete"] },
88
+ "path": { "$ref": "#/$defs/repoRef" },
89
+ "symbol": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/text" }] },
90
+ "expected_at": { "enum": ["baseline", "current", "after_task"] }
91
+ }
92
+ },
93
+ "sourceRef": {
94
+ "oneOf": [
95
+ {
96
+ "type": "object", "additionalProperties": false,
97
+ "required": ["kind", "anchor_id"],
98
+ "properties": { "kind": { "const": "code" }, "anchor_id": { "$ref": "#/$defs/identifier" } }
99
+ },
100
+ {
101
+ "type": "object", "additionalProperties": false,
102
+ "required": ["kind", "task_id", "port_id"],
103
+ "properties": {
104
+ "kind": { "const": "task_output" },
105
+ "task_id": { "$ref": "#/$defs/identifier" },
106
+ "port_id": { "$ref": "#/$defs/identifier" }
107
+ }
108
+ },
109
+ {
110
+ "type": "object", "additionalProperties": false,
111
+ "required": ["kind", "contract_id"],
112
+ "properties": {
113
+ "kind": { "const": "external" },
114
+ "contract_id": { "$ref": "#/$defs/identifier" }
115
+ }
116
+ },
117
+ {
118
+ "type": "object", "additionalProperties": false,
119
+ "required": ["kind", "constant_id", "value"],
120
+ "properties": {
121
+ "kind": { "const": "constant" },
122
+ "constant_id": { "$ref": "#/$defs/identifier" },
123
+ "value": true
124
+ }
125
+ }
126
+ ]
127
+ },
128
+ "inputPort": {
129
+ "type": "object", "additionalProperties": false,
130
+ "required": ["port_id", "source", "access", "contract"],
131
+ "properties": {
132
+ "port_id": { "$ref": "#/$defs/identifier" },
133
+ "source": { "$ref": "#/$defs/sourceRef" },
134
+ "access": { "enum": ["read", "consume", "observe"] },
135
+ "contract": { "$ref": "#/$defs/dataContract" }
136
+ }
137
+ },
138
+ "outputSink": {
139
+ "oneOf": [
140
+ {
141
+ "type": "object", "additionalProperties": false,
142
+ "required": ["kind", "task_id", "port_id"],
143
+ "properties": {
144
+ "kind": { "const": "task" },
145
+ "task_id": { "$ref": "#/$defs/identifier" },
146
+ "port_id": { "$ref": "#/$defs/identifier" }
147
+ }
148
+ },
149
+ {
150
+ "type": "object", "additionalProperties": false,
151
+ "required": ["kind", "anchor_id"],
152
+ "properties": { "kind": { "const": "code" }, "anchor_id": { "$ref": "#/$defs/identifier" } }
153
+ },
154
+ {
155
+ "type": "object", "additionalProperties": false,
156
+ "required": ["kind", "contract_id"],
157
+ "properties": {
158
+ "kind": { "const": "external" },
159
+ "contract_id": { "$ref": "#/$defs/identifier" }
160
+ }
161
+ },
162
+ {
163
+ "type": "object", "additionalProperties": false,
164
+ "required": ["kind", "product_id"],
165
+ "properties": {
166
+ "kind": { "const": "final_product" },
167
+ "product_id": { "$ref": "#/$defs/identifier" }
168
+ }
169
+ }
170
+ ]
171
+ },
172
+ "outputPort": {
173
+ "type": "object", "additionalProperties": false,
174
+ "required": ["port_id", "data_id", "contract", "sinks"],
175
+ "properties": {
176
+ "port_id": { "$ref": "#/$defs/identifier" },
177
+ "data_id": { "$ref": "#/$defs/identifier" },
178
+ "contract": { "$ref": "#/$defs/dataContract" },
179
+ "sinks": {
180
+ "type": "array", "maxItems": 256, "uniqueItems": true,
181
+ "items": { "$ref": "#/$defs/outputSink" }
182
+ }
183
+ }
184
+ },
185
+ "operation": {
186
+ "type": "object", "additionalProperties": false,
187
+ "required": ["operation_id", "input_port_ids", "output_port_ids", "summary"],
188
+ "properties": {
189
+ "operation_id": { "$ref": "#/$defs/identifier" },
190
+ "input_port_ids": {
191
+ "type": "array", "maxItems": 256, "uniqueItems": true,
192
+ "items": { "$ref": "#/$defs/identifier" }
193
+ },
194
+ "output_port_ids": {
195
+ "type": "array", "minItems": 1, "maxItems": 256, "uniqueItems": true,
196
+ "items": { "$ref": "#/$defs/identifier" }
197
+ },
198
+ "summary": { "$ref": "#/$defs/text" }
199
+ }
200
+ },
201
+ "transform": {
202
+ "type": "object", "additionalProperties": false,
203
+ "required": [
204
+ "outcome", "inputs", "operations", "outputs", "code_anchors", "failures",
205
+ "first_live_e2e", "non_goals"
206
+ ],
207
+ "properties": {
208
+ "outcome": { "$ref": "#/$defs/text" },
209
+ "inputs": {
210
+ "type": "array", "maxItems": 256, "uniqueItems": true,
211
+ "items": { "$ref": "#/$defs/inputPort" }
212
+ },
213
+ "operations": {
214
+ "type": "array", "maxItems": 256, "uniqueItems": true,
215
+ "items": { "$ref": "#/$defs/operation" }
216
+ },
217
+ "outputs": {
218
+ "type": "array", "maxItems": 256, "uniqueItems": true,
219
+ "items": { "$ref": "#/$defs/outputPort" }
220
+ },
221
+ "code_anchors": {
222
+ "type": "array", "maxItems": 256, "uniqueItems": true,
223
+ "items": { "$ref": "#/$defs/codeAnchor" }
224
+ },
225
+ "failures": {
226
+ "type": "array", "maxItems": 128, "uniqueItems": true,
227
+ "items": { "$ref": "#/$defs/text" }
228
+ },
229
+ "first_live_e2e": { "$ref": "#/$defs/text" },
230
+ "non_goals": {
231
+ "type": "array", "maxItems": 128, "uniqueItems": true,
232
+ "items": { "$ref": "#/$defs/text" }
233
+ }
234
+ }
235
+ },
236
+ "externalContract": {
237
+ "type": "object", "additionalProperties": false,
238
+ "required": ["contract_id", "description", "contract"],
239
+ "properties": {
240
+ "contract_id": { "$ref": "#/$defs/identifier" },
241
+ "description": { "$ref": "#/$defs/text" },
242
+ "contract": { "$ref": "#/$defs/dataContract" }
243
+ }
244
+ },
245
+ "graphTask": {
246
+ "type": "object", "additionalProperties": false,
247
+ "required": ["task_id", "applicability", "planned"],
248
+ "properties": {
249
+ "task_id": { "$ref": "#/$defs/identifier" },
250
+ "applicability": { "const": "graph" },
251
+ "planned": { "$ref": "#/$defs/transform" }
252
+ }
253
+ },
254
+ "excludedTask": {
255
+ "type": "object", "additionalProperties": false,
256
+ "required": ["task_id", "applicability", "excluded_reason"],
257
+ "properties": {
258
+ "task_id": { "$ref": "#/$defs/identifier" },
259
+ "applicability": { "const": "excluded" },
260
+ "excluded_reason": { "$ref": "#/$defs/text" }
261
+ }
262
+ }
263
+ }
264
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quolu/lattice",
3
- "version": "0.57.3",
3
+ "version": "0.58.1",
4
4
  "description": "Schedulability compiler for multi-agent development: observe real code boundaries, refactor the conflicting seam, recompile the plan for parallel execution",
5
5
  "author": {
6
6
  "name": "Quo / クオ at kitepon.dev",
@@ -34,6 +34,9 @@
34
34
  "docs/schemas/lattice.phase_todo_revision.v3.schema.json",
35
35
  "docs/schemas/lattice.todo_extraction.v2.schema.json",
36
36
  "docs/schemas/lattice.todo_extraction.v3.schema.json",
37
+ "docs/schemas/lattice.todo_structure_set.v1.schema.json",
38
+ "docs/schemas/lattice.todo_structure_realization.v1.schema.json",
39
+ "docs/schemas/lattice.todo_structure_binding.v1.schema.json",
37
40
  "docs/schemas/lattice.run_request.v1.schema.json",
38
41
  "docs/schemas/lattice.executor_packet.v1.schema.json",
39
42
  "docs/schemas/lattice.executor_receipt.v1.schema.json",
@@ -0,0 +1,20 @@
1
+ export interface TraversalCandidate {
2
+ node: {
3
+ name: string;
4
+ qualifiedName?: string;
5
+ filePath: string;
6
+ };
7
+ }
8
+ export type ExactTraversalSelection<T> = {
9
+ outcome: 'ready';
10
+ candidate: T;
11
+ } | {
12
+ outcome: 'absent' | 'ambiguous';
13
+ candidate: null;
14
+ };
15
+ /**
16
+ * fuzzy検索結果から、宣言されたsymbolとfileを同時にexact一致するnodeを一つだけ選ぶ。
17
+ * node IDは既存index内の走査にだけ使い、外部contractへは公開しない。
18
+ */
19
+ export declare function selectExactTraversalCandidate<T extends TraversalCandidate>(candidates: T[], symbol: string, exactPath: string): ExactTraversalSelection<T>;
20
+ //# sourceMappingURL=exact-traversal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exact-traversal.d.ts","sourceRoot":"","sources":["../../src/bin/exact-traversal.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,IACjC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,CAAC,CAAA;CAAE,GAClC;IAAE,OAAO,EAAE,QAAQ,GAAG,WAAW,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,kBAAkB,EACxE,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GACjD,uBAAuB,CAAC,CAAC,CAAC,CAM5B"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectExactTraversalCandidate = selectExactTraversalCandidate;
4
+ /**
5
+ * fuzzy検索結果から、宣言されたsymbolとfileを同時にexact一致するnodeを一つだけ選ぶ。
6
+ * node IDは既存index内の走査にだけ使い、外部contractへは公開しない。
7
+ */
8
+ function selectExactTraversalCandidate(candidates, symbol, exactPath) {
9
+ const exact = candidates.filter(({ node }) => node.filePath === exactPath
10
+ && (node.name === symbol || node.qualifiedName === symbol));
11
+ if (exact.length === 0)
12
+ return { outcome: 'absent', candidate: null };
13
+ if (exact.length > 1)
14
+ return { outcome: 'ambiguous', candidate: null };
15
+ return { outcome: 'ready', candidate: exact[0] };
16
+ }
17
+ //# sourceMappingURL=exact-traversal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exact-traversal.js","sourceRoot":"","sources":["../../src/bin/exact-traversal.ts"],"names":[],"mappings":";;AAgBA,sEAQC;AAZD;;;GAGG;AACH,SAAgB,6BAA6B,CAC3C,UAAe,EAAE,MAAc,EAAE,SAAiB;IAElD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS;WACpE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACtE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACvE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,CAAC;AACpD,CAAC"}
@@ -84,6 +84,7 @@ const node_version_check_1 = require("./node-version-check");
84
84
  const fatal_handler_1 = require("./fatal-handler");
85
85
  const wasm_runtime_flags_1 = require("../extraction/wasm-runtime-flags");
86
86
  const command_supervision_1 = require("./command-supervision");
87
+ const exact_traversal_1 = require("./exact-traversal");
87
88
  const extraction_version_1 = require("../extraction/extraction-version");
88
89
  const telemetry_1 = require("../telemetry");
89
90
  // Decided once, before `--color`/`--no-color` are stripped from argv below
@@ -1805,6 +1806,7 @@ function main() {
1805
1806
  .description('Find all functions/methods that call a specific symbol')
1806
1807
  .option('-p, --path <path>', 'Project path')
1807
1808
  .option('-l, --limit <number>', 'Maximum results', '20')
1809
+ .option('--exact-path <repo-relative-path>', 'Traverse one exact symbol in this repo-relative file')
1808
1810
  .option('-j, --json', 'Output as JSON')
1809
1811
  .action(async (symbol, options) => {
1810
1812
  const projectPath = resolveProjectPath(options.path);
@@ -1824,9 +1826,13 @@ function main() {
1824
1826
  }
1825
1827
  const seen = new Set();
1826
1828
  const allCallers = [];
1827
- for (const match of matches) {
1829
+ const strict = options.exactPath === undefined
1830
+ ? null : (0, exact_traversal_1.selectExactTraversalCandidate)(matches, symbol, options.exactPath);
1831
+ const traversalMatches = strict === null
1832
+ ? matches : strict.outcome === 'ready' ? [strict.candidate] : [];
1833
+ for (const match of traversalMatches) {
1828
1834
  const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
1829
- if (!exactMatch && matches.length > 1)
1835
+ if (strict === null && !exactMatch && matches.length > 1)
1830
1836
  continue;
1831
1837
  for (const c of cg.getCallers(match.node.id)) {
1832
1838
  if (!seen.has(c.node.id)) {
@@ -1836,7 +1842,7 @@ function main() {
1836
1842
  }
1837
1843
  }
1838
1844
  // Fallback: if exact filter removed everything, use the top match
1839
- if (allCallers.length === 0 && matches[0]) {
1845
+ if (strict === null && allCallers.length === 0 && matches[0]) {
1840
1846
  for (const c of cg.getCallers(matches[0].node.id)) {
1841
1847
  if (!seen.has(c.node.id)) {
1842
1848
  seen.add(c.node.id);
@@ -1846,7 +1852,11 @@ function main() {
1846
1852
  }
1847
1853
  const limited = allCallers.slice(0, limit);
1848
1854
  if (options.json) {
1849
- console.log(JSON.stringify({ symbol, callers: limited }, null, 2));
1855
+ console.log(JSON.stringify({
1856
+ symbol,
1857
+ ...(strict === null ? {} : { exactPath: options.exactPath, exactResolution: strict.outcome }),
1858
+ callers: limited,
1859
+ }, null, 2));
1850
1860
  }
1851
1861
  else if (limited.length === 0) {
1852
1862
  info(`No callers found for "${symbol}"`);
@@ -1876,6 +1886,7 @@ function main() {
1876
1886
  .description('Find all functions/methods that a specific symbol calls')
1877
1887
  .option('-p, --path <path>', 'Project path')
1878
1888
  .option('-l, --limit <number>', 'Maximum results', '20')
1889
+ .option('--exact-path <repo-relative-path>', 'Traverse one exact symbol in this repo-relative file')
1879
1890
  .option('-j, --json', 'Output as JSON')
1880
1891
  .action(async (symbol, options) => {
1881
1892
  const projectPath = resolveProjectPath(options.path);
@@ -1895,9 +1906,13 @@ function main() {
1895
1906
  }
1896
1907
  const seen = new Set();
1897
1908
  const allCallees = [];
1898
- for (const match of matches) {
1909
+ const strict = options.exactPath === undefined
1910
+ ? null : (0, exact_traversal_1.selectExactTraversalCandidate)(matches, symbol, options.exactPath);
1911
+ const traversalMatches = strict === null
1912
+ ? matches : strict.outcome === 'ready' ? [strict.candidate] : [];
1913
+ for (const match of traversalMatches) {
1899
1914
  const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
1900
- if (!exactMatch && matches.length > 1)
1915
+ if (strict === null && !exactMatch && matches.length > 1)
1901
1916
  continue;
1902
1917
  for (const c of cg.getCallees(match.node.id)) {
1903
1918
  if (!seen.has(c.node.id)) {
@@ -1906,7 +1921,7 @@ function main() {
1906
1921
  }
1907
1922
  }
1908
1923
  }
1909
- if (allCallees.length === 0 && matches[0]) {
1924
+ if (strict === null && allCallees.length === 0 && matches[0]) {
1910
1925
  for (const c of cg.getCallees(matches[0].node.id)) {
1911
1926
  if (!seen.has(c.node.id)) {
1912
1927
  seen.add(c.node.id);
@@ -1916,7 +1931,11 @@ function main() {
1916
1931
  }
1917
1932
  const limited = allCallees.slice(0, limit);
1918
1933
  if (options.json) {
1919
- console.log(JSON.stringify({ symbol, callees: limited }, null, 2));
1934
+ console.log(JSON.stringify({
1935
+ symbol,
1936
+ ...(strict === null ? {} : { exactPath: options.exactPath, exactResolution: strict.outcome }),
1937
+ callees: limited,
1938
+ }, null, 2));
1920
1939
  }
1921
1940
  else if (limited.length === 0) {
1922
1941
  info(`No callees found for "${symbol}"`);
@@ -38,7 +38,7 @@
38
38
  "fast-wrap-ansi": "^0.2.0",
39
39
  "ignore": "^7.0.5",
40
40
  "jsonc-parser": "^3.3.1",
41
- "picomatch": "^4.0.3",
41
+ "picomatch": "^4.0.4",
42
42
  "sisteransi": "^1.0.5",
43
43
  "tree-sitter-wasms": "^0.1.11",
44
44
  "web-tree-sitter": "^0.25.3"