Skip to content

feat(ka-routes)!: remove /api/assertion — unify everything on /api/knowledge-assets#1039

Closed
branarakic wants to merge 11 commits into
integration/v10-devnetfrom
feat/unify-knowledge-assets-routes
Closed

feat(ka-routes)!: remove /api/assertion — unify everything on /api/knowledge-assets#1039
branarakic wants to merge 11 commits into
integration/v10-devnetfrom
feat/unify-knowledge-assets-routes

Conversation

@branarakic

Copy link
Copy Markdown
Contributor

What & why

The v10 daemon carried two parallel HTTP surfaces for the same engine: the legacy /api/assertion/* routes and the newer /api/knowledge-assets/* (KA) routes — both calling the identical agent.assertion.* engine. That dual-route ambiguity caused a string of subtle bugs across the open PRs (#971/#978/#988/#990/#991/#992): missing side-effects, dropped response fields, validation gaps, alreadyExists/author-scoping regressions, vm/publish status mismatches.

This PR removes /api/assertion/* entirely and makes /api/knowledge-assets/* the single, complete surface — one coherent WM→SWM→VM lifecycle. The KA file header always said the legacy routes would be redirected/retired in a follow-up; this is that follow-up, done as a clean cut.

Targeting rc.17. Base integration/v10-devnet (which has the KA hardening main lacks).

Staged sequence (9 commits)

  1. KA route completeness + parity — ported the 6 missing route families onto KA and brought the existing routes to full legacy parity:
    • GET .../:name/wm/quads (was POST :name/query), POST .../:name/wm/import-file (multipart) + GET .../wm/extraction-status, POST .../import-artifact/{resolve,read-markdown}, POST .../semantic-enrichment/write, and the promote-async queue as POST .../:name/swm/share-async + GET/DELETE .../swm/share-jobs[/:jobId][/recover]
    • parity: context-graph resolution/validation, :name decode/validation, SSE emitMemoryGraphChanged + recordAssertionActivity + notifications on every mutation, full finalize/publish payloads, alreadyExists, author-scoped agentAddress, strict boolean validation, seal-author activity attribution
    • 30 shared helpers extracted into shared-assertion-helpers.ts; 61 route unit tests
  2. ~80 consumers repointed — cli SDK (api-client.ts), mcp-dkg, adapter-openclaw, the Hermes Python client, node-ui (UI + e2e), network-sim (incl. its server-side mock), agent/core, ~14 devnet scripts, and living docs/skills. The one shape change handled throughout: query POST-body → GET-querystring.
  3. 25 test files migrated/repointed — route-level tests moved from handleAssertionRouteshandleKnowledgeAssetsRoutes preserving every edge case (409 not-persisted, owner-guard 403, 503 worker-unavailable, validation 400s). Also fixes a discard parity gap the migration surfaced (KA discard now evicts the cached extraction-status, matching legacy).
  4. Delete assertion.ts (−3909 lines) + its dispatch. The two read-only chain-metadata routes that happened to live there (GET /api/kc/:id, GET /api/kc/:id/author) — not part of the lifecycle — were preserved verbatim in a new kc-chain-metadata.ts module.

Full path mapping + the 35 parity gaps are documented in docs/migrations/assertion-to-knowledge-assets.md.

Verification

  • Full monorepo build: 20/20 packages, 0 errors
  • cli vitest: 1963 passed (the only 2 failures are environmental e2e timeouts — one with zero assertion/KA refs, the other a CLI-cold-start timing flake whose command was manually verified to produce correct output)
  • adapter-openclaw: 82+191+58 green; migrated cli route suites green (31+2+4+5+32+23+28)
  • Live 6-node devnet (this build, commit 3b5c47f):
    • /api/assertion/*404 everywhere; /api/knowledge-assets/* create/write/wm/quads/swm/share-jobs all live with the new parity fields
    • bootstrap landed 10 confirmed on-chain publishes through the KA surface
    • v10-core-flows 4/5, including the decisive "create/write/finalize/promote emit memory_graph_changed in order" lifecycle test. The 1 failure is an unrelated Random-Sampling epoch-score timing flake, downstream of a successful KA publish.

⚠️ Breaking

/api/assertion/* no longer exists. All first-party clients/adapters/scripts/docs/tests are migrated in this PR. External callers must move to /api/knowledge-assets/* (mapping in the migration doc).

🤖 Generated with Claude Code

Branimir Rakic and others added 9 commits June 6, 2026 01:14
…y + add wm/quads

First increment of the assertion→knowledge-assets unification (issue: remove
/api/assertion entirely; base integration/v10-devnet; targeting rc.17).

Brings the EXISTING /api/knowledge-assets/* routes to full parity with the
legacy /api/assertion/* handlers, fixing the ambiguity bugs the dual-route
model caused (PR #971/#988 reviews):
- contextGraphId resolution/validation on every mutation (resolveRequiredWrite
  ContextGraphId) — bad/foreign id is a 400, not an opaque 500
- :name decode + validateAssertionName on all verbs + GET
- side-effects restored: emitMemoryGraphChanged + recordAssertionActivity +
  notification SSE on create/write/finalize/discard/share/publish (dashboards
  and the bell pane were going silent under the KA routes)
- full finalize payload (assertionUri/authorAddress/schemeVersion/chainId/
  kav10Address) and full vm/publish payload (assertionUri/authorAddress/
  merkleRoot/kas/blockNumber)
- create now reports `alreadyExists` (idempotent get-or-create); GET accepts
  author-scoped `agentAddress`; strict boolean validation of alsoShareSwm/
  alsoPublishVm; published-activity attributed to the seal author
- NEW route: GET /api/knowledge-assets/:name/wm/quads (replaces the legacy
  POST /api/assertion/:name/query quad dump)

Full migration blueprint (6 missing routes, 30-helper relocation, 35 parity
gaps, ~80 consumers) captured in docs/migrations/assertion-to-knowledge-assets.md.

Typecheck-clean (cli tsc). Route unit-test mocks (listContextGraphs writability)
and the remaining 5 missing routes follow in subsequent Stage-1 increments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…o shared-assertion-helpers.ts

Moves 30+ helpers (import-artifact resolution, owner-guard, semantic-enrichment
RDF builders, promote-async job views, quad sort) out of assertion.ts into a new
shared module so the new /api/knowledge-assets route ports can reuse them and
assertion.ts can be deleted in Stage 4. assertion.ts re-imports them; behavior
unchanged. Typecheck-clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nt onto KA surface

Adds POST /api/knowledge-assets/import-artifact/{resolve,read-markdown} and
POST /api/knowledge-assets/semantic-enrichment/write as faithful ports of the
legacy /api/assertion/* equivalents (new module knowledge-assets-import.ts,
reusing shared-assertion-helpers). Identical owner-guard (#872 relax on
public+open CGs for reads, strict for enrichment), 400/403/404/409/413 mapping,
response shapes, and the semantic_enrichment_written SSE. Collection-level paths
dispatched before :name parsing. Typecheck-clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n-status onto KA surface

POST /api/knowledge-assets/:name/wm/import-file (multipart) and
GET  /api/knowledge-assets/:name/wm/extraction-status — verbatim ports of the
legacy /api/assertion/:name/{import-file,extraction-status} handlers (same
multipart parsing, MIME inference, per-assertion lock, extractionStatus
lifecycle, two-graph atomic insert, SSE side-effects, 400/409/413/415 mapping).
import-file dispatch is placed BEFORE the JSON safeParseJson preflight so the
multipart stream is read raw. Typecheck-clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ync + share-jobs

Ports all 5 legacy /api/assertion/promote-async* routes onto the KA surface:
  POST   /api/knowledge-assets/:name/swm/share-async         (enqueue)
  GET    /api/knowledge-assets/swm/share-jobs                (list, ?state/limit/contextGraphId)
  GET    /api/knowledge-assets/swm/share-jobs/:jobId         (status)
  DELETE /api/knowledge-assets/swm/share-jobs/:jobId         (cancel)
  POST   /api/knowledge-assets/swm/share-jobs/:jobId/recover (recover)
New module knowledge-assets-async-share.ts; reuses shared promote-job helpers.
Collection job routes dispatched early (incl. new DELETE handling); enqueue
inlined in the SWM section. Faithful 503/400/404/409 mapping + PromoteJobView
shapes. Typecheck-clean.

This completes the 6 missing KA route families — the /api/knowledge-assets
surface is now a full superset of /api/assertion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…w route families)

Updates the route-test harness for the new parity (mock listContextGraphs
writability, ctx side-effect spies, full seal/publish payloads, alreadyExists)
and adds coverage for every new route: wm/quads, import-artifact resolve/
read-markdown, semantic-enrichment/write, wm/import-file (multipart), wm/
extraction-status, swm/share-async, and swm/share-jobs list/status/cancel/
recover (incl. 503 worker-unavailable, agentAddress scoping). 61 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dge-assets

Repoints every /api/assertion/* caller across the codebase to the unified KA
surface (path mapping per docs/migrations/assertion-to-knowledge-assets.md):
- cli api-client.ts (central SDK): all 7 assertion methods → KA; queryAssertion
  changed from POST-body to GET /wm/quads with querystring; promote→swm/share
- mcp-dkg client.ts + adapter-openclaw dkg-client.ts: all assertion methods → KA
  (query POST→GET, history→GET :name, createAssertion reads alreadyExists)
- adapter-hermes Python client.py: all 9 endpoints → KA (py_compile clean)
- node-ui (src/api.ts, ui/lib/ontologyInstall.ts), network-sim (client + the
  server-side sim mock), agent/core doc-strings
- ~14 devnet/test scripts (curl/fetch) repointed; living docs + SKILL.md updated
Historical records (CHANGELOG, RFCs, ADRs, bug reports, async-promote specs) and
unit/e2e test files left for later stages. Every touched TS package typechecks
clean; Python py_compile clean; shell bash -n / node --check clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…client/devnet tests

- cli daemon route-level tests (promote-async-routes, promote-async-daemon-
  lifecycle, promote-route-not-persisted, async-promote-queue-e2e, import-
  artifact-routes, memory-graph-events, context-graph-write-path-validation)
  migrated from handleAssertionRoutes → handleKnowledgeAssetsRoutes at the KA
  paths, preserving every edge case (409 not-persisted, owner-guard 403, 503
  worker-unavailable, validation 400s, SSE operations). Ran green via chain-free
  configs (31+2+4+5+32+23+28).
- adapter-openclaw/hermes + node-ui + agent client tests repointed to KA URLs/
  methods/shapes (openclaw 82+191+58 green); devnet integration tests + bootstrap
  repointed for the final live run.

Also fixes a discard parity gap the migration surfaced: the KA wm/discard handler
now evicts the cached extraction-status record (extractionStatus.delete via
contextGraphAssertionUri) exactly as the legacy discard did, so a re-import after
discard doesn't see a stale "completed".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/kc reads

Removes packages/cli/src/daemon/routes/assertion.ts (3909 lines) and its dispatch
in handle-request.ts. The /api/assertion/* HTTP surface is gone — everything now
flows through /api/knowledge-assets/*.

Two read-only chain-metadata routes that happened to live in assertion.ts but are
NOT part of the assertion lifecycle (GET /api/kc/:id, GET /api/kc/:id/author) are
extracted verbatim into the new routes/kc-chain-metadata.ts module and dispatched
separately, preserving their exact paths/shapes. kc-author-route.e2e.test.ts
repointed to the new module.

BREAKING: /api/assertion/* routes no longer exist. All first-party clients,
adapters, scripts, docs, and tests were migrated to /api/knowledge-assets/* in
Stages 2-3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex review skipped: filtered diff is 13260 lines (cap: 5,000). Please consider splitting this into smaller PRs for reviewability.

branarakic and others added 2 commits June 6, 2026 08:35
…rix + rc.17 (#996)

* fix(storage): blank-node-safe delete on SPARQL backends (sparql-http, blazegraph)

`SparqlHttpStore.delete(quads)` (and the identical `BlazegraphStore.delete`)
serialized every quad into a single `DELETE DATA { … }` block. SPARQL forbids
blank nodes in DELETE DATA, so any quad whose subject/object is a blank node
made a spec-compliant endpoint (Oxigraph server, Fuseki, Blazegraph) reject the
whole statement with HTTP 400 ("Variables and blank nodes are not allowed in
DELETE DATA"). This broke "Promote All → Shared" (WM→SWM, assertionPromote →
store.delete of the CONSTRUCT'd source quads) for any entity containing nested/
anonymous RDF — the common case — and exposed every other store.delete(quads)
caller (tentative/finalization cleanup, etc.) on the oxigraph-server backend.

Only the SPARQL-over-HTTP adapters are affected. The embedded OxigraphStore and
oxigraph-worker delete via the native object API (blank-node-safe), which is why
every promote/share unit test (all on OxigraphStore) and the devnet (oxigraph-
worker default) stayed green — while a fresh `dkg init`, which defaults to the
oxigraph-server backend, hit it on real data.

Fix: new `buildBlankNodeSafeDelete()` keeps ground quads on the fast DELETE DATA
path and removes blank-node quads via `DELETE { … } WHERE { … }`, grouping
connected blank-node components (linked by shared labels) into separate
statements and rewriting each blank node to a query variable — the only
spec-legal way to target existing blank-node structure over SPARQL. Per-component
emission avoids cross-product WHERE joins that would silently delete nothing.
Both adapters now share the builder.

Tests (packages/storage/test/sparql-http-blank-nodes.test.ts, 20 cases): a broad
matrix of blank-node shapes (object/subject bnodes, nested entities, RDF lists,
shared bnodes, disjoint components, deep chains, mixed ground+bnode, cross-graph,
the CONSTRUCT→delete promote reproduction) executed against a REAL embedded
Oxigraph engine (same engine oxigraph-server runs) plus the full SparqlHttpStore
HTTP path. A control test asserts the legacy DELETE-DATA-with-bnode form still
throws on that engine. Verified: 20/20 pass on the fix; 16/20 fail on the legacy
behaviour (the suite genuinely gates the regression).

Root-cause of the test gap: the prior sparql-http test used a mock HTTP server
that recorded the update string but never parsed/executed it, so invalid SPARQL
passed. The new suite runs generated SPARQL through a real engine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump version to 10.0.0-rc.17

rc.17 ships the blank-node-safe SPARQL delete fix (see previous commit). No
contract changes — the on-chain contracts stay at 10.0.3 and need no redeploy.
Root + all 18 workspace packages 10.0.0-rc.16 → 10.0.0-rc.17. Internal deps are
workspace:* and pnpm-lock.yaml does not pin workspace versions, so frozen-install
CI stays green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(storage): run the conformance matrix against the sparql-http backend by default + fix deleteByPattern

Adds the SPARQL-over-HTTP backend (the oxigraph-server default a fresh
`dkg init` gets) to the shared TripleStore conformance matrix, backed by an
in-process endpoint running the real Oxigraph engine — so it executes the
adapter's generated SPARQL (no server binary, runs on every CI run). Also adds
blank-node cases (object/subject bnodes, nested-entity-with-bnode-children =
the WM→SWM promote shape) to the shared suite so EVERY backend is exercised
with blank nodes. This is the matrix entry that would have caught the rc.16
blank-node DELETE-DATA bug.

Wiring sparql-http into the matrix immediately surfaced a SECOND latent bug in
the same class: `deleteByPattern`'s no-graph branch emitted
`DELETE { ?g_ctx { … } }` (missing the GRAPH keyword) — invalid SPARQL,
HTTP 400 on any real endpoint, never executed by a test before. Fixed in both
`sparql-http.ts` and `blazegraph.ts`.

devnet.sh already runs a backend matrix (nodes 1-2 oxigraph-worker, 3-4
blazegraph, 5-6 sparql-http/oxigraph-server) but SILENTLY fell back to the
embedded store when Docker was unavailable — which is how no devnet node ever
ran sparql-http during rc.16 validation. Added a loud coverage summary and an
opt-in `DEVNET_REQUIRE_ALL_BACKENDS=1` strict gate so CI cannot silently shrink
the matrix.

Storage suite: 181 passed / 3 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(pr996): address CodeQL + e2e review feedback

- storage test: stop reflecting the caught exception text in the mock SPARQL
  server's HTTP response (CodeQL: exception-text-as-HTML + stack-trace info
  exposure). The adapter only inspects the 400 status; return a constant
  text/plain body and log the real reason to stderr.
- node-ui: add the `widget-promote-all-btn` / `widget-publish-vm-btn` /
  `layer-action-result` data-testids the WM→SWM UI-cycle spec targets. They
  were missing, so the regression spec's first toBeVisible() would time out and
  the promote flow never ran. Tag only the LayerActionsWidget surface (the one
  the default WM/SWM `items` tab actually renders) to avoid .or() strict-mode
  multi-matches.
- e2e: correct the stale SWM→VM `fixme` rationale — the bulk publish control now
  mints one KA per SWM assertion (Design B), so on the shared seeded CG (~25
  roots) it fires ~25 on-chain mints; single-root publish (PublishPanel) is not
  wired into ProjectView nav. Kept deferred (on-chain mint already covered by the
  API sibling spec) with accurate reasoning.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(pr996): silence CodeQL in the new sparql endpoint helper

The in-process oxigraph SPARQL endpoint added in 25124c2 reintroduced the same
pattern just fixed in sparql-http-blank-nodes.test.ts: its catch block reflected
the caught exception text into the HTTP response, which CodeQL flags as
exception-text-as-HTML (#3984) + stack-trace info exposure (#3985). The
SparqlHttpStore adapter only inspects the 400 status, never the body, so return a
constant text/plain message and log the real reason to stderr.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(e2e): sort WM assertion graphs by name segment, not full URI (PR review)

findWmAssertion sorted candidate graph URIs by the full string. URIs are
.../assertion/<agent>/<name>, so a raw sort orders by the <agent> segment first
and could pick an older assertion from a different agent on a shared devnet,
making the rest of the spec read counts/markers from the wrong graph. Sort by
the trailing assertion-name segment (the stable per-import key) instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(e2e): poll for CG readiness + isolate adapter-path store per test (PR review)

- wm-swm-vm-ui-cycle.devnet: /api/status answering doesn't mean the seeded
  primary CG has finished registering, so listContextGraphs() can briefly
  return [] on a cold boot and the spec falsely skips. Poll a bounded window
  before the skip-check; a genuinely-empty operator devnet still skips.
- sparql-http-blank-nodes (adapter-path describe): the long-lived endpoint
  served a single shared embedded store across both cases, so leftover data /
  an early failure could leak into the next case. Reset to a fresh store in
  beforeEach for isolation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(e2e): drive the WM→SWM→VM UI spec on the production-default oxigraph-server backend (no Docker) (#1014)

* test(e2e): run devnet UI node on the production-default oxigraph-server backend (no Docker)

The devnet's node 1 (the node the UI/e2e suite drives) ran `oxigraph-worker`,
while fresh installs default to `oxigraph-server`. So the UI e2e never exercised
the real backend — and SPARQL-over-HTTP-only bugs like #996 (blank-node
DELETE DATA) could not reproduce in the UI flow. oxigraph-server was only
available via Docker (nodes 5-6), which silently degraded when Docker was
absent — the exact rc.16 trap.

Switch devnet nodes 1-2 to the DAEMON-MANAGED `oxigraph-server` backend: the
daemon auto-downloads + SHA-256-verifies + caches the Oxigraph binary and
spawns it on its own port — NO Docker, cross-platform, production parity (it's
what HariSeldon runs). Keep the Dockerized external Oxigraph on 5-6 as optional
extra coverage; update the backend-matrix summary + DEVNET_REQUIRE_ALL_BACKENDS
gate accordingly.

Add a HARD precondition to wm-swm-vm-ui-cycle.devnet.spec.ts: assert node 1's
/api/status storeBackend === 'oxigraph-server' and FAIL (not skip) otherwise, so
the bug-reproducing backend can never silently regress to a trivial pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(devnet): pin per-node oxigraph-server ports (7900+n) to avoid the 7878 collision

The daemon-managed oxigraph-server defaults to port 7878; two nodes on one host
(devnet nodes 1-2) collided with 'Address already in use'. Give each its own
port via store.options.port. Caught by booting the e2e devnet on the new
oxigraph-server backend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(e2e): make the WM→SWM→VM UI spec green — stale-state wipe, import-result hooks, publish-policy retry

Three issues surfaced by running the flagship oxigraph-server UI spec end-to-end:

1. devnet.sh: each `start` redeploys a FRESH chain but kept persisted per-node
   store state, so a node's stale `dkg:contextGraphOnChainId` triple made
   registerContextGraph short-circuit ("already registered") and never create
   the CG on the new chain → isContextGraphActive=false, publishPolicy reads 0,
   and every VM publish hit LU-5 "publish access-policy is unknown". Now wipe
   per-node state on a fresh-chain boot (keeping the cached Oxigraph binary), so
   nodes re-register against the new chain. Fixes local repeated-boot flakiness
   (CI was masked by always starting from a clean .devnet).

2. ImportFilesModal: the result element exposed `className="v10-import-result"`
   but none of the `data-testid="import-result"` / `data-import-status` /
   `data-import-triples` hooks the spec asserts on. Added them (the spec was
   written test-first; the component just never exposed the contract).

3. devnet-publish.ts: retry the SPECIFIC LU-5 "policy-not-confirmed" transient
   in publishToVm (≤45s) — defensive hardening for the genuine few-blocks
   registration→confirmation lag (distinct from #1 above), centralized so the
   global-setup seed and every publish caller benefit.

Result: wm-swm-vm-ui-cycle.devnet.spec → import + promote (the #996 blank-node
WM→SWM migration) pass through the REAL UI on the production-default
oxigraph-server backend; VM-publish stays an intentional test.fixme (covered by
the API-driven sibling spec).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Branimir Rakic <aleatoric@Branimirs-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* fix(e2e): query the _meta marker with a hardcoded GRAPH IRI (PR review)

readMemoryLayerMarker queried the meta partition with `GRAPH ?mg` + a
CONTAINS(/_meta) filter. Under the daemon's scoped-query guard (documented in
this file's header) the `<cg>/_meta` partition is ONLY reachable via a
hardcoded `GRAPH <iri>`; the variable+filter form is for the data /
_shared_memory partitions and 400s on a strict daemon, so the marker read would
fail even after a successful promote. Build the exact meta-graph IRI
(`did:dkg:context-graph:<cg>/_meta`, identical to what the agent's
gossip/finalization handlers use) and query it directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(e2e): scope dropzone 'supported-format hint' assertions to the modal

import-files + import-data-display asserted page-wide getByText(/\.md/) for the
dropzone's static supported-formats hint. On the shared devnet that also matches
any .md document already imported (e.g. the WM→SWM→VM lifecycle spec's
single-entity-fixture.md), tripping strict-mode with multiple matches. The hint
lives in the import modal, so scope the assertions to importFilesModal.overlay.
Hardens them against any shared .md content (root cause; green on main only
because nothing else imported a .md there).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Branimir Rakic <aleatoric@Branimirs-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…n routes

The Stage-2 consumer sweep missed 4 live calls in the browser API client:
import-file, create (publishTriples), promote, and extraction-status. Repoint
them to the unified /api/knowledge-assets surface (wm/import-file, POST
/api/knowledge-assets one-shot, swm/share, wm/extraction-status). Bodies and
response shapes are unchanged — the KA create route accepts the same
{quads, finalize, promote} one-shot (see api-client.createAssertion).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex review skipped: filtered diff is 15233 lines (cap: 5,000). Please consider splitting this into smaller PRs for reviewability.

@branarakic

Copy link
Copy Markdown
Contributor Author

Update: follow-up fixes + combined-state devnet validation

Two commits added since the initial push:

  1. fix(node-ui): repoint browser ui/api.ts off the retired /api/assertion routes — the Stage-2 consumer sweep missed 4 live calls in the browser API client (import-file, create/publishTriples, promote, extraction-status). Now on the unified KA surface (wm/import-file, POST /api/knowledge-assets one-shot, swm/share, wm/extraction-status); bodies/response shapes unchanged. Audited the rest of the source — no other live /api/assertion calls remain.

  2. cherry-pick of fix(storage): blank-node-safe SPARQL delete + backend conformance matrix + rc.17 #996 (blank-node-safe SPARQL delete + oxigraph-server devnet matrix), with the rc.17 version bump dropped — pulled in so the devnet validation runs on the production-default oxigraph-server backend. Happy to drop this from the PR if you'd prefer a migration-only diff — it's already on main and integration will get it separately.

Combined-state validation (throwaway staging branch = latest main + this migration + #1020/#1021/#1029/#1037, on a uniform oxigraph-server fleet):

  • Build 20/20; /api/assertion → 404; bootstrap publishes confirmed on-chain
  • v10-core-flows 5/5 on a clean isolated run (lifecycle SSE + Support subgraph-scoped view routing #1037 view routing + RFC-26 fees + both staking flows)

Two notes for the eventual main reconciliation (not changed here — they're main-only):

@branarakic

Copy link
Copy Markdown
Contributor Author

Superseded by #1041, which retargets this migration onto main (the active line) and fixes the one reconciliation gap (browser ui/api.ts still calling /api/assertion on main's copy). Build 20/20, combined-state v10-core-flows 5/5. Recommend reviewing/landing #1041 and closing this.

@branarakic

Copy link
Copy Markdown
Contributor Author

Subsumed into rc17-vm-wip (the rc.17 integration branch → main via #1053) — this work shipped as part of integrated rc.17. Closing as superseded.

@branarakic branarakic closed this Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant