You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@stackbilt/surface extracts HTTP routes (Hono, Express, itty-router) and D1 SQL schema from a project's source. It powers the charter surface CLI command and is a prerequisite for the #113 repo-brief proposal.
Today, surface's API contracts are plain TypeScript interfaces (Route, SchemaTable, SchemaColumn). No runtime validation, no machine-readable schema. charter serve currently exposes zero surface-related MCP tools — agents can't invoke route/schema extraction through MCP.
This is the same shape @stackbilt/blast had before #110 — and the same Core-Out refactor resolves it.
commands/surface.ts — route argv through SurfaceInputSchema.parse. ZodError → CLIError mapping, same shape as blast's CLI adapter.
commands/serve.ts — register charter_surface tool following the charter_blast pattern (raw shape advertised, authoritative validation in the handler via SurfaceInputSchema.parse).
Zod → JSON-schema path: pass the Zod raw shape directly to server.registerTool. No new library.
Schema location: @stackbilt/surface. Zod becomes a runtime dep — same rationale as blast: programmatic consumers need the authoritative schema from the package surface, not from a downstream adapter.
Snapshot tests: structural assertions via SurfaceOutputSchema.parse on representative fixtures. No byte-identical snapshots.
Defaults as shared constants: any default input values (e.g. default include/exclude globs) live as exported constants referenced by both the schema's .default() and the primitive's in-function fallback. Same DEFAULT_MAX_DEPTH pattern used in blast.
#113 (repo-brief) composes blast + surface + config-file reads into a pre-digested brief. Blast's Core-Out shipped in 0.11.0 (#110); surface's is outstanding. Consuming un-Core-Out'd surface output in the brief would cause the brief's Surface section to reshape with each future refactor — exactly the drift the Core-Out pattern was designed to prevent.
Out of scope
Breaking changes to Route / SchemaTable / SchemaColumn shapes. Re-exported as z.infer<> aliases; no consumer breaks.
Additional framework support (Next.js routes, tRPC, etc.). Separate issue.
Context
@stackbilt/surfaceextracts HTTP routes (Hono, Express, itty-router) and D1 SQL schema from a project's source. It powers thecharter surfaceCLI command and is a prerequisite for the #113 repo-brief proposal.Today, surface's API contracts are plain TypeScript
interfaces (Route,SchemaTable,SchemaColumn). No runtime validation, no machine-readable schema.charter servecurrently exposes zero surface-related MCP tools — agents can't invoke route/schema extraction through MCP.This is the same shape
@stackbilt/blasthad before #110 — and the same Core-Out refactor resolves it.Proposal: Zod-Core-Out, applied to surface
Exactly the pattern proven in #110:
SurfaceInputSchema+SurfaceOutputSchemabecome the authoritative contracts in@stackbilt/surface.analyze(input: SurfaceInput): SurfaceOutputcomposes the existingextractRoutes+extractSchemaprimitives.charter surfaceCLI routes argv → schema →analyze→ human formatter.charter serveregisterscharter_surfaceas a callable MCP tool.Scope
@stackbilt/surface(additive):SurfaceInputSchemaandSurfaceOutputSchema.analyze(input: SurfaceInput): SurfaceOutputas the adapter entry point.Route,SchemaTable,SchemaColumninterfaces asz.infer<>aliases.zoddependency (^3.24.1), matching the blast decision. Update "Zero dependencies" README claim.@stackbilt/cli(additive):commands/surface.ts— route argv throughSurfaceInputSchema.parse. ZodError →CLIErrormapping, same shape as blast's CLI adapter.commands/serve.ts— registercharter_surfacetool following thecharter_blastpattern (raw shape advertised, authoritative validation in the handler viaSurfaceInputSchema.parse).Decisions locked upfront (per #110 review)
server.registerTool. No new library.@stackbilt/surface. Zod becomes a runtime dep — same rationale as blast: programmatic consumers need the authoritative schema from the package surface, not from a downstream adapter.SurfaceOutputSchema.parseon representative fixtures. No byte-identical snapshots..default()and the primitive's in-function fallback. SameDEFAULT_MAX_DEPTHpattern used in blast.Acceptance criteria
@stackbilt/surfaceexportsSurfaceInputSchema,SurfaceOutputSchema,SurfaceInput,SurfaceOutput,analyze.extractSurface,extractRoutes,extractSchema,formatSurfaceMarkdownexports preserved (OSS additive-only policy).charter surface <root>CLI output is structurally equivalent to current behavior.charter serveregisterscharter_surface;tools/listsurfaces the JSON schema with per-field.describe()strings.SurfaceOutputSchema.parse(analyze(...))succeeds on a representative fixture with both routes and D1 tables.packages/surface/package.jsonlistszodas adependency, notdevDependency.analyzevia synthetic fixtures. No child-process tests.Why this is a prerequisite for #113
#113 (repo-brief) composes
blast+surface+ config-file reads into a pre-digested brief. Blast's Core-Out shipped in 0.11.0 (#110); surface's is outstanding. Consuming un-Core-Out'd surface output in the brief would cause the brief's Surface section to reshape with each future refactor — exactly the drift the Core-Out pattern was designed to prevent.Out of scope
Route/SchemaTable/SchemaColumnshapes. Re-exported asz.infer<>aliases; no consumer breaks.(server.registerTool as Function)casts inserve.ts. Follow-up once the SDK ships cleaner typings (flagged in refactor(blast,cli,serve): Zod-Core-Out vertical slice (#109) #110 already).Related