5.1 KiB
Workspace preprocessing CLI contract
thothctl workspace is a closed native host interface. Only the seven paths below are representable; there is no passthrough, shell, arbitrary child argv, or host-selected bootstrap run ID.
workspace inspect --workspace ID [--json]
workspace preprocess dwh --workspace ID [--resume RUN] [--json]
workspace schema suggest-fks --workspace ID [--from-sql FILE]... [--assume COLUMN=TABLE]... [--output FILE] [--json]
workspace schema check --workspace ID --resume RUN [--annotations FILE --reviewed-candidates sha256:HEX] [--json]
workspace index-schema --workspace ID [--json]
workspace preprocess evidence --workspace ID [--dry-run] [--resume RUN] [--json]
workspace preprocess run --workspace ID [--resume RUN] [--json]
IDs are lowercase [a-z][a-z0-9-]{2,62} and outer run IDs are exactly 32 lowercase hexadecimal characters. --from-sql accepts at most 32 canonical regular non-symlink files, each at most 1 MiB and 16 MiB total. --assume accepts at most 256 values of 256 bytes, each matching column=table. Annotations are one canonical UTF-8 file at most 16 MiB. Existing output, links, hardlinks, directories, replacement races, and reparse points are refused with a generic unsafe-file error.
The bounded schema-v1 stdin envelope is exact: omitted fields are not equivalent to explicit zero, empty, or null fields. Its fields are, per operation (in addition to the always-required schemaVersion:1, operation, and workspaceId):
inspect: no additional fields.dwh:resumeonly when--resume RUNwas supplied.run:resumeonly when--resume RUNwas supplied.evidence:resumeonly when supplied, anddryRunonly when--dry-runwas supplied.suggest-fks:sqlonly when one or more--from-sqlfiles were supplied, andassumeonly when one or more--assumevalues were supplied. Eachsqlitem is exactly{basename, contentBase64, sha256}.check:resumeis required;annotationsandreviewedCandidatesare either both present or both absent.annotationsis exactly{basename, contentBase64, sha256}.index-schema: no additional fields.
No other fields, duplicate JSON value, host path, raw SQL, or raw annotation content are accepted. SQL and annotations use a logical basename, base64 bytes, and a declared sha256:<hex> digest. The request envelope is independently capped at 24 MiB (after JSON/base64 encoding), enough to carry the frozen 1 MiB-per-file/16 MiB aggregate raw ingress bounds; every supplied field/value must exactly match the command-derived envelope. Candidate responses may carry the internal hostExport (mediaType, sha256, contentBase64) only for suggest-fks; its object is strict (unknown fields rejected) and is always verified, even without --output: YAML media type (application/yaml or text/yaml), UTF-8, digest, and decoded size at most 700 KiB. It is removed from the public result and written exclusively only after result/run/identity validation. Output publication uses restrictive mode 0600 and refuses existing leaves, links, hardlinks, directories, replacement races, and reparse points.
The public result has schema version 1 and only these fields: status, code, workspace/revision/descriptor/operation identities, optional run and child run IDs, completed stages, counts, artifact identities, and warnings. Revisions/descriptors are 40-hex; run IDs are 32-hex; artifact digests are sha256:<hex>. Allowed statuses are succeeded, unchanged, dry_run, blocked, and failed. Allowed codes are ok, workspace_not_found, workspace_not_activatable, binding_missing, preprocessing_conflict, preprocessing_resume_mismatch, manual_review_required, evidence_materialization_required, effective_config_mismatch, semantic_index_incompatible, annotation_invalid, egress_policy_refused, and registry_bootstrap_recovery_conflict. succeeded, unchanged, and dry_run require ok and child exit 0. blocked requires one of manual_review_required, evidence_materialization_required, preprocessing_conflict, preprocessing_resume_mismatch, or registry_bootstrap_recovery_conflict, and child exit 3. failed requires a non-ok operational code other than those blocked-only codes, and child exit 1. A nonzero child exit is never accepted for another status/code combination. The public thothctl exit mapping is fixed independently of child details: 0 for succeeded/unchanged/dry-run, 3 for an expected blocked result, 2 for command grammar or unsafe host-file failures, and 1 for operational failures (including invalid child envelopes, output-limit failures, and child execution failures). Stdout is capped at 1 MiB after final human/JSON encoding and stderr at 64 KiB after sanitization; output is never allowed to exceed those bounds. In human mode, a registry_bootstrap_recovery_conflict result prints exactly Bootstrap recovery is ambiguous or corrupt; inspect the installation registry jobs. and prints neither a candidate export nor any run/candidate ID. Compose is invoked only as compose run --rm --no-deps --no-TTY workspace-maintenance ...; output never includes child stderr or secrets.