Skip to content

feat(spec): make spec types and required sections configurable - #77

Merged
jamesaphoenix merged 2 commits into
mainfrom
feat/configurable-spec-types
Aug 13, 2026
Merged

feat(spec): make spec types and required sections configurable#77
jamesaphoenix merged 2 commits into
mainfrom
feat/configurable-spec-types

Conversation

@jamesaphoenix

Copy link
Copy Markdown
Owner

Context

Spec structure was hardcoded: five spec types with fixed required markdown sections, enforced in parseMdDocSync as a hard parse failure. Teams could not express their own documentation conventions, define new spec types, or tailor the prompts agents receive when a section is missing.

Key observation driving the design: no markdown heading is load-bearing. tx spec discover, invariant sync, and FCI scoring locate embedded ```yaml blocks by fence and top-level key anywhere in the body, never by heading. What is load-bearing is the frontmatter contract and the block schemas, and those stay fixed.

What changed

Config-driven sections. Required sections now come from [spec.types.*] in .tx/config.toml. Each section carries a description (what belongs under the heading) and its own message (the lint prompt when it is missing); each type carries severity (error|warn|off), subdir, and an optional template file.

[spec.types.prd.section.problem]
heading = "Problem"
description = "The user or system problem being solved, with evidence."
message = "{name}: PRD is missing '# Problem'. State the problem first. {description}"

User-defined spec types. A [spec.types.rfc] table is enough to make tx doc add rfc scaffold, store, and lint that type like a built-in. DocKindSchema/MdSpecTypeSchema become validated identifiers instead of literal unions, and migration 048 drops the docs.kind allow-list (following the 046 rebuild pattern — FK-off, self-reference written with the final table name).

Lint-only enforcement. validateRequiredSections is gone from the parser. A missing heading no longer blocks tx doc add/update/sync/render or drift detection; tx spec lint reports it under a new Required Sections group at the configured severity, plus a Spec Type Config group for advisory warnings.

Bundled defaults. tx init writes the built-in definitions into every scaffolded config as active, editable TOML, generated from DEFAULT_CONFIG itself so the file and the code cannot drift (round-trip test). Re-running tx init on an existing project appends the new block additively via upgradeConfigToml.

Config-aware skills. Generated skills embed this project's headings, descriptions, and resolved lint prompts via a marker block, and a new spec-doc skill covers custom types. Skills also point at tx spec types --json as the live authority between syncs.

New commands. tx spec types [--json] (the machine-readable contract) and tx doc template <type> (preview a scaffold without writing).

Verification

  • Full suite: 5128 passed, 0 failures. Typecheck and lint clean.
  • New: test/unit/spec-type-registry.test.ts (13), test/unit/spec-section-lint.test.ts (12), test/integration/spec-types-config.test.ts (14 numbered CLI scenarios), plus 14 added to toml-config.test.ts.
  • doc-schema-validation scenarios 2, 5, and 10 were inverted from asserting parse rejection to asserting creation plus a lint finding.
  • Backward compatibility: a config with no [spec.types.*] resolves to the built-in defaults, asserted by a deep-equality round-trip test.

Specs

specs/prd/configurable-spec-types.md and specs/design/configurable-spec-types-design.md (11 invariants, all linked to tests via tx spec discover).

tx tests added 2 commits August 13, 2026 21:41
Spec structure was hardcoded: five spec types with fixed required
markdown sections, enforced as a parse failure. Teams could not express
their own documentation conventions, define new spec types, or tailor the
prompts agents receive when a section is missing.

Required sections now come from [spec.types.*] in .tx/config.toml. Each
section carries a description (what belongs under the heading) and its own
lint message, and each type carries a severity (error|warn|off), a
subdirectory, and an optional template file. Entirely new spec types are
supported and are scaffolded, stored, and linted like built-ins.

Enforcement moves out of the parser into tx spec lint, so a missing
heading no longer blocks tx doc add/update/sync/render or drift detection.
The frontmatter contract and the embedded yaml block schemas stay fixed,
because tx spec discover, invariant sync, and FCI scoring depend on them;
those blocks are located by fence and top-level key anywhere in the body,
never by heading.

The built-in definitions are written into every scaffolded config, and
tx init upgrades an existing config additively.

- config: [spec.types.*] parsing, listTomlSections, collectTomlTables
  (merges repeated tables instead of stopping at the first), and
  upgradeConfigToml for projects initialized before this change
- core: resolveSpecTypes registry, lintSpecSections, opened DocKind and
  MdSpecType to validated identifiers, migration 048 drops the
  docs.kind allow-list following the 046 rebuild pattern
- cli: tx spec types, tx doc template, and config/sections lint groups
- skills: generated skills embed this project's headings, descriptions,
  and resolved lint prompts, plus a new spec-doc skill for custom types

Specs: specs/prd/configurable-spec-types.md,
specs/design/configurable-spec-types-design.md (11 invariants, all linked
to tests via tx spec discover).
The dashboard's YAML renderer fell back to the literal "overview", which no
longer satisfies the branded DocKind type. Also exports asDocKind and the
built-in kind predicates from the core barrel so consumers outside core can
construct one.
@jamesaphoenix
jamesaphoenix merged commit 24d2095 into main Aug 13, 2026
2 checks passed
@jamesaphoenix
jamesaphoenix deleted the feat/configurable-spec-types branch August 13, 2026 21:15
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