2 Commits

Author SHA1 Message Date
Edward Cheng-I Wu eb9e7bed17 feat(#127): v3.10 triangulation policy layer (PR-B) (#288)
Ships the contamination-triangulation policy layer deferred by v3.9.0 (#102):
opt-in strict modes that promote the advisory k=3 triangulation signal to a
non-acknowledgeable terminal HIGH-BLOCK at the citation-emission boundary.
Built on PR-A's canonical firm-rules + sync-lint base. Default behavior
(absent / all-advisory terminal_policies) stays byte-equivalent to v3.9.0.

Schema:
- New standalone shared/contracts/passport/terminal_policies.schema.json
  (passport-level, NOT entry-level). contamination_triangulation enum
  {advisory, strict, strict_articles_only}; temporal_integrity accepts only
  advisory (forward-reserved namespace).
- literature_corpus_entry.schema.json gains venue_type (closed enum incl.
  explicit unknown), venue_type_provenance (no _inferred values),
  venue_type_source (required iff trusted_source_declared). Bidirectional
  type/provenance pair dependency + one-way unknown-type rule.
- check_literature_corpus_schema.py validates a passport-level terminal_policies
  block before iterating entries.

Finalizer / formatter (agent prompts):
- pipeline_orchestrator_agent.md: sole policy evaluator. Stamps a fully-encoded
  policy_hash slug ONLY under a non-advisory passport; co-emits a TERMINAL-BLOCK
  token under strict (k=3) alongside the advisory suffix. strict_articles_only
  is a precision mode (DOI + journal/conference venue + declared provenance);
  DOI-less / unknown-venue stays advisory by design.
- formatter_agent.md: generic rule-11 HIGH-BLOCK refusal + STAMP-ONLY two-gate
  freshness check; never re-evaluates policy logic.

Firm rule / migration / adapters / lint:
- R-L3-2-A reworded to the broad default-advisory + opt-in-strict form
  (canonical single-source); contradiction guard added to check_firm_rules_sync.py.
- migrate_literature_corpus_to_v3_10.py deep-merge-seeds terminal_policies
  (idempotent, dry-run, no venue backfill).
- folder_scan / zotero / obsidian adapters declare venue_type.
- New check_v3_10_policy.py (alongside the v3.9.0 lint) + CI wiring in
  spec-consistency.yml and _ci_pytest_manifest.toml.

Docs: CHANGELOG Unreleased v3.10 entry; CLAUDE.md v3.10 Key Additions;
v3.9.0 / v3.9.4 spec superseded-framing notes.

Tests: 1857 passed / 3 skipped (+67 vs PR-A baseline of 1790, 0 regression).

Spec: docs/design/2026-05-31-ars-v3.10-policy-layer-rescope-spec.md

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 23:20:57 +08:00
Edward Cheng-I Wu 8261cfee4b refactor(#127): disambiguate R-L3-2/R-CIM rule IDs + canonical firm-rules sync lint (#285)
PR-A of the v3.10 triangulation-policy-layer split: a zero-behavior-change
base that removes the R-L3-2-A/B/C ID overload between the contamination
advisory rules (original holder, v3.7.3 §3.2) and the claim-intent-manifest
emission rules (borrowed the same ID in three writer-stage prompts).

- Rename the claim-manifest rules R-L3-2-A/B/C -> R-CIM-A/B/C in
  synthesis_agent, report_compiler_agent, draft_writer_agent, and the
  claim_intent_manifest schema description. Wording byte-identical except
  the ID token.
- Add shared/references/firm_rules.md as the canonical single source for the
  contamination R-L3-2-A..E blocks and the claim-manifest R-CIM-A..C blocks.
  The note for the contamination mirrors states plainly that their wording is
  NOT sync-checked yet (prose references, not full-block copies) — only their
  IDs are guarded; full wording-sync lands with the PR-B reword.
- Add scripts/check_firm_rules_sync.py: sync-checks the R-CIM mirrors against
  the canonical blocks (modulo the agent self-reference noun) and guards the
  disambiguation. The collision guard seals the full R-L3-2-A..E namespace out
  of claim-manifest surfaces, and _extract_section is fence-aware so a forbidden
  ID hidden after a fake heading inside a fenced example cannot escape the scan.
  Wired into CI via spec-consistency.yml + the pytest manifest. 19 tests.
- Spec: docs/design/2026-05-31-ars-v3.10-policy-layer-rescope-spec.md.

Part of #127 (policy layer lands in PR-B on this base). No runtime behavior
change; full pytest unchanged at 1790 passed / 3 skipped.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:30:16 +08:00