Foundry Foundry

Foundry on Autri — Requirements Contract (v1)

Status: Requirements contract — blue-team output, session 26 (2026-06-29). Grounds the build for the scoping/design doc projects/autri/foundry-integration (which carries the rationale, the grounded audit, and decisions D1–D7). This doc is authoritative on scope; where it differs from the scoping doc's phase framing, this wins (notably: MCP authoring is in v1, and GitHub integration is dropped). Built in-house, post-launch, off the critical path.

v1 in one line

The full read-write loop on markdown docs — annotate, review, edit, and version with a changelog — in a standalone re-themed "Foundry" surface inside Autri, plus a curated MCP authoring surface built behind a local tool-testing harness. Everything private; no git.

Scope decisions (blue-team, session 26)

  • Full read-write loop is v1, not review-only. Foundry's value is the read-write loop; review-only would ship half of it and force an edit-in-Foundry / review-in-Autri split.
  • MCP document authoring is IN v1 — but the toolset is curated, not a blind 25-tool port, and is built + optimized via a local testing harness that irons out bugs before anything ships.
  • Migrate the existing Foundry docs to S3 (one-time import). No GitHub integration at all — the bridge is dropped, not deferred; there is no ongoing git relationship.
  • Markdown-first. Non-markdown editing/anchoring is out of v1.
  • Out of v1: real-time collaboration, PDF/non-markdown annotate-only, named version snapshots (every-save changelog only), tiering/packaging, per-document visibility/public reads.

Must-haves (v1) — with acceptance bars

M1 — Annotation + review domain on Autri [Phase 1]. Re-implement Foundry's domain (annotations: create, thread via parent_id, status lifecycle draft→submitted→replied→resolved, resolve/reopen; reviews: collect → submit; review lifecycle) as a faithful async re-implementation on Autri Postgres + the Cognito/MCP auth context.

  • Acceptance: the mirrored Foundry domain test suite passes against the Autri-backed implementation; an annotation on a real ingested doc threads, batches into a review, and resolves correctly.

M2 — Anchor model [Phase 1]. Annotations anchor to (section_id, char_start, char_end) into source_ranges, plus a quoted-text snapshot for display/recovery.

  • Acceptance: an annotation on a markdown section resolves to the exact span and survives a re-ingest of unchanged content — the regression test that proves the orphaning cluster (#163/#161/#127) is structurally fixed, not ported.

M3 — Identity & access [Phase 1]. user_id = Cognito sub; author_type = web→human / MCP→agent (D6). Everything private, Autri library-scoped (D5).

  • Acceptance: web- and MCP-created annotations carry correct user_id + author_type; the tenant-isolation probe shows no cross-tenant leakage.

M4 — Authoring/review UI [Phase 2]. Standalone "Foundry" sidebar surface, rebuilt native in Next.js (D3), Autri-themed. Reviewer flow (highlight → comment → batch → submit) and author flow (edit → save → changelog), with the char-offset annotation renderer.

  • Acceptance: a human reviews and edits a real doc end-to-end in the surface; visual QA passes; highlights map to the correct spans.

M5 — Editable source of truth + versioning [Phase 3] — the keystone. In-app markdown edit → S3 re-publish (D1) → incremental section re-embed → section-level atomic stage-then-flip → an every-save changelog of edits and comments (D2).

  • Acceptance (load-bearing): during a section edit, retrieval never returns a missing or un-embedded section (the atomicity invariant, tested under concurrent reads); unchanged sections' chunks + annotations are untouched; the changelog shows doc-state + comment-state at each version.
  • Gate: the stage-then-flip mechanism (granularity + how it extends the shipped superseded flag / supersedeAndFlip) must be designed and locked before build — the single highest-risk item.

M6 — Curated MCP authoring surface + a tool-testing harness [Phase 4]. A curated MCP authoring toolset (document edit + annotate/review), reusing the Wave-2 write authz and fixing the D4 bug list. Built behind a local testing harness that exercises the tool surface against real authoring tasks, measures whether an agent drives the tools correctly, optimizes the toolset (names/descriptions/params/granularity), and irons out bugs before any prod ship.

  • Acceptance: the harness demonstrates an agent completing representative authoring/review tasks via the tools at a defined success rate; the fixed-on-port issues carry regression coverage; the curated tool set is justified against the harness results (not a blind port).
  • Note: the harness is local with no prod dependency, so this workstream can start early / run in parallel and feed tool-shape decisions back into the M1 domain design.

M7 — Corpus migration (one-time) [migration]. Migrate the existing Foundry docs (git-backed markdown) into S3-backed Autri docs so the real design-doc corpus is editable/reviewable in Autri. No ongoing git sync.

  • Acceptance: the corpus is reviewable + editable in Autri with spot-checked fidelity. Annotation migration policy (re-anchor existing threads vs. start fresh) is decided in Phase 0.

Should-haves (v1.x fast-follow)

  • Latency UX / synchronous re-embed path — explicit "saving / re-indexing" states are v1; a faster synchronous single-section re-embed path can trail.
  • Sophisticated edited-section re-anchoring — v1 floor is "flag on edit"; fuzzy carry-forward into the changed span (G6) can trail.

Out of scope (v1) — explicit, with why

  • GitHub integration / bridge — dropped entirely. No git relationship; M7 is a one-time import, not a sync.
  • Real-time collaboration — v1 assumes one editor at a time; concurrent multi-editor is a separate effort.
  • PDF / non-markdown annotate-only — markdown-first; PDFs lack a char source for anchoring.
  • Named version snapshots — the every-save changelog is v1; explicit named tags are a fast-follow.
  • Tiering / packaging — a go-to-market decision, not a build gate.
  • Per-document visibility / public reads — cut by D5; all access at the Autri level.

Load-bearing design locks (resolve in Phase-0 build planning)

Three locks were owed before build. Lock 1 (M5) is RESOLVED — designed + locked with Dan, session 27 (2026-06-29). Locks 2–3 remain, each owed before its phase.

  1. ✅ RESOLVED (session 27) — M5 section flip. The keystone. The shipped whole-doc machinery (supersedeAndFlip in retrieval/src/documents.ts; the chunks.superseded boolean from migration 027; the partial hot index chunks_embedding_live_idx WHERE superseded = false) extends to section granularity — and the locked mechanism is simpler than the "stage-then-flip" working name implied (the staging turned out unnecessary):

    • Two states, not three. Reuse the existing superseded boolean (live / retired). No "staged" state. A staging window only exists if you insert chunk rows, then embed them — the order the ingestion worker uses. The in-app edit path does the opposite: embed first, then insert. The changed section's vectors are computed before the database transaction, so new chunks are born with embeddings already attached and there is never a live-but-un-embedded window for a third state to cover.
    • The flip = one atomic transaction, scoped by (document_id, unit_index) — a markdown section is a document_unit, and chunks already carry unit_index. Under a document-row FOR UPDATE lock: mark the old unit's chunks superseded = true, insert the new unit's chunks superseded = false with embeddings inline. Same atomicity + idempotency invariant as supersedeAndFlip, scoped to one unit (a failure mid-flip rolls back; retrieval never sees a missing or doubled section). Old chunks are preserved (history / inspector / dev-memory), never deleted; new chunks get fresh monotonically-increasing chunk_index values (the unique (document_id, chunk_index) index forbids reuse while the old rows survive).
    • content_hash (migration 026) gates the re-embed — only sections whose hash actually changed are re-chunked and re-embedded. A pure move (reorder, identical text) keeps its hash and re-embeds nothing.
    • Per edit tool call, inline + automatic. Each edit MCP call mutates the section → (if content_hash changed) re-embeds it → flips it, then returns. "Background" here means automatic and in-code — the agent never orchestrates it, there is no separate save/embed step to forget — not deferred-to-a-worker: the MCP/web runtime is Lambda, which freezes the instant the call returns and would kill any fire-and-forget background work. Inline gives read-your-writes: the section is live and queryable the moment the call returns.
    • Why per-call rather than coalesce-the-burst: correctness is identical either way (each flip is independent and atomic), so the only axis it moves is the number of embedding API calls — and content_hash keeps the common case free. Per-call also yields finer-grained history (every edit call becomes its own preserved version, not one per session). Simplest-first.
    • Documented escalation (deferred, not built in v1): if repeated re-embeds of a frequently-edited section start to cost real money/latency, introduce an explicit editing-doc-state that coalesces a burst of edits and re-embeds the dirty set once on finish; and only if embeds grow heavy enough to bust an in-call time budget, move that finish step onto a real queued worker (SQS → the ingestion worker). One escalation path, triggered by one signal (in-call embed cost).
  2. The MCP tool harness + curated toolset (M6). What the harness measures, what "good" looks like, which tools make the cut. Owed before M6 — but the harness is local with no prod dependency, so it can be stood up in Wave 1 and its findings feed the toolset cut.

  3. Annotation migration policy (M7). Re-anchor existing Foundry annotation threads onto the new anchor model, or start fresh. Owed before M7.

Build approach & sequencing

Built in-house through the normal hl/CSDLC process (D7): each phase scoped as an epic, red/blue-teamed, shipped via /hl:ship waves with standard QA gates. Off the critical path — after Brehob + launch. Natural order: M1 domain → M4 UI → M5 editing/versioning → M7 migration, with M6's MCP tool harness startable early/in parallel (local, no prod dependency) so its toolset findings inform the M1 domain shape. The attention cost is Dan's review/direction bandwidth, mitigated by sequencing off-critical-path and locking the M5 atomicity design before any Phase-3 build.

Review

🔒

Enter your access token to view annotations