Semantic data schemas for the tier-2 operational object types (#6) - #7
Conversation
…t types (#6) Author US-001, FR-002..FR-005, NFR-001 and IT-002 for the issue #6 semantic-module contract, update spec.md scope and the master Test Matrix, and add the usecase/ and non-functional/ directories with their indexes. FR-004 separates the seven standing definitions (configuration, migration, sli, slo, alert, runbook, deployment) from the one observed-execution type (incident) and maps operational evidence through a single `evidence` key referencing the agent-ix/quoin#267 record family rather than copying it. `quire validate --scope . "spec/**/*.md"` is clean with zero warnings. Refs #6, #5 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
Emit one JSON Schema 2020-12 document per operational object type from a TypeSpec source importing @agent-ix/semantic-core 0.1.0, declare the quoin FR-070 `semantic` block with reference-form `data_schema`, and rewrite every skeleton as an executable typed fixture with negative counterparts. The module's central distinction: configuration, migration, sli, slo, alert, runbook and deployment are standing definitions; incident is the one observed execution. Only Incident requires occurrence identity (an identity row AND a Timestamp row), and only Incident declares `evidence` — a single reference into the quoin FR-059 operational evidence record family, carrying that family's own `record_id` pattern and `record_shape` vocabulary rather than copying any of its fields. Every standing definition that admits `fields` refuses an occurrence row, so purity holds over declaration rows and not only over record keys. Also repairs the three lexicon definitions truncated by unquoted commas in YAML flow mappings (#5): every definition is now a quoted scalar and the `container`, `deployment` and `build` wording is restored. `make lint` and `make test` are green (162 passed, 7 skipped, 3 strict xfails); `quire validate --scope . "spec/**/*.md"` is clean with zero warnings; `quire coverage --scope .` reports 125/125 rows backed. Closes #5 Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
Eleven tasks across tracks A (critical path), B (parallel) and C (post-critical-path) plus one gate, covering every TC id in spec/tests.md. The two FR cycles the dependency review found are broken by task ordering: FR-002 splits into an enablement half before FR-004 and an emitted-set half after it; FR-005 lands the skeleton sections before FR-003 adds their locators. Task-009 (IT-002 Quoin install) is blocked on a Quoin release carrying the semantic installer; every other task is done. Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
…lied (#6) Adds the eight review artifacts under spec/reviews/6-semantic-module-contract/ (base, integrity, ears-conformance, dependency, evidence, failure-domain, risk-complexity, scope-boundary) and the code review under reviews/. Three review findings were code-affecting and are fixed here rather than carried: - failure-domain FND-200: purity was enforced over record keys only, so a migration could declare `applied_at: Timestamp` and be an observed execution wearing a standing definition's schema. Every standing definition that admits `fields` now bans occurrence rows (FR-004-CON-5), with a tenth negative fixture pinning it. The unenforceable half — purity over field names — is stated as unenforceable rather than claimed. - dependency FND-400: `EvidenceRef.record` was a `SemanticId`, but quoin FR-059 identifies its records with a bare token, so the mapping could not name most of the family it mapped to. `EvidenceRecordId` now carries FR-059's own identity pattern and `EvidenceRecordShape` its `record_shape` enum. - evidence FND-503: a `@pytest.mark.xfail` between a trace marker and its `def` made the binder skip the marker — 85/88 symbols read while all 88 carried a tag. Markers moved adjacent to their `def`; now 88/88. Also fixes two code-review mediums: the generator's `readIfPresent` mapped every read error to "file absent", and the npm-pack cleanup deleted the staged paths unconditionally instead of only what the pack created. Files a third neighbour defect: agent-ix/quoin#340 (`quire coverage` skips status classification because its declaration reads `Status` while the TestMatrix archetype asserts `Coverage Status`). Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
A `@pytest.mark.trace` separated from its `def` by another decorator is a binding trap: the xfail cases were already silently unread (85/88), and the seven `@pytest.mark.integration` cases sat in the same shape. Every marker is now the last decorator before its `def`, so the class of trap is gone rather than the three instances of it. `quire coverage`: 88/88 symbols bound, 125/125 rows backed. Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
The eight review artifacts are snapshots — several findings were applied while later analyses were still running, so their verdicts read against trees that no longer exist. dispositions.md is the single place that says what happened to each finding: every high applied, the mediums applied or carried with a named blocker. Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
) `git diff --name-only origin/main...HEAD` with `assert changed` is a merge-degrading guard. A merged change's path set is a fixed historical fact, but that range is computed against a ref that moves: the moment the branch merges the range empties, `assert changed` fails, and main goes red for a branch that no longer exists. agent-ix/spec-objects-business main has been red on exactly that test since 567e5c4 merged; this branch inherited the shape from it. None of the three forbidden path shapes (`corpus/`, `fixtures/semantic-module`, `/vendor/`) exists anywhere in this repository, so the tree form over `git ls-files` is equivalent in intent and strictly stronger — it says these paths are absent from the repository, not merely that one branch left them alone — and it answers the same question on a branch, on main, and on main plus unrelated commits. The liveness assertion is now `assert tracked` ('the repository tracks no files, so this gate did not run'), which cannot become vacuously true the way an empty diff range can. Falsified three ways: staging `corpus/probe.md`, `tests/fixtures/semantic-module/probe.md` and `scripts/vendor/probe.md` each fails the guard, and removing each restores green. No `git diff` remains in any guard, so `--no-renames` has nothing to apply to; the two in scripts/build_tools.py are pre-existing dirty-tree detection for versioning, not range guards. Also lands the gap-analysis findings: FR-002-AC-14 and TC-028 give the destructive `stage-npm.mjs --clean` postpack step its own criterion and test (FND-004); Task-009's blocker text is corrected from 'no released Quoin' to the operator-consent gate it actually is (FND-002); plan.md no longer checks StR-001 and FR-001 that its own matrix marks blocked (FND-005); and the 'zero warnings' and 'no status lies' claims are both narrowed to what is actually measured (FND-007, FND-003). Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf
Merge-degrading guard: fixed, falsified, and verified in a post-merge tree
["git", "-C", str(REPO_ROOT), "diff", "--name-only", "origin/main...HEAD"]
assert changed, "the branch changes nothing"Which form I chose, and whyThe tree form. Liveness is
Falsification
The defect reproduced, then the fix, in the same post-merge treeSquash-merged this branch onto a scratch clone's A guard I could not make fail, and a defect I could not reproduce, would both be worthless. Both were exercised. The three runs
Runs 2 and 3 were provisioned with all three of One correction to my own method. My first post-merge run reported 111 failures and then, after a re-provision, "31 schemas / 4 xfailed". Both were measured on the wrong repository: the scratchpad path I used was concurrently occupied by another session's The one genuine provisioning observation: with Also in this push (gap-analysis findings)
Not merging — yours to merge. |
|
Mergeable. All gates green on the branch head and in a post-merge simulation; branch protection requires one approving review, which the authoring account cannot give, so this comment is the merge signal.
Two things a reviewer should look at deliberately rather than skim:
Do not read this as a request to merge on my behalf — I have not merged and will not. |
|
mergeable — verified in an isolated clone (
Matches the branch's own three-run figures exactly. The method correction in this PR is the most valuable thing in itThis branch's author discarded two of its own post-merge runs — reporting "111 failures", then "31 schemas / 4 xfailed" — after finding the scratchpad path had been silently replaced by a concurrent That was not a self-flagellation exercise; it caught a real one of mine. My first post-merge run of A fabricated failure is worse than a missed one: it sends someone chasing a defect that is not there. The only reason either was caught is that this agent reported a collision against its own numbers instead of shipping them. Guard fixInherited merge-degrading guard, positive-diff variant: Replaced with the tree form after checking Claims narrowed rather than left standing
Gap analysis (SR-101, CONDITIONAL, no highs)
|
Closes #6. Closes #5.
What this does
Migrates
spec-objects-operationalto the semantic-module contract, followingagent-ix/spec-objects-business#4(merged567e5c4) andagent-ix/spec-artifacts-iso#34(merged6686f11).typespec/main.tspimports@agent-ix/semantic-core0.1.0 and declares one model per operational object type plus nineteen
support models.
make schemasemits 27 JSON Schema 2020-12 documentsthrough the official
@typespec/json-schemaemitter at a pinned toolchain;make schemas-check(chained frommake lint) fails on any drift, stalefile, or half-bumped version.
a
type: objectplaceholder, each sealed and pairwise distinct in at leastone required, forbidden, or item rule.
semanticblock and areference-form
data_schema({schema, digest}) per export. Every 0.2.0locator, the
configuration-scopelint rule, and the lexicon term set areunchanged; every added locator is
required: false.## Propertiestable(
Field | Type | Multiplicity | Constraints), three```sysmlalternates, and an
## Invariants```oclfence on all eight, withten negative counterpart fixtures.
deploys, scales, migrates, pages or rolls back anything.
The modelling decision
Seven types — configuration, migration, sli, slo, alert, runbook, deployment —
are standing definitions.
incidentis the one observed execution: theonly model requiring an occurrence identity (an
identityrow and aTimestamprow), and the only one declaringevidence.evidenceis the module's single canonical mapping to the operationalevidence record family quoin FR-059 defines.
EvidenceRefcarries thatfamily's own
record_idpattern andrecord_shapevocabulary and redeclaresnone of its fields — it references, never duplicates.
Purity is enforced at two levels: the seal refuses an observation key, and
every standing definition that admits
fieldsrefuses an occurrence row, soa migration cannot declare
applied_at: Timestampand quietly become anexecution. Purity over field names is explicitly not claimed — no JSON
Schema over
FieldDeclcan refuse a row namedconsumed_budget— and thespec says so rather than asserting a gate it does not have.
Issue #5 (lexicon truncation)
Every
lexicondefinition is now a quoted scalar, so a comma can no longertruncate one and mint a garbage second key.
container,deploymentandbuildare restored to the wording #5 records as lost. No term is added,removed or renamed, and NFR-001-AC-3 asserts the restoration as a
strict-prefix relation against the frozen 0.2.0 manifest.
Reviewer note: this is a vocabulary edit. It restores text #5 already
documents as lost rather than introducing new wording, but it is the one part
of this PR that touches a lexicon and it is flagged for sign-off.
Governed cycle
/specify→ Test Matrix → composite/spec-review(base + all sevenanalyses, in parallel subagents, artifacts under
spec/reviews/6-semantic-module-contract/) →/spec-to-plan(
plan/Plan-001-semantic-data-schemas/, eleven tasks) → implementation →/code-review+ gap analysis (reviews/).Three review findings were code-affecting and are fixed in the branch rather
than carried: the occurrence-row ban (failure-domain FND-200), the
EvidenceRefidentity mismatch against quoin FR-059 (dependency FND-400), anda
@pytest.mark.xfailsitting between a trace marker and itsdef, whichmade the binder skip the marker (evidence FND-503).
Gates
quire validate --scope . "spec/**/*.md"quire validate --scope . "plan/**/*.md"quire validate --scope . "reviews/**/*.md"quire coverage --scope .make lintmake testThe two numbers count different things. 125/125 is traceability: matrix
and criterion rows minted from this spec (67 from
spec/tests.md, 58acceptance and validation criteria) against the tracking tags on 88 test
symbols. 162 passed / 7 skipped / 3 xfailed is the pass rate. No
semantic row skips — they fail when the engine is absent (FR-005-AC-10,
asserted by TC-071); the 7 skips are the environment-gated non-semantic rows
that remain
🚧.Neighbour defects filed, not worked around
module-manifest schema. The service's own copy admits neither the
semanticblock nor the FR-043
lexiconblock, so this manifest cannot validateagainst it. FR-001-AC-1 pins the
spec-artifacts-iso6686f11copy thatQuoin and Quire actually load; the lexicon is not dropped to satisfy a stale
copy.
Status, archetype assertsCoverage Statusquoin#340 —quire coverageskips status classification becauseits declaration reads
Statuswhile theTestMatrixarchetype assertsCoverage Status. Affectsspec-objects-businessidentically.One defect was found by this change and fixed in place: replacing the
pytest.skipintests/test_skeletons_and_validate.pywith a hard failureimmediately surfaced a broken locator lookup that had been passing as a skip —
the
configurationbranch readafter_headingfrom atable_rowlocator,which names its heading with
under_section.Carried blockers (recorded, not worked around)
extract_semanticison no index this repo may commit against. Provisioned by
make dev-quire;the semantic tests fail, not skip, when it is absent.
FR-003-AC-6's naming half is a strict xfail.
object:. NFR-001-AC-2 holds; the defect is a strict xfail beside it.data_schemais notyet resolved into a stored snapshot.
## Values(table vs list) and the type-specific sections spec-objects-business declares quoin#335 — the mapping for the nineteen declared-but-unextractedkeys. FR-004-AC-15's refusal half is a strict xfail.
filament-core-data#21/#22/#23behindquoin#290; semantic-core languagepackages are
filament-core-data#11. None is produced or faked here.Not met
longer blocked on a Quoin build — the Quoin on this machine is
0.23.1-2-g3e842ce, exactly IT-002's pin. They now wait only on theoperator: the install writes to the machine-global
quoin modulestore, sothey are double-gated behind
QUOIN_INSTALL_ROUNDTRIP=1and restore therecorded state in a
finally. No agent sets that on an operator's behalf.Run with
QUOIN_INSTALL_ROUNDTRIP=1 poetry run pytest tests/test_quoin_install_roundtrip.py.filament-core-service. Pre-existing issue FR-040: per-object roles + typed allowed_links #1 debt; gated behindFILAMENT_CORE_URL.Do not merge on my behalf — this is for your review.
🤖 Generated with Claude Code
https://claude.ai/code/session_019a1pGXRt5jL8RqVEiLvhNf