Skip to content

feat(kcl-corpus): extract KCL into a training corpus - #40

Closed
willsun0 wants to merge 2 commits into
mainfrom
willsun0/kcl-corpus
Closed

feat(kcl-corpus): extract KCL into a training corpus#40
willsun0 wants to merge 2 commits into
mainfrom
willsun0/kcl-corpus

Conversation

@willsun0

@willsun0 willsun0 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Adds @foundry/kcl-corpus: extraction of FOUNDRY's KCL into a content-addressed
corpus for model training. Opening this for review rather than pushing to main
— it collects product data, so it should be a deliberate call, not a surprise.

Why a package rather than a script

AGENTS.md rule 2 keeps vendor SDKs out of domain logic. Extractors here are
pure functions over rows; everything writes through CorpusSinkPort, and the
Supabase adapter in ./sink is the only file importing a vendor SDK. Swapping
in a file dump or a dry run is a sink swap.

Extraction reuses normalizeCadDoc, parseKclModuleImports,
parseForeignImports, and parseCadParams from @foundry/cad rather than
re-implementing them, so the corpus cannot drift from what the app believes a
CadDoc means.

Two traps this encodes

  • CadDoc.script is a compat mirror of the active component. Counting it
    would duplicate one component per document, so extractDesignDoc reads
    components[] only. There is a test pinning this.
  • DesignDoc is last-write-wins (@@unique([projectId, branchId, kind])),
    so it holds head state with no revision history. Every intermediate revision
    is lost unless it passed through chat. Worth considering an append-only
    CadRevision table separately — it is the highest-leverage change for
    training-data volume.

What it does NOT collect

Prompts and other user-authored text are not extracted. That step is gated
on a legal basis for training use (terms coverage and/or a workspace opt-out)
plus redaction of emails, URLs, tokens, and names. The extractor for it is
deliberately absent, not merely disabled.

Project and branch ids are HMAC-pseudonymized before reaching the sink, with the
salt held outside the corpus database.

Storage

Target is a separate Supabase project, not FOUNDRY's own database. The corpus
lives in its own kcl schema, not exposed through PostgREST, RLS enabled with
no permissive policies — service-role only. Migration is checked in at
packages/kcl-corpus/migrations/0001_kcl_schema.sql.

Phase 1 (repo constants) has been run end-to-end against that project: 4
snippets, 4 occurrences, re-scrape verified idempotent, all three export views
queryable.

Validation

pnpm lint, pnpm format:check, pnpm typecheck (16/16), pnpm test (11/11
packages) all pass. 18 new tests.

Not done here

extractDesignDoc is implemented and tested against synthetic docs, including a
legacy v4 migration, but has not been run against a live database — none was
available.

Adds @foundry/kcl-corpus: pure extractors that turn FOUNDRY's KCL sources
into content-addressed records, behind a CorpusSinkPort so the Supabase
adapter is the only file importing a vendor SDK.

Covers repo constants, external sample sets, and project CAD workspaces.
DesignDoc extraction reads components[] and never CadDoc.script, which is a
compat mirror of the active component and would double-count it. Stock
starter content is hashed once and flagged so it can be held out.

Project/branch ids are HMAC-pseudonymized before reaching the sink.
Documents the two extraction traps (the CadDoc.script compat mirror, and
DesignDoc holding head state only) and states the governance bar that gates
chat/prompt extraction.
@willsun0

willsun0 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Closing — superseded by gofoundry-app/atlas-ingest.

Per Alan's call, the corpus work shouldn't live in FOUNDRY: the codebase gets too big, and this needs to run on its own schedule against its own warehouse rather than inside the app.

It's now a standalone CLI in atlas-ingest, with the Zoo generator and Supabase writer each behind a port, its own atlas schema (service-role only, separate from production), and 23 tests that run with no token and no network.

Nothing is lost by closing this — the extractors and the two KCL traps this PR documented (CadDoc.script being a compat mirror of the active component, and DesignDoc being last-write-wins with no revision history) carry over. The second one still caps what any corpus can capture: without an append-only revision table, only head state is recoverable, never the edit sequences.

@willsun0 willsun0 closed this Aug 6, 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