Commit graph

5 commits

Author SHA1 Message Date
Shay
131e711054
feat(ADR-0172/tightening): three follow-ups — self-contained JSONL, widened dispatch, shape_category gap (#386)
Bundles three post-Tier-1 follow-ups into one PR (no scope change, no
new ADR — implementation tightening on the already-shipped corridor).

(1) Standalone JSONL self-containment
  teaching/math_contemplation_proposal.py
    + to_jsonl_record() — emits proposal_id + full evidence_pointers
      (nested dicts including audit_row) + full reasoning_trace.steps
    + from_jsonl_record() — inverse; goes through build_proposal()
      so all invariants are re-validated; raises on proposal_id mismatch
    canonical_bytes() UNCHANGED (still the content-hash function;
    trace_id/proposal_id stability preserved)
  core/cli.py W3 lane now writes to_jsonl_record() output instead of
    canonical_bytes() — same compact-JSON encoding (sort_keys=True,
    ensure_ascii=False, separators=(",", ":"))
  workbench/readers.py loads via self-contained record fields directly;
    decompose_audit() re-run removed.  read_math_proposal() now reads
    reasoning_trace.steps and evidence_pointers from the JSONL record.

(2) Widened change_kind heuristic dispatch
  teaching/math_contemplation.py
    + _CHANGE_KIND_BY_PAIR table on (refusal_reason, missing_operator):
      (unexpected_category, pre_frame_filler_sentence) → matcher_extension
      (unexpected_category, multi_subject_sentence)    → frame_reclassification
      (unexpected_category, fraction_percentage_literal) → matcher_extension
      (unexpected_category, descriptive_frame_question) → frame_reclassification
      (unresolved_pronoun, pronoun_resolution)         → matcher_extension
    Single-key fallback (lexicon_entry/narrowness_violation/
    frame_unrecognized) retained for completeness.
    hypothesis-step justification text updated to reflect new table.

  Result on audit_brief_11.json:
    3  matcher_extension       (was 0)
    2  frame_reclassification  (was 0)
    3  injector_sub_shape      (was 8)
    0  vocabulary_addition     (no unknown_word group ≥2 in train sample)

(3) shape_category structural gap
  MathReaderRefusalEvidence does not carry shape_category, so the
  proposal cannot derive it.  All proposals continue to emit
  ShapeCategory.UNCATEGORIZED with a structural-gap comment.  No
  invented values — handler dispatch decision (per ADR-0167-FOLLOWUPS
  §1) drives ratification routing today, not shape_category.

Tests
  + W1: 5 new tests (to_jsonl_record self-containment, round-trip,
    byte stability, proposal_id mismatch rejection, canonical_bytes
    unchanged invariant)
  + W2: 3 new pair-dispatch tests + real-audit change_kind distribution
    test + shape_category-uncategorized test
  + W3: 2 new tests (records are self-contained, round-trip via
    from_jsonl_record); existing byte-comparison test updated to use
    proposal_id ordering instead of canonical_bytes
  + W4: existing 6 tests updated to build JSONL via to_jsonl_record;
    + 1 new decoupling test that drops teaching.math_contemplation from
    sys.modules and verifies the workbench still loads + serves detail

Verification
  - core eval math-contemplation produces the expected 3/2/3 distribution
  - core test --suite teaching -q → 33 passed
  - core test --suite runtime  -q → 20 passed
  - All 57 ADR-0172 W1-W4 tests pass (49 existing + 8 new)

Determinism / invariants preserved
  - canonical_bytes() byte-stable (test pins this)
  - to_jsonl_record() byte-stable via sort_keys=True + no floats
  - wrong=0 invariant: proposals stay evidence-only; no auto-apply
  - ChangeKind Literal unchanged (4 values; no new ones invented)
2026-05-27 13:43:16 -07:00
Shay
93d244f4bf
feat(ADR-0172/W4): workbench math-proposals integration + e2e tests (#385)
Wires teaching/math_proposals/proposals.jsonl into the CORE Workbench
API (ADR-0160) alongside the existing cognition proposal queue:

workbench/schemas.py
  - MathReasoningStep, MathProposalSummary, MathProposalDetail,
    MathRatifyResult schemas

workbench/readers.py
  - MATH_PROPOSALS_JSONL + _DEFAULT_MATH_AUDIT_PATH constants
  - teaching/math_proposals added to ALLOWED_ARTIFACT_ROOTS
  - _HANDLER_DISPATCH table (vocabulary_addition→LexicalClaim; all
    others not yet implemented)
  - list_math_proposals(), read_math_proposal(), ratify_math_proposal()
  - read_math_proposal() re-runs decompose_audit() to recover full
    4-step reasoning trace (canonical_bytes only carries trace_id)
  - ratify_math_proposal() raises NotImplementedError with clear
    "handler not yet implemented: {change_kind}" for unhandled kinds

workbench/api.py
  - GET /math-proposals, GET /math-proposals/{id}
  - POST /math-proposals/{id}/ratify → _math_ratify()
    (vocabulary_addition→200/routed; unhandled→501 with loud message)

tests/test_adr_0172_w4_workbench_e2e.py — 6 tests:
  1. loads from JSONL
  2. renders domain:math badge (distinct from cognition /proposals)
  3. ratify-vocabulary_addition routes to LexicalClaim (200)
  4. ratify-matcher_extension fails loudly (501 "handler not yet
     implemented")
  5. all 4 trace steps visible in detail response
  6. no cross-contamination between math and cognition queues

teaching + runtime suites green (28 + 20 passed).

Brief-gap note: canonical_bytes() excludes proposal_id and serialises
evidence pointers as hashes only. D1 loader derives proposal_id via
sha256(line_bytes) and re-runs decompose_audit() to recover full trace
for read_math_proposal(). This works but means the JSONL cannot be
loaded without the original audit file. If a future wave needs
standalone JSONL loading, C1 should emit a richer format.
2026-05-27 13:16:23 -07:00
Shay
19506e9f60
feat(workbench/W-031): replay theater (ADR-0160 §Phase 6, deterministic-evidence UX) (#328) 2026-05-26 20:56:31 -07:00
Shay
a612038d41
feat(W-028): chat surface + trace drawer (#303) 2026-05-26 13:22:11 -07:00
Shay
8a24ebe726
feat(W-026): read-only workbench API (ADR-0160 Phase 1) (#292)
* feat(W-026): add read-only workbench API

* fix(workbench): harden read-only API review gaps
2026-05-26 10:16:35 -07:00