tools tier

tools-artifact-scaffold

Sprint/story artifact generator: allocates the next sprint number from a git-tracked registry (monotonic, no duplicates), writes docs/userstories/sprint-NNNN-<slug>.md with typed YAML front matter + named prose slots, and measures existing files for grammar/schema drift (US-3.96.7).

Sprint/story artifact generator: allocates the next sprint number from a git-tracked registry (monotonic, no duplicates), writes docs/userstories/sprint-NNNN-<slug>.md with typed YAML front matter + named prose slots, and measures existing files for grammar/schema drift (US-3.96.7).

Tiertools
Roleunclassified (baselined)
Pathcrates/tools/artifact-scaffold
Edition2021
Targetstools-artifact-scaffold, tools_artifact_scaffold
Public items16 across 0 modules
Tests17

What it is for

US-3.96.7: artifact scaffolder -- "the harness creates the object, AI fills slots." Two halves:

registry (docs/reference/sprint-number-registry.txt, monotonic -- read the current NEXT-TO-ALLOCATE value, write back current+1), and writes docs/userstories/sprint-<N>-<slug>.md with typed YAML front matter + named prose-slot headings (empty, for an AI/operator to fill -- this crate creates structure, never content). Filename carries identity only (the sprint number + a human-readable slug); state (status, dates) lives in the front matter, never re-derived from or encoded into the filename.

grammar/schema drift -- missing/malformed front matter, and a sprint number (parsed from the FILENAME, since most existing files predate front matter entirely) shared by more than one file. Existing files are counted, never renamed or rewritten.

Deliberately dependency-free path-walking: check reads docs/userstories/ directly via std::fs::read_dir rather than shelling out to git ls-files -- this crate has no existing git-tracked-walk helper of its own (that's tools-org-knowledge::corpus::walk, a different crate), and a plain directory listing is the AC's own framing ("GIVEN existing docs/userstories files").

Capabilities

crate root

US-3.96.7: artifact scaffolder -- "the harness creates the object, AI

Item
pub const TEMPLATE_REGISTRY_MAX_BYTES: u64
fn slugify(title : & str) -> String
fn render_story_markdown(front_matter : & StoryFrontMatter, sections : & TemplateSection,) -> Result <String, ScaffoldError>
pub const REGISTRY_PATH: & str
fn sprint_number_from_filename(file_name : & str) -> Option <String>
fn extract_status_line(text : & str) -> Option <& str>

CheckReport

US-3.96.7: artifact scaffolder -- "the harness creates the object, AI

Item
pub struct CheckReport
CheckReport :: fn as_metrics(& self) -> Vec <(& 'static str, usize)>
fn check(repo_root : & Path) -> std::io::Result <CheckReport>

ScaffoldError

US-3.96.7: artifact scaffolder -- "the harness creates the object, AI

Item
pub enum ScaffoldError
fn load_template_registry(repo_root : & Path) -> Result <Vec <TemplateSection>, ScaffoldError>
fn new_story(repo_root : & Path, title : & str, today : & str) -> Result <PathBuf, ScaffoldError>

StatusCategory

US-3.96.7: artifact scaffolder -- "the harness creates the object, AI

Item
pub enum StatusCategory
StatusCategory :: fn as_str(self) -> & 'static str
fn classify_status(line : Option <& str>) -> StatusCategory

StoryFrontMatter

US-3.96.7: artifact scaffolder -- "the harness creates the object, AI

Item
pub struct StoryFrontMatter

How to use it

No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.

Module structure

No public modules: the crate root is its whole surface.

Public surface

`crate root`

ItemWhat it is
pub const TEMPLATE_REGISTRY_MAX_BYTES: u64The template registry is a few kilobytes; anything past this is not it.
pub struct StoryFrontMatterTyped YAML front matter for a scaffolded story doc
pub enum ScaffoldError
fn slugify(title : & str) -> StringLowercase, ASCII-alnum-run slug: non-alphanumeric runs become one -, leading/trailing - trimmed
fn render_story_markdown(front_matter : & StoryFrontMatter, sections : & TemplateSection,) -> Result <String, ScaffoldError>Render a scaffolded story doc: YAML front matter + named, empty prose slots matching Gate 1's own required structure (user story, acceptance criteria, technical plan, tasks) -- this operationalizes an existing prose convention into something check can measure
fn load_template_registry(repo_root : & Path) -> Result <Vec <TemplateSection>, ScaffoldError>Sprint 4.47 U21: the sections of a story document, read from the rendering of story_template_section that corpus sprint-template-export writes
fn new_story(repo_root : & Path, title : & str, today : & str) -> Result <PathBuf, ScaffoldError>tools-artifact-scaffold new story --title "<t>": allocate the next sprint number, render the doc, write it to <repo_root>/docs/userstories/sprint-<N>-<slug>.md, and persist the registry's advance
pub const REGISTRY_PATH: & strRelative to the repo root: the git-tracked NEXT-TO-ALLOCATE registry.
fn sprint_number_from_filename(file_name : & str) -> Option <String>sprint extracted from a sprint-<N>-<slug>-sprint-doc.md filename, if it matches that shape (N may contain ., never - -- the first - after the sprint- prefix always ends the number)
pub struct CheckReportWhat one check pass found, as named metrics ("feeds run_measurement via corpus audit" -- US-3.96.6/3.96.8's job to persist these, not this crate's).
pub enum StatusCategoryMechanical classification of a userstory's free-text **Status:** line
StatusCategory :: fn as_str(self) -> & 'static str
fn extract_status_line(text : & str) -> Option <& str>Extract the first **Status:**-prefixed line's text, if present
fn classify_status(line : Option <& str>) -> StatusCategoryClassify one **Status:** line's text by keyword match, checked in this priority order (a line naming both "done" and "planned" -- e.g
CheckReport :: fn as_metrics(& self) -> Vec <(& 'static str, usize)>(metric_name, value) pairs, the exact shape corpus audit forwards into run_measurement (US-3.96.8).
fn check(repo_root : & Path) -> std::io::Result <CheckReport>Measure every <repo_root>/docs/userstories/*.md file

Re-exports. Exported here, defined elsewhere.

ExportDefined in
{TemplateSection,TEMPLATE_REGISTRY_PATH}operations_control_plane::story::{TemplateSection,TEMPLATE_REGISTRY_PATH}

Boundary

Reaches into operations.

Shares tier tools with 84 other crates: tools-advisory-reach, tools-archive-guard, tools-ask-ai-core, tools-ask-ais, tools-ask-gemini, tools-book, tools-book-report, tools-boundary-scan, … (84 total).

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)tools
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/tools/artifact-scaffold
Vocabulary in force (lexicon)current

Tier flow. Which tiers this crate's own edges cross.

flowchart LR
  n_tools["tools"] --> n_operations["operations"]

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`operations-control-plane`operationsnoalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
chrono^0.4serdenoalways
clap^4derivenoalways
serde^1derive, derivenoalways
serde_json^1noalways
serde_yaml^0.9noalways
thiserror^2noalways

Development, in this workspace.

CrateTierOptionalOnly on
`tools-cli-conformance`toolsnoalways

Build. None.

Depended on by. 1 workspace crate.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  n_tools_corpus["tools-corpus"] -->|uses| SELF
  SELF["tools-artifact-scaffold"]
  SELF -->|development| n_tools_cli_conformance["tools-cli-conformance"]
  SELF -->|runtime| n_operations_control_plane["operations-control-plane"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.

Targets

KindNameSource
bintools-artifact-scaffold`src/main.rs`
libtools_artifact_scaffold`src/lib.rs`

Error model

Error typeNamed by
ScaffoldErrorload_template_registry, new_story, render_story_markdown

Operational characteristics

PropertyEvidence
async public surfacenone detected
async runtimenone detected
database accessnone detected
network I/Onone detected
unsafe codenone detected
environment variablesnone detected

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.

1 workspace crate depends on this one: tools-corpus.

Verification

KindCount
Unit tests17
Integration tests0
Examples0
Doctests0

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
crate root1402

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc1416
Public modules with a //! block00
pie showData
    title Public items with rustdoc
    "Documented" : 14
    "No rustdoc detected" : 2

Metrics

MetricValue
Rust source files2
Source lines1101
Code lines862
Public API items16
Public modules0
Tests17
Examples0
Cargo features0
Direct runtime dependencies7
Workspace reverse dependencies1
pie showData
    title Public API by kind
    "constant" : 2
    "enum" : 2
    "function" : 8
    "method" : 2
    "struct" : 2
pie showData
    title Rust source composition
    "Code" : 862
    "Blank or comment" : 239

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All tools · Manual