Skip to content

Commit b9345ef

Browse files
authored
feat(daemon): add graph sync + project graph read surface (#270)
* feat(daemon): add graph sync + project graph read surface * style(daemon): gofumpt graph ledger sqlite * fix(daemon): use eagle/graph after hawk-core-contracts rename * fix(api): use OpenAPI 3.1 null type for graph read pagination cursor * refactor: migrate to vendored ecosystem types across bridges, engine, and gateway - Convert vendored sibling graph/review/verify types (kestrel, merlin, harrier, eyrie) to hawk's eagle contract types at boundary - Use eyrie/llm, eyrie/tools, eyrie/graph for provider, session, and engine contracts post-vendoring - Point shrike alias at vendored shrike root package - Update go.mod pins to synced sibling main (vendored state) - Relax testaudit eyrie facade rule to allow vendored llm/graph/tools * chore: reconcile ecosystem manifest with vendored state - Bump eagle_version to synced main (5877bed17503) so the contracts parity guard matches hawk's go.mod pin - Mark eyrie/harrier/shrike/swift/kestrel/merlin as not tracking eagle's module: they vendored eagle's contract types and no longer require the eagle Go module; hawk is the sole eagle consumer - gofumpt gateway files * chore: allow vendored eyrie packages in engine boundary guard check-eyrie-engine-boundary.sh forbade all eyrie imports below the engine facade; hawk uses the full vendored eyrie/llm, eyrie/graph, and eyrie/tools surfaces post-vendoring. Allow those packages, matching the testaudit facade rule.
1 parent a7161c5 commit b9345ef

34 files changed

Lines changed: 2169 additions & 71 deletions

‎api/openapi.yaml‎

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,77 @@ components:
273273
items:
274274
$ref: "#/components/schemas/GraphEvent"
275275

276+
GraphSyncRequest:
277+
type: object
278+
required: [syncId, projectId, graph]
279+
properties:
280+
syncId:
281+
type: string
282+
minLength: 1
283+
maxLength: 256
284+
projectId:
285+
type: string
286+
minLength: 1
287+
maxLength: 128
288+
sessionId:
289+
type: string
290+
maxLength: 128
291+
graph:
292+
$ref: "#/components/schemas/ExecutionGraph"
293+
294+
GraphSyncResponse:
295+
type: object
296+
required: [accepted, duplicate, graphDigest]
297+
properties:
298+
accepted:
299+
type: boolean
300+
duplicate:
301+
type: boolean
302+
graphDigest:
303+
type: string
304+
pattern: '^[a-f0-9]{64}$'
305+
facts:
306+
type: integer
307+
308+
GraphReadResponse:
309+
type: object
310+
required: [graph, limits, pagination]
311+
properties:
312+
graph:
313+
type: object
314+
properties:
315+
schema_version:
316+
type: string
317+
generated_at:
318+
type: string
319+
format: date-time
320+
scope:
321+
type: object
322+
additionalProperties:
323+
type: string
324+
nodes:
325+
type: array
326+
items:
327+
type: object
328+
edges:
329+
type: array
330+
items:
331+
type: object
332+
events:
333+
type: array
334+
items:
335+
type: object
336+
limits:
337+
type: object
338+
properties:
339+
perFactType:
340+
type: integer
341+
pagination:
342+
type: object
343+
properties:
344+
next_cursor:
345+
type: [string, "null"]
346+
276347
Message:
277348
type: object
278349
properties:
@@ -863,6 +934,105 @@ paths:
863934
schema:
864935
$ref: "#/components/schemas/Error"
865936

937+
/v1/graph/sync:
938+
post:
939+
operationId: syncGraph
940+
tags: [graphs]
941+
summary: Ingest portable graph facts from a producer
942+
description: |
943+
Accepts a producer's portable `*.graph/v1` facts (e.g. from a future
944+
ecosystem repo), validates them against the shared graph contract, and
945+
acknowledges with an idempotency digest. Mirrors the cloud plane's
946+
`/v1/graph/sync` so a producer can target either surface with the same
947+
payload. The daemon retains an in-memory idempotency ledger; durable
948+
retention is the cloud plane's job.
949+
requestBody:
950+
required: true
951+
content:
952+
application/json:
953+
schema:
954+
$ref: "#/components/schemas/GraphSyncRequest"
955+
responses:
956+
"202":
957+
description: Graph accepted
958+
content:
959+
application/json:
960+
schema:
961+
$ref: "#/components/schemas/GraphSyncResponse"
962+
"200":
963+
description: Graph accepted as a duplicate of a prior sync
964+
content:
965+
application/json:
966+
schema:
967+
$ref: "#/components/schemas/GraphSyncResponse"
968+
"400":
969+
description: Invalid or non-portable graph
970+
content:
971+
application/json:
972+
schema:
973+
$ref: "#/components/schemas/Error"
974+
"401":
975+
description: Unauthorized
976+
content:
977+
application/json:
978+
schema:
979+
$ref: "#/components/schemas/Error"
980+
"409":
981+
description: Sync ID reused with different content
982+
content:
983+
application/json:
984+
schema:
985+
$ref: "#/components/schemas/Error"
986+
987+
/v1/projects/{projectId}/graph:
988+
get:
989+
operationId: getProjectGraph
990+
tags: [graphs]
991+
summary: Read back ingested portable graph facts for a project
992+
description: |
993+
Returns the portable graph facts previously accepted via
994+
`POST /v1/graph/sync` for a project, mirroring the cloud plane's read
995+
projection so a producer can verify what was ingested on either
996+
surface. The daemon returns a single page per fact type.
997+
parameters:
998+
- name: projectId
999+
in: path
1000+
required: true
1001+
schema:
1002+
type: string
1003+
- name: sessionId
1004+
in: query
1005+
required: false
1006+
schema:
1007+
type: string
1008+
- name: limit
1009+
in: query
1010+
required: false
1011+
schema:
1012+
type: integer
1013+
default: 100
1014+
minimum: 1
1015+
maximum: 250
1016+
responses:
1017+
"200":
1018+
description: Portable graph facts for the project
1019+
content:
1020+
application/json:
1021+
schema:
1022+
$ref: "#/components/schemas/GraphReadResponse"
1023+
"400":
1024+
description: Invalid project or session identifier
1025+
content:
1026+
application/json:
1027+
schema:
1028+
$ref: "#/components/schemas/Error"
1029+
"401":
1030+
description: Unauthorized
1031+
content:
1032+
application/json:
1033+
schema:
1034+
$ref: "#/components/schemas/Error"
1035+
8661036
/v1/stats:
8671037
get:
8681038
operationId: getStats

‎ecosystem.yaml‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ schema_version: 1
55
# records the user-facing capability. Tooling must consume this file instead of
66
# carrying its own repo-name list.
77
contracts:
8-
eagle_version: v0.0.0-20260831121050-12ea8cc11b16
8+
eagle_version: v0.0.0-20260902153929-5877bed17503
99
portable_graph_schema: hawk.graph/v1
1010
cloud_graph_schema: graycode-cloud.graph/v1
1111
usage_event: usage.recorded.v1
@@ -45,7 +45,7 @@ repositories:
4545
language: go
4646
module: github.com/GrayCodeAI/eyrie
4747
workspace: true
48-
tracks_eagle: true
48+
tracks_eagle: false
4949
facade: github.com/GrayCodeAI/eyrie/engine
5050

5151
- directory: harrier
@@ -55,7 +55,7 @@ repositories:
5555
language: go
5656
module: github.com/GrayCodeAI/harrier
5757
workspace: true
58-
tracks_eagle: true
58+
tracks_eagle: false
5959
facade: github.com/GrayCodeAI/harrier/engine
6060

6161
- directory: shrike
@@ -65,7 +65,7 @@ repositories:
6565
language: go
6666
module: github.com/GrayCodeAI/shrike
6767
workspace: true
68-
tracks_eagle: true
68+
tracks_eagle: false
6969
facade: github.com/GrayCodeAI/shrike
7070

7171
- directory: swift
@@ -75,7 +75,7 @@ repositories:
7575
language: go
7676
module: github.com/GrayCodeAI/swift
7777
workspace: true
78-
tracks_eagle: true
78+
tracks_eagle: false
7979
facade: github.com/GrayCodeAI/swift/cli
8080

8181
- directory: kestrel
@@ -85,7 +85,7 @@ repositories:
8585
language: go
8686
module: github.com/GrayCodeAI/kestrel
8787
workspace: true
88-
tracks_eagle: true
88+
tracks_eagle: false
8989
facade: github.com/GrayCodeAI/kestrel
9090

9191
- directory: merlin
@@ -95,7 +95,7 @@ repositories:
9595
language: go
9696
module: github.com/GrayCodeAI/merlin
9797
workspace: true
98-
tracks_eagle: true
98+
tracks_eagle: false
9999
facade: github.com/GrayCodeAI/merlin
100100

101101
- directory: sparrow

‎go.mod‎

Lines changed: 7 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎go.sum‎

Lines changed: 14 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)