7.5 KiB
Generic CaseBuilder foundation v1
architecture.md remains authoritative. This milestone assembles supplied data
deterministically. It performs no LLM calls, interpretation, hypothesis generation,
diagnosis, investigation, external research or project-specific adapter work.
Tester hypotheses remain supplied data, never generated or promoted to facts.
Explicit input contracts
The manifest may declare artifacts.case_inputs, pointing to a UTF-8 JSON index:
{
"format": "viano-case-inputs",
"format_version": 1,
"reports": ["original/report.data"],
"reproductions": ["original/reproduction.data"],
"context": {
"runtime": ["original/runtime.bin"],
"database": [],
"source": [],
"research": []
},
"attachments": []
}
Paths and extensions have no inherent meaning. Listed reports conform to
report-v1.schema.json, reproductions to reproduction-v1.schema.json, and the
index to case-inputs-v1.schema.json. Schemas are bundled offline Draft 2020-12
contracts. Unlisted files are preserved as unclassified inputs without parsing
or guessing their role. A missing index produces explicit data-quality gaps.
Invalid declared versions/contracts, duplicate JSON keys, repeated sources within
an index role, unsafe or absent references are controlled errors.
A report requires format viano-bug-report and format_version 1. Optional fields:
title, summary, observations, comments, tester_hypotheses, expected_behavior,
expected_behavior_complete and entities. Statements have nonblank text, optional
author and timezone-aware observed_at, and optionally a structured claim
with key and JSON value. Categories are producer-supplied, not inferred from
prose. Unknown extensions remain accessible in the preserved source file.
{
"format": "viano-bug-report",
"format_version": 1,
"title": "A generic observed problem",
"observations": [{"text": "The switch remains off", "author": "Tester A"}],
"tester_hypotheses": [{"text": "Perhaps a timing issue"}],
"expected_behavior": [{"text": "The switch turns on"}],
"expected_behavior_complete": false,
"entities": [{"type": "component", "id": "42", "roles": ["focus"]}]
}
A reproduction requires format viano-reproduction and format_version 1. Optional
fields: steps (strings), observations (human statements), events_ref, attachments,
facts and entities. Facts have a name and JSON value: they are supplied facts,
not independently verified technical findings. Events, attachments and all context
files remain opaque references with hashes/sizes. Supplied research stays separate;
no research is performed and no local implementation facts are inferred from it.
Canonical case and provenance
case-v1.schema.json defines format viano-case, format_version 1, builder_version
1, and the architecture's main blocks: case, bug, human_observations,
expected_behavior, reproduction, entities, runtime_facts, database_context,
source_context, research, data_quality, inputs.
Identity/project/revision come only from the manifest. Each statement/fact/entity has a source path and JSON Pointer with provenance kind. Human statements retain author/time. Observations, comments, tester hypotheses and expected behavior are separate. Record IDs use O/C/T/E/F namespaces; previous IDs remain stable by source path and pointer when inputs are appended. Facts use F0001 etc. Reproduction IDs follow source order. Integer entity IDs become strings; equal integer/string IDs of the same explicit type combine roles and retain every source. No domain types, relations or content are invented.
Expected-behavior completeness is missing, unspecified, reported_complete, reported_partial or conflicting. Reported completeness is an assertion by the reporter, not a sufficiency judgment. Different canonical JSON values for the same explicit claim key within observations or expected behavior are flagged with source references. Natural-language contradictions are not interpreted; comments and tester hypotheses never participate in fact or conflict inference.
Large context/events stay outside case JSON. Fact values over the inline limit
use value_ref (source path and JSON Pointer) instead of value; nothing is
truncated or replaced by a synthetic null. Old structured inputs are inherited
from the prior case's role inventory, hash-checked, and re-read from their immutable
originals. A returning index can add only new reports without losing old statements,
facts or provenance. Prior case files remain explicitly referenced. Incompatible
prior canonical case contracts are rejected instead of guessed.
Artifact and checkpoint integration
from viano_bug_analysis.case import CaseBuilder, CaseBuildError
from viano_bug_analysis.lifecycle import Workspace, CheckpointStore
store = CheckpointStore(Workspace("service-data"))
try:
result = CaseBuilder(store).build("case-A", "stable-package")
except CaseBuildError as error:
print(error.code, error.path, str(error))
Input must already be admitted. VALIDATED or REOPENED enters BUILDING_CASE through
a start checkpoint; existing BUILDING_CASE work continues there. Artifacts use
case/revisions/NNNN/case.json and case_summary.md. Revision paths preserve
append-only history; manifest pointers case and case_summary select the current
documents. Existing case files and unknown artifacts are never overwritten.
Case JSON, deterministic summary and the case-built completion checkpoint are
published together through PackageWriter. State remains BUILDING_CASE; construction
does not execute or start interpretation. Later phase orchestration advances it.
Summary is generated only from canonical JSON, adds no interpretation and escapes
supplied Markdown/HTML. render_summary is pure; CaseAssembler.assemble is
deterministic for the same validated snapshot.
Completion uses a stable step ID per builder version and analysis revision. Repeats check the input request hash, case contract and summary, reuse output and repair local metadata. Crashes after publication do not create another generation; unconfirmed work retries from the same snapshot. Changed payloads after completion require reopening with a new analysis revision. The request hash includes explicit source roles and all unclassified payloads, excluding known generated case outputs and checkpoint artifacts. Analysis revisions and package generations stay separate.
Prepared output calls CheckpointStore.advance(expected_generation=...) to reject
concurrent changes before committing. Identical confirmed requests remain replayable
with the old expected generation. Locks and this optimistic check prevent stale
prepared data from being committed over newer work. There are no external side
effects in construction.
Configurable resource defaults
CaseBuilderLimits holds operational policy, not immutable format limits:
| Limit | Default |
|---|---|
| Individual index/report/reproduction JSON | 1 MiB |
| Aggregate structured input JSON | 8 MiB |
| Structured input documents | 256 |
| Prior/canonical case JSON | 8 MiB |
| Summary bytes | 8 MiB |
| Inline fact value | 16 KiB |
Prior case JSON is bounded separately from the structured input budget. Package limits still apply to the archive/artifacts. Context is hashed in chunks rather than loaded as prose. Invalid attempts preserve all source/previous case files; they may retain a confirmed start checkpoint in BUILDING_CASE, allowing resumption after corrected sources and a new index are appended. Changing resource defaults does not rewrite a previously confirmed case.