Skip to content

feat: five-domain coherence engine — quality, meaning, signal, investiture, frames (closes #8 #9 #10 #11)#14

Merged
OriNachum merged 45 commits into
mainfrom
feat/five-domains
Jul 6, 2026
Merged

feat: five-domain coherence engine — quality, meaning, signal, investiture, frames (closes #8 #9 #10 #11)#14
OriNachum merged 45 commits into
mainfrom
feat/five-domains

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

What

The five-domain coherence engine, built per the converged spec + plan merged in #13. Implements #11 (restructure), #9 (signal), #8 (investiture), #10 (frames provenance), plus the user-approved additions (quality MVP, forecast, assess, signed resonance, frames inspect/diff + mixed-frame guard, signal collect). v0.5.1 → v0.6.0, 146 → 665 tests, all offline in CI.

Built via /assign-to-workforce: 18 tasks across 7 dependency waves, one agent per task in isolated worktrees, every merge TDD-gated (full suite green before and after). Zero merge conflicts — the plan's file-disjoint waves held.

The five domains

Domain Verbs Question it answers
quality (greenfield) quality score/compare Can this claim/context be trusted? Offline freshness/provenance/fidelity heuristics, visible confidence, honest can't-verify diagnostics
meaning (shipped 0.5.0) meaning score/compare/trend What semantic structure does this carry? Unchanged, plus additive domain/score_type/frame keys
signal signal trend/pattern/resonance/forecast/collect How do measurements behave over time/context? f′/f″, motifs, signed alignment (+=resonance, −=interference), labeled extrapolation, score-JSONs→series glue
investiture investiture score/compare Did meaning become a durable causal imprint? Estimated micro-investiture from meaning subdimensions, mode: estimated, unmeasured components explicitly null
frames frames inspect/diff Which semantic gauge produced this measurement? Provenance completeness, gauge-comparability, mixed-frame guard in the series loader

Plus coherence assess <file> — one multi-domain report with per-domain availability honestly reported (embed endpoint down ⇒ quality still answers, meaning/investiture listed unavailable, exit 0).

Compatibility (the merge gate)

  • Two-speed envelope: new nouns emit the full envelope (domain, score_type, scores, frame, diagnosticsdocs/envelope.md); meaning outputs gained only additive keys. Proven by golden tests (tests/test_additive_compatibility.py): stripping the three new keys yields the v0.5.0 shape byte-identically.
  • h15 verified — colleague's gate is additive-tolerant: colleague/coherence.py passes unknown payload keys through verbatim (_KNOWN_PAYLOAD_KEYS + pass-through loop), its tests assert subset-style, and test_unknown_payload_keys_pass_through_verbatim explicitly injects a frame key (colleague PR #298, merged). Optional colleague-side follow-up: refresh _LIVE_PAYLOAD from a 0.6.0 run.
  • meaning trend delegation is byte-identical, proven three ways: golden JSON snapshot from pre-refactor code, behavioral equivalence to signal.trend's functions, and a source-level test asserting the old helpers are gone.

Verified live

Smoke-tested end-to-end against the local embed gear: the emitted frame block reports the actual runtime endpoint (http://localhost:8001/v1, not the hardcoded default) — the h9 honesty condition observed in the wild. Offline: quality → collect → trend pipeline works; forecast's minimum-points guard exits 1 with hint on a 2-point series; frames inspect reports absent with a machine-readable reason on a rule-based measurement.

Docs

README repositioned around the five domains (claim quality named the first practical domain, not the whole product), docs/domains.md + docs/envelope.md + docs/signal-series.md, explain catalog +19 command paths +7 frame-vocabulary concepts, and a banned-terms language test keeping the docs to model-relative, anchor-defined framing.

Deferred (documented as planned extensions, not built)

Harmonic/wave/decay analyses (#9), gauge-robustness checks (#10), investiture trace (#8), experiment runner / doctor / certify / LLM-judge / routing output (#4/#6), freshness half-life prediction.

Closes #8. Closes #9. Closes #10. Closes #11.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk

  • coherence-cli (Claude)

OriNachum and others added 30 commits July 7, 2026 00:04
Adds the stdlib-only shared measurement envelope (domain, score_type,
scores, frame, diagnostics) that every new domain noun (quality, signal,
investiture, assess) will emit from day one. build_envelope/validate_envelope
round-trip a valid envelope unchanged; every violation (missing key,
non-dict scores, non-numeric score value, malformed diagnostic entry, etc.)
raises the dedicated EnvelopeError with a machine-readable code. An absent
frame is representable explicitly via frame=None (paired with a diagnostic)
or the null_frame() helper dict — never a missing key.

docs/envelope.md documents all five fields and the two-speed adoption rule:
new nouns emit the full envelope; existing meaning verbs keep their pinned
v0.5.0 shape and only gain additive top-level keys (domain, score_type,
frame), with the scores-nesting migration deferred to an explicitly
versioned future change.

20 new tests in tests/test_schema.py, all offline. Full suite: 146 -> 166
passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Add coherence/frames/{__init__.py,provenance.py} — build_frame() assembles
the frame provenance block (embedding_model, embedding_endpoint, anchor_set,
axis/axes, projection_method, score_type) for embedding-derived measurements.

embedding_model/embedding_endpoint are resolved at call time by reusing
coherence.meaning.embed's own COHERENCE_EMBED_URL/COHERENCE_EMBED_MODEL
resolution functions directly (not duplicated default literals), satisfying
t2's acceptance criterion that a monkeypatched env changes the emitted block
and defaults only appear when the env is unset.

Absent provenance re-exports coherence.schema.null_frame verbatim (asserted
via identity in tests) rather than reinventing the null-frame shape.

17 new offline tests in tests/test_frames_provenance.py; full suite 166 -> 183
passing.
Add coherence/signal as the source-agnostic series analysis layer's input
contract. coherence/signal/schema.py defines the series shape (optional
domain + ordered points; per point id/index/timestamp/values + optional
per-point frame) and load_series(), a robust loader that normalizes into
typed Series/SeriesPoint records plus a mutable diagnostics list.

- values are arbitrarily named numerics (caller-defined, never enumerated);
  missing/null/non-numeric values and booleans are skipped WITH a diagnostic,
  never a crash. bool is not numeric.
- per-point frames are surfaced on the normalized point and diagnostics is
  left appendable, so a later mixed-frame guard plugs in cleanly.
- only top-level structural failure raises SeriesError (machine-readable
  code), mirroring coherence.schema.EnvelopeError.
- series_from_meaning_trend() converts a real meaning-trend result into a
  valid series dict, proving source-agnosticism (same loader as hand-written).
- documented in docs/signal-series.md, referenced from the module docstring.

Tests: tests/test_signal_schema.py (37 tests, fully offline; the trend JSON
is built by driving the real trend engine with the synthetic embed_fn over
the recorded series fixtures). Full suite 166 -> 203, green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
First honest implementation of the "quality" coherence domain: fully offline,
deterministic, rule-based scoring of freshness/provenance/fidelity. Emits the
shared measurement envelope (coherence/schema.py) with domain=quality,
score_type=rule_based_heuristic, and an explicit null-frame
(rule_based_no_embedding_frame) — never a fabricated embedding frame.

Honesty contract:
- diagnostics NAME what rules could not verify (source_liveness_unverified,
  publication_date_unverified, quote_accuracy_unverified);
- absent signals lower per-component confidence with a diagnostic
  (no_dateable_statements / no_source_attribution / no_verbatim_signal),
  never fabricating a score;
- confidence is visible in the scores map as <component>_confidence.

- coherence/quality/heuristics.py: rule-based detectors + component scorers
- coherence/quality/score.py: assess() raw breakdown + score_text() envelope
- tests: 43 new, fully offline (socket-blocked fixture proves zero network)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Implement coherence/quality/compare.py mirroring the shape of
coherence/meaning/compare.py: before/after full quality envelopes plus a
delta map with signed floats for all score components (freshness, provenance,
fidelity and their _confidence entries). Delta = after - before for each
component.

- Fully offline: reuses score_text engine, threaded with reference_date
- Open component registry: delta keys mirror scores map keys
- Comprehensive test suite: 13 tests covering shape, delta arithmetic, edge
  cases, socket blocking (zero network access), and string/Path handling

All 276 tests pass (263 existing + 13 new).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Add coherence/signal/collect.py with shape-driven extraction that builds valid
series from N measurement JSONs of any domain (meaning, quality, investiture).

Extraction rule: if measurement has dict-valued `scores` → extract those (full
envelope path); otherwise harvest numeric leaves generically (top-level numeric
keys + numeric entries from any top-level dict like subdimensions).

API:
- collect(measurements: list[Mapping], *, ids: list[str] | None = None) -> dict
- collect_files(paths: list[str]) -> dict

Output per point: id, index, timestamp (None), values (extracted numerics),
frame (carried from measurement verbatim or None). Series-level domain: set
when all inputs agree on one domain string, else None (no error).

Zero numeric leaves in an input → raises SeriesError with code
"collect_no_numeric_values" (matches schema error convention).

All 25 new collect tests pass; full suite 288 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Add coherence/signal/resonance.py: pairwise Pearson alignment between a
series' numeric fields, reported as ONE signed metric. Positive alignment
is labeled "resonance" (streams reinforce), negative is "interference"
(streams conflict) — both derived from the sign of the same computation,
never two separate code paths. A neutral band (NEUTRAL_BAND = 0.1) around
zero labels weak alignment as neither.

Pairs with fewer than MIN_COMMON_POINTS (3) shared points, or with a
constant (zero-variance) field, are excluded with a diagnostic rather than
producing a NaN or fabricated correlation. A defensive non-finite-result
guard (CODE_NON_FINITE_CORRELATION) covers any other source of a
non-finite value.

Tests (tests/test_signal_resonance.py, 15 new, offline/numpy-only) cover
sign-carries-meaning (co-rising -> resonance, co-falling -> interference,
sign-symmetry under negation), exact +-1 correlation cases, the neutral
band, and every exclusion path (too-few-points, one/both constant fields,
disjoint fields, NaN-poisoned values bypassing the loader).
Add coherence/signal/pattern.py: motif detection over a loaded Series, per
numeric field. Six motifs (increasing, decreasing, plateau, spike, reversal,
stair_step), each a deterministic, tolerance-gated rule against the field's
own observed range — no learned/tuned parameters. Sparse fields are analyzed
over their present values only (gaps get a diagnostic, never interpolated);
series/fields with fewer than 3 usable points get an explicit
insufficient-points diagnostic instead of motifs.

tests/test_signal_pattern.py covers all 6 motifs on synthetic + counterexample
series (12+ assertions), short-series guards, sparse-field gaps, per-field
insufficiency, multi-field independence, and JSON-serializability.
Score/compare/trend JSON gains three ADDITIVE top-level keys — domain,
score_type, frame — while every pre-existing key stays byte-identical
(the two-speed envelope rule; docs/envelope.md). meaning keeps its pinned
v0.5.0 shape and only grows.

- score.py: DOMAIN/SCORE_TYPE constants; meaning_frame() resolves the frame
  from the runtime embed config at call time via frames.provenance.build_frame
  (axes = meaning + the five subdimensions); score() = clean v0.5.0 core
  (_score_v050) + the three keys; offline_result() is the offline-diagnostics
  path — an explicit null_frame (code embed_endpoint_unreachable), never a
  fabricated frame. score() still raises EmbedUnavailable (exit-2 path
  unchanged).
- compare.py: one shared top-level frame; before/after stay clean v0.5.0.
- trend.py: one shared top-level frame added; difference math untouched.
- CLI unchanged (it dumps the engine dict verbatim in --json mode).
- New tests/test_meaning_envelope_keys.py (9): runtime-resolved frame, golden
  subset byte-identity on recorded vectors, offline null-frame.
- Narrow additive-tolerance relaxations to existing meaning shape assertions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Point coherence/meaning/trend.py's f'/f'' differencing at the generic
coherence.signal.trend.first_difference / second_difference functions so
meaning trend is a dimension-specific wrapper (embed, label, assemble)
rather than a private reimplementation. Output is byte-identical: pinned
via full-result JSON goldens captured from the pre-refactor code
(recorded-vector + synthetic-embed series) in the new
tests/test_meaning_trend_delegation.py.

Removed the private _first_difference and _slot helpers; retained
_cosine_distance (drift distance), _second_unavailable_reason (labeling),
and the _derivatives_from_* helpers (imported by test_meaning_envelope_keys).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Add coherence/investiture/{__init__,score,compare}.py: the MVP measures
estimated micro-investiture (meaning that becomes causal, issue #8) as
meaning_score * agency * future_constraint * affordance, reusing
coherence.meaning.score.score() for every embedding/axis computation
(no duplicate embed path, same EmbedUnavailable exit-2 behavior).
score() output satisfies both the shared measurement envelope (domain,
score_type, scores, frame, diagnostics) and the issue-#8 JSON contract
(investiture_score, mode="estimated", components with the unmeasured
persistence_signal/integration_signal/behavioral_effect explicit nulls,
evidence) in one dict, since validate_envelope tolerates extra
top-level keys. compare() mirrors quality/compare.py's shape: before/
after are full score() results (each independently validating as an
envelope, frame passed through verbatim from meaning), delta is a
signed investiture_score plus the four numeric component deltas.

34 new tests in tests/test_investiture_{score,compare}.py, fully
offline via the shared synthetic hash embedder; full suite 423 -> 457
green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Adds coherence/assess.py: one verb (assess) that runs every applicable
domain (quality, meaning, investiture) against an artifact and returns a
single report. assess itself ships the full shared envelope (domain,
score_type, scores={}, frame=None, diagnostics) per the two-speed adoption
rule for new nouns, with domains/unavailable/artifact layered on top.

Quality always runs offline. Meaning/investiture need the embedding
endpoint; when it's down, both are listed in `unavailable` with a
machine-readable code + reason (investiture is skipped rather than
re-attempted, since it derives from meaning), and meaning's offline
rule-based diagnostics are still surfaced under
unavailable["meaning"]["offline_diagnostics"] — partial availability is a
normal, honest result, never silently dropped.

tests/test_assess.py adds 19 fully-offline tests (synthetic embed_fn) for
both acceptance criteria: endpoint down (quality + offline diagnostics,
meaning/investiture unavailable with reasons) and endpoint up (all three
domains present, unavailable empty). Full suite: 490 -> 509 passing.
OriNachum and others added 6 commits July 7, 2026 01:28
…n catalog

Wires the five merged domain engines into the CLI, mirroring the existing
meaning noun's pattern: quality (score/compare), signal (trend/pattern/
resonance/forecast/collect), investiture (score/compare, sharing meaning's
EmbedUnavailable exit-2 path), frames (inspect/diff, where absent/partial
provenance is a normal exit-0 result), and assess (a global verb; partial
domain availability is exit 0, never an error). Extends the explain catalog
with an entry per new noun/verb plus the eight frame-vocabulary concept terms,
and extends cli overview/learn to list all five domains.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
…n touch-up)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Deliverable 1 (tests/test_additive_compatibility.py): additive-only pre/post
diff proof. meaning score/compare/trend, driven offline with the synthetic
embedder, have {domain, score_type, frame} stripped and the remainder asserted
byte-identical to an independent v0.5.0 reconstruction; before/after and
per-point blocks carry no new keys. Scaffold verbs (whoami/learn/explain/
overview/doctor/cli overview) pin their established --json key sets unchanged.

Deliverable 2 (tests/test_five_domain_structure.py): a package home per domain
(quality/meaning/signal/investiture/frames + assess/schema) is importable;
quality/signal/investiture/frames/assess are registered CLI nouns (top-level
help, -h, explain); and the offline nouns never dial the embed endpoint
(localhost:8002) — proven by a socket guard plus the green offline suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
@OriNachum

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

qodo-code-review Bot commented Jul 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 5 rules
✅ Skills: doc-test-alignment

Grey Divider


Action required

1. Recorded vectors lack model tie-out ✓ Resolved 📎 Requirement gap ☼ Reliability
Description
Meaning frame provenance is derived from runtime env
(COHERENCE_EMBED_MODEL/COHERENCE_EMBED_URL) rather than the model/endpoint that produced the
committed recorded-vector fixtures, so offline replays can report incorrect frame provenance. This
violates the requirement to tie fixtures to a specific embedding model/version and guard against
silent drift.
Code

coherence/meaning/score.py[R130-151]

+def meaning_frame() -> dict:
+    """Build the meaning engine's frame provenance block for the current run.
+
+    The ``embedding_model``/``embedding_endpoint`` half is resolved from the
+    runtime embed config (``COHERENCE_EMBED_URL`` / ``COHERENCE_EMBED_MODEL``)
+    *at call time* by :func:`coherence.frames.provenance.build_frame`, so the
+    emitted frame follows the environment rather than a cached literal. The
+    ``anchor_set``/``projection_method``/``score_type`` half is this engine's
+    declared gauge, and ``axes`` are the axis names actually scored — the global
+    ``meaning`` axis plus every subdimension, read from
+    :data:`coherence.meaning.axis.DIMENSIONS` at call time so a newly registered
+    dimension is reflected here too.
+
+    Only meaningful when embeddings actually happened; the offline path uses
+    :func:`offline_result` (an explicit null-frame) instead of fabricating one.
+    """
+    return build_frame(
+        anchor_set=_ANCHOR_SET,
+        projection_method=_PROJECTION_METHOD,
+        score_type=SCORE_TYPE,
+        axes=list(axis_mod.DIMENSIONS),
+    )
Evidence
Rule 921863 requires recorded vectors be tied to the embedding model/version and guarded against
drift. The PR’s meaning frame is built from runtime env (meaning_frame()/build_frame()), while
the refresh script writes a metadata-free {text -> vector} fixture, so an offline replay can claim
any embedding_model regardless of which model actually produced the vectors.

Account for fixture risks: anchor changes and model version tie-outs
coherence/meaning/score.py[130-151]
coherence/frames/provenance.py[107-113]
scripts/refresh_meaning_vectors.py[90-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Offline meaning tests replay committed `recorded_vectors.json`, but the emitted `frame.embedding_model`/`frame.embedding_endpoint` are resolved from the current environment at runtime, not from the model/endpoint that generated the recorded vectors. This breaks the required model/version tie-out for fixtures and can silently misstate provenance.

## Issue Context
- `meaning_frame()` builds the frame by reading env-configured embedding model/endpoint at call time.
- `scripts/refresh_meaning_vectors.py` writes `recorded_vectors.json` as a plain `{text -> vector}` map with no metadata about the embedding model/version.

## Fix Focus Areas
- coherence/meaning/score.py[130-151]
- coherence/frames/provenance.py[107-113]
- scripts/refresh_meaning_vectors.py[90-105]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Noun --json ignored ✓ Resolved 🐞 Bug ≡ Correctness
Description
coherence signal defines --json on both the noun parser and each verb subparser, so when
--json is provided before the verb (e.g. coherence signal --json trend …), argparse can
overwrite the noun-level True with the verb parser’s default False, causing text output despite
requesting JSON. The same pattern appears in other noun groups (e.g. quality), making --json
placement-dependent and surprising.
Code

coherence/cli/_commands/signal.py[R265-274]

+    p.add_argument("--json", action="store_true", help=_JSON_HELP)
+    p.set_defaults(func=_no_verb, json=False)
+    noun_sub = p.add_subparsers(dest="signal_command", parser_class=type(p))
+
+    tr = noun_sub.add_parser(
+        "trend", help="Per-field f'/f'' differences, monotonicity, and volatility."
+    )
+    tr.add_argument("file", help="Path to the series JSON.")
+    tr.add_argument("--json", action="store_true", help=_JSON_HELP)
+    tr.set_defaults(func=cmd_trend)
Evidence
The noun parser adds --json, but each verb parser adds another --json with the same destination;
verb handlers read args.json to decide output mode, so losing the noun-level value changes the
emitted format.

coherence/cli/_commands/signal.py[259-274]
coherence/cli/_commands/signal.py[189-193]
coherence/cli/_commands/quality.py[212-225]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The noun-level `--json` flag can be lost when a verb subparser also defines `--json` with the same `dest` (`json`) and default `False`. This makes `coherence <noun> --json <verb> ...` unexpectedly emit text.

## Issue Context
`cmd_*` handlers choose JSON/text via `json_mode = bool(getattr(args, "json", False))`, so if the noun-level `--json` is overwritten during parsing, output mode is wrong.

## Fix Focus Areas
- Prefer one source of truth for `--json`, or ensure verb-level defaults don’t overwrite noun-level values.
- Recommended: keep `--json` on verbs for help visibility but set `default=argparse.SUPPRESS` on verb-level `--json` so it doesn’t override a previously-set noun-level `True`.
- Apply consistently across noun groups that define both noun-level and verb-level `--json`.

### Target code
- coherence/cli/_commands/signal.py[259-298]
- coherence/cli/_commands/quality.py[212-235]
- coherence/cli/_commands/investiture.py[180-210]
- coherence/cli/_commands/frames.py[206-230]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Collect crashes on non-objects ✓ Resolved 🐞 Bug ☼ Reliability
Description
coherence.signal.collect.collect_files appends json.loads() results without validating they are
objects; if a measurement file contains valid JSON that’s not an object (e.g. [] or "x"),
collect() later calls measurement.items() / measurement.get() and raises AttributeError.
This bypasses the intended SeriesError user-error path and yields a generic “unexpected” CLI
failure.
Code

coherence/signal/collect.py[R200-211]

+    for path_str in paths:
+        path = Path(path_str)
+        text = path.read_text(encoding="utf-8")
+        measurement = json.loads(text)
+        measurements.append(measurement)
+        # Use filename (without directory path) as ID
+        ids.append(path.name)
+
+    return collect(measurements, ids=ids)
+
+
+__all__ = ["collect", "collect_files", "SeriesError", "CODE_NO_NUMERIC_VALUES"]
Evidence
collect_files() does not ensure the parsed measurement is a mapping, and _extract_values()
iterates measurement.items() (and _get_domain() calls measurement.get()), which will crash for
non-mapping JSON types.

coherence/signal/collect.py[180-209]
coherence/signal/collect.py[51-91]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`signal collect` assumes every parsed JSON measurement is a mapping/object. Non-object JSON leads to `AttributeError` when `_extract_values()` uses `.items()` and `_get_domain()` uses `.get()`, rather than raising a controlled `SeriesError` with a clear code/message.

## Issue Context
`json.loads()` may return `list`, `str`, `int`, `float`, `bool`, or `None` for valid JSON inputs. The collect pipeline should treat these as user errors with a stable machine-readable code.

## Fix Focus Areas
- Add type checks after `json.loads()` in `collect_files()` and/or at the start of `collect()`’s loop.
- Raise `SeriesError` with a new code (e.g. `collect_measurement_not_an_object`) and a message naming the offending file/id.
- Add a test case for a non-object measurement JSON (e.g. `[]`) asserting exit code 1 and structured error.

### Target code
- coherence/signal/collect.py[51-100]
- coherence/signal/collect.py[180-209]
- tests/test_cli_signal.py[207-216]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

OriNachum and others added 2 commits July 7, 2026 01:45
…ldens float-tolerant across CPU/BLAS (structure still exact)

The golden literals were captured pre-refactor and reproduced byte-for-byte
on the capture machine; CI CPUs shift the last float ulp, so the assertion
is now a deep compare — exact keys/strings/nulls, floats at 1e-9 rel tol.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
…d in previous commit)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

feat: five-domain coherence engine (quality, meaning, signal, investiture, frames)

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds four new measurement domains plus assess, expanding CLI to five coherent domains.
• Introduces a shared measurement envelope with explicit frame provenance and diagnostics.
• Implements signal series analysis, frame inspection/diff, investiture estimation, and offline
 quality heuristics.
• Keeps meaning outputs backward-compatible via additive keys; delegates meaning trend differencing
 to signal.
• Expands offline test suite to 665, including additive-compatibility and byte-identical golden
 proofs.
Diagram

graph TD
    CLI["coherence CLI"] --> QualityCmd["quality noun"] --> QualityEngine["quality/score+compare"] --> Schema[("schema envelope")]
    CLI --> SignalCmd["signal noun"] --> SignalEngine["signal engines"] --> SignalSchema["series loader"] --> FramesCompat["mixed-frame guard"]
    CLI --> InvestCmd["investiture noun"] --> InvestEngine["investiture/score+compare"] --> Schema
    CLI --> FramesCmd["frames noun"] --> FramesEngine["frames/inspect+diff"]
    CLI --> AssessCmd["assess verb"] --> AssessEngine["assess report"] --> Schema

    InvestEngine --> MeaningEngine["meaning/score"] --> FramesProv["frame builder"]
    AssessEngine --> QualityEngine
    AssessEngine --> MeaningEngine
    MeaningEngine --> SignalTrend["signal first/second diff"]

    FramesEngine --> FramesDiff["frame diff"]
    FramesCompat --> FramesDiff

    subgraph Legend
      direction LR
      _cli(["CLI surface"]) ~~~ _eng["Engine module"] ~~~ _shared[("Shared contract")]
    end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Full immediate migration of meaning onto the shared envelope
  • ➕ Single uniform output shape across all domains
  • ➕ Eliminates the two-speed rule and its documentation/tests
  • ➖ Breaking change for existing consumers relying on v0.5.0 meaning JSON shapes
  • ➖ Requires coordinated rollout with downstream integrations (e.g., colleague)
  • ➖ Would invalidate additive-compatibility golden proofs
2. Per-domain contracts (no shared envelope module)
  • ➕ Each domain fully owns its JSON shape without shared dependency
  • ➕ Less shared-coupling across domains
  • ➖ Duplicates validation/diagnostic conventions across domains
  • ➖ Harder to build generic cross-domain tooling like assess/collect
  • ➖ Increases risk of drift in frame/diagnostic handling across domains

Recommendation: Keep the PR’s approach. The shared stdlib-only envelope plus the two-speed adoption rule is the best tradeoff under strict backward-compatibility constraints: new nouns can be consistent immediately, while meaning remains additive-only to protect existing consumers. The mixed-frame guard reuse of diff’s identity logic is also a strong choice to prevent silent gauge mixing.

Files changed (71) +13920 / -75

Enhancement (25) +4985 / -3
assess.pyAdd multi-domain assess report engine +234/-0

Add multi-domain assess report engine

• Implements 'assess(path)' to run quality always, meaning conditionally, and investiture derived from meaning, returning one report that explicitly lists unavailable domains with codes/reasons and preserves meaning offline diagnostics.

coherence/assess.py

__init__.pyRegister quality/signal/investiture/frames/assess commands +10/-3

Register quality/signal/investiture/frames/assess commands

• Updates CLI parser wiring to include the new noun groups and the assess verb.

coherence/cli/init.py

assess.pyAdd 'coherence assess <file>' CLI verb +151/-0

Add 'coherence assess <file>' CLI verb

• Adds assess CLI wiring, including '--reference-date' support, with exit code semantics treating embed unavailability as success (reported in JSON).

coherence/cli/_commands/assess.py

frames.pyAdd 'coherence frames inspect/diff' CLI noun +223/-0

Add 'coherence frames inspect/diff' CLI noun

• Adds frames CLI commands that load measurement JSON, inspect frame status, and diff gauge identity with clear exit codes and remediation.

coherence/cli/_commands/frames.py

investiture.pyAdd 'coherence investiture score/compare' CLI noun +203/-0

Add 'coherence investiture score/compare' CLI noun

• Adds investiture CLI commands delegating to investiture engines and mirroring meaning’s EmbedUnavailable exit behavior.

coherence/cli/_commands/investiture.py

quality.pyAdd 'coherence quality score/compare' CLI noun +235/-0

Add 'coherence quality score/compare' CLI noun

• Implements quality CLI wiring with '--reference-date' boundary defaulting to today and maps file/arg errors to user/env exit codes.

coherence/cli/_commands/quality.py

signal.pyAdd 'coherence signal' verbs (trend/pattern/resonance/forecast/collect) +298/-0

Add 'coherence signal' verbs (trend/pattern/resonance/forecast/collect)

• Adds signal CLI noun with five verbs, consistent JSON/text output handling, and error mapping for SeriesError/ForecastError.

coherence/cli/_commands/signal.py

__init__.pyIntroduce frames domain package exports +49/-0

Introduce frames domain package exports

• Adds frames package with re-exports for build_frame/null_frame, inspect/diff, and mixed-frame guard utilities.

coherence/frames/init.py

diff.pyAdd frame gauge-comparability diff engine +231/-0

Add frame gauge-comparability diff engine

• Implements 'diff_frames' comparing identity fields (hard) and axis/score_type (soft), with distinct codes for no provenance and asymmetric frame presence.

coherence/frames/diff.py

inspect.pyAdd frame provenance inspector (complete/partial/absent) +220/-0

Add frame provenance inspector (complete/partial/absent)

• Implements 'inspect_measurement' to classify frame completeness and surface missing fields or null-frame reasons without raising on absent provenance.

coherence/frames/inspect.py

provenance.pyAdd frame provenance block builder +118/-0

Add frame provenance block builder

• Implements 'build_frame' assembling the provenance block and resolving embed model/endpoint from runtime embed config (no duplicated literals).

coherence/frames/provenance.py

__init__.pyIntroduce investiture domain package +48/-0

Introduce investiture domain package

• Adds investiture package documentation and exports for score/compare engines.

coherence/investiture/init.py

compare.pyAdd investiture compare engine +112/-0

Add investiture compare engine

• Implements signed before/after delta over investiture_score and numeric components, excluding unmeasured components from delta to avoid fabrications.

coherence/investiture/compare.py

score.pyAdd estimated micro-investiture score engine +210/-0

Add estimated micro-investiture score engine

• Implements investiture scoring derived from meaning score/subdimensions, emitting full envelope plus issue-#8 fields with 'mode: estimated' and explicit nulls for unmeasured components.

coherence/investiture/score.py

__init__.pyIntroduce quality domain package +24/-0

Introduce quality domain package

• Adds quality package definition and exports for score/compare.

coherence/quality/init.py

compare.pyAdd quality compare engine +86/-0

Add quality compare engine

• Implements signed 'after - before' deltas across the open 'scores' map from quality envelopes.

coherence/quality/compare.py

heuristics.pyAdd offline quality heuristics (freshness/provenance/fidelity) +400/-0

Add offline quality heuristics (freshness/provenance/fidelity)

• Implements deterministic, regex-based component scoring with confidence and a diagnostic catalog; avoids network and datetime.now usage for reproducibility.

coherence/quality/heuristics.py

score.pyAdd quality envelope-emitting score engine +142/-0

Add quality envelope-emitting score engine

• Assembles component scores into the shared envelope with an explicit null-frame and visible per-component confidence in the scores map.

coherence/quality/score.py

__init__.pyIntroduce signal domain package +17/-0

Introduce signal domain package

• Adds signal package docstring and exports stub for series analysis layer.

coherence/signal/init.py

collect.pyAdd measurement-to-series collector +211/-0

Add measurement-to-series collector

• Builds a series from measurement JSONs by extracting numerics shape-driven (envelope scores vs meaning-style leaves) and carrying per-point frame provenance.

coherence/signal/collect.py

forecast.pyAdd extrapolative forecast engine with minimum-points guard +288/-0

Add extrapolative forecast engine with minimum-points guard

• Implements labeled next-point extrapolation per field using a linear-trend + recent-delta blend; raises ForecastError only when no field is forecastable.

coherence/signal/forecast.py

pattern.pyAdd per-field motif detection engine +415/-0

Add per-field motif detection engine

• Detects six motifs (increasing/decreasing/plateau/spike/reversal/stair_step) per numeric field with explicit diagnostics for insufficient points and gaps.

coherence/signal/pattern.py

resonance.pyAdd signed alignment engine (resonance/interference) +242/-0

Add signed alignment engine (resonance/interference)

• Computes signed Pearson correlation per field pair and labels by sign (resonance vs interference) with guards for insufficient common points and constant fields.

coherence/signal/resonance.py

schema.pyAdd series schema + robust loader with frame guard hook +493/-0

Add series schema + robust loader with frame guard hook

• Defines 'Series'/'SeriesPoint', 'load_series' with structured errors for structural failures and diagnostics for data issues, and wires in mixed-frame checking; includes helper to convert meaning trend output into a series dict.

coherence/signal/schema.py

trend.pyAdd generic trend differencing utilities and per-field analysis +325/-0

Add generic trend differencing utilities and per-field analysis

• Implements reusable 'first_difference'/'second_difference' and a trend report across all fields, handling sparse/short fields with explicit diagnostics rather than raising.

coherence/signal/trend.py

Bug fix (1) +122 / -0
compat.pyAdd mixed-frame guard for series loading +122/-0

Add mixed-frame guard for series loading

• Implements 'check_series_frames' to warn on mixed/partially-framed series points using the same identity definition as frames diff.

coherence/frames/compat.py

Refactor (3) +209 / -57
compare.pyAdd additive envelope keys to meaning compare output +23/-10

Add additive envelope keys to meaning compare output

• Keeps v0.5.0 before/after blocks clean while adding top-level 'domain'/'score_type'/'frame' keys derived from runtime embed config.

coherence/meaning/compare.py

score.pyAdd meaning frame provenance and offline_result; preserve v0.5.0 shape +129/-12

Add meaning frame provenance and offline_result; preserve v0.5.0 shape

• Introduces 'DOMAIN'/'SCORE_TYPE', 'meaning_frame()', and 'offline_result()' with explicit null-frame on embed failure; refactors to a '_score_v050' core then adds only the three additive keys.

coherence/meaning/score.py

trend.pyDelegate meaning differencing to signal.trend; add frame keys +57/-35

Delegate meaning differencing to signal.trend; add frame keys

• Removes private difference helpers and delegates to 'coherence.signal.trend' for f′/f″ math; adds additive 'domain'/'score_type'/'frame' keys, with golden tests proving byte-identical legacy output when stripped.

coherence/meaning/trend.py

Tests (32) +7019 / -12
test_additive_compatibility.pyProve meaning outputs remain byte-identical aside from additive keys +269/-0

Prove meaning outputs remain byte-identical aside from additive keys

• Golden tests strip 'domain'/'score_type'/'frame' from meaning results and assert byte-identical equality to independent v0.5.0 reconstructions; also pins scaffold verb shapes.

tests/test_additive_compatibility.py

test_assess.pyAdd assess engine tests for full and partial availability +218/-0

Add assess engine tests for full and partial availability

• Tests assess report shape and behavior when embed endpoint is unavailable (quality still runs; meaning/investiture reported unavailable with offline diagnostics).

tests/test_assess.py

test_cli_assess.pyAdd CLI tests for 'coherence assess' +210/-0

Add CLI tests for 'coherence assess'

• Verifies exit semantics (partial availability still exit 0), JSON output shape, and reference-date parsing and I/O error mapping.

tests/test_cli_assess.py

test_cli_frames.pyAdd CLI tests for 'coherence frames' +205/-0

Add CLI tests for 'coherence frames'

• Covers inspect/diff outputs and error handling for invalid JSON and non-object measurements, including absent provenance treated as non-error.

tests/test_cli_frames.py

test_cli_investiture.pyAdd CLI tests for 'coherence investiture' +216/-0

Add CLI tests for 'coherence investiture'

• Covers investiture score/compare output and EmbedUnavailable exit-path behavior.

tests/test_cli_investiture.py

test_cli_new_nouns.pyAdd CLI registration smoke tests for new nouns +209/-0

Add CLI registration smoke tests for new nouns

• Verifies quality/signal/investiture/frames/assess appear in top-level help, respond to -h, and resolve via explain paths.

tests/test_cli_new_nouns.py

test_cli_quality.pyAdd CLI tests for 'coherence quality' +220/-0

Add CLI tests for 'coherence quality'

• Validates score/compare behavior, JSON/text output, reference-date parsing, and file I/O error handling.

tests/test_cli_quality.py

test_cli_signal.pyAdd CLI tests for 'coherence signal' verbs +243/-0

Add CLI tests for 'coherence signal' verbs

• Covers trend/pattern/resonance/forecast/collect execution, schema errors, and forecast minimum-points behavior.

tests/test_cli_signal.py

test_docs_language.pyAdd docs language guard test +103/-0

Add docs language guard test

• Adds a banned-terms test to keep documentation model-relative and avoid mystical/absolute phrasing.

tests/test_docs_language.py

test_five_domain_structure.pyAdd structure tests for packages, CLI wiring, and offline-only guarantees +160/-0

Add structure tests for packages, CLI wiring, and offline-only guarantees

• Validates domain packages/modules are importable, new nouns are registered, and offline nouns do not dial the default embed endpoint (socket guard).

tests/test_five_domain_structure.py

test_frames_compat.pyAdd mixed-frame guard tests +189/-0

Add mixed-frame guard tests

• Tests partially framed and mixed identity warnings and ensures the guard’s identity definition matches frames diff.

tests/test_frames_compat.py

test_frames_diff.pyAdd frame diff tests +215/-0

Add frame diff tests

• Covers comparable/mismatch/no-provenance/asymmetric-presence codes and soft-difference reporting.

tests/test_frames_diff.py

test_frames_inspect.pyAdd frame inspect tests +239/-0

Add frame inspect tests

• Tests complete/partial/absent classification, missing field reporting, and null-frame detection.

tests/test_frames_inspect.py

test_frames_provenance.pyAdd frame provenance builder tests +258/-0

Add frame provenance builder tests

• Verifies build_frame assembly, axis/axes exclusivity, and runtime embed config resolution behavior.

tests/test_frames_provenance.py

test_investiture_compare.pyAdd investiture compare tests +190/-0

Add investiture compare tests

• Verifies signed delta behavior and excludes unmeasured components from deltas.

tests/test_investiture_compare.py

test_investiture_score.pyAdd investiture score tests +258/-0

Add investiture score tests

• Verifies formula, 'mode=estimated', explicit null unmeasured components, diagnostic emission, and envelope validity.

tests/test_investiture_score.py

test_meaning_compare.pyUpdate meaning compare tests for additive envelope keys +19/-4

Update meaning compare tests for additive envelope keys

• Adjusts tests to validate top-level 'domain'/'score_type'/'frame' without contaminating before/after blocks.

tests/test_meaning_compare.py

test_meaning_envelope_keys.pyAdd explicit tests for meaning’s additive envelope keys +309/-0

Add explicit tests for meaning’s additive envelope keys

• Pins presence and shape of meaning’s 'domain'/'score_type'/'frame' across score/compare/trend and asserts offline null-frame behavior.

tests/test_meaning_envelope_keys.py

test_meaning_schema.pyUpdate meaning schema tests for additive keys +16/-4

Update meaning schema tests for additive keys

• Minor test updates to reflect meaning’s additive envelope keys while keeping legacy fields unchanged.

tests/test_meaning_schema.py

test_meaning_score.pyUpdate meaning score tests for additive keys +11/-3

Update meaning score tests for additive keys

• Adds assertions for 'domain'/'score_type'/'frame' on meaning score output.

tests/test_meaning_score.py

test_meaning_trend.pyUpdate meaning trend tests for additive keys +8/-1

Update meaning trend tests for additive keys

• Adds assertions for 'domain'/'score_type'/'frame' on meaning trend output.

tests/test_meaning_trend.py

test_meaning_trend_delegation.pyAdd byte-identical golden proof for meaning trend delegation to signal +211/-0

Add byte-identical golden proof for meaning trend delegation to signal

• Pins pre-refactor trend output as goldens, proves behavioral equivalence to signal difference functions, and asserts source-level delegation (no private _first_difference).

tests/test_meaning_trend_delegation.py

test_quality_compare.pyAdd quality compare tests +298/-0

Add quality compare tests

• Covers before/after/delta shape and signed deltas over open scores map.

tests/test_quality_compare.py

test_quality_heuristics.pyAdd quality heuristics tests +258/-0

Add quality heuristics tests

• Covers all three heuristic components and diagnostic/confidence behaviors using fixed reference dates.

tests/test_quality_heuristics.py

test_quality_score.pyAdd quality score envelope tests +168/-0

Add quality score envelope tests

• Validates envelope shape, explicit null-frame usage, and confidence surfaced as score keys.

tests/test_quality_score.py

test_schema.pyAdd shared envelope validation tests +291/-0

Add shared envelope validation tests

• Tests build/validate round-trips and rejects malformed envelopes with machine-readable error codes.

tests/test_schema.py

test_signal_collect.pyAdd collect glue tests +516/-0

Add collect glue tests

• Tests numeric extraction rules (scores dict vs meaning-style leaves), domain consensus, and per-point frame carry-through.

tests/test_signal_collect.py

test_signal_forecast.pyAdd forecast engine tests +318/-0

Add forecast engine tests

• Covers extrapolation label, method behavior, sparse-field handling, and ForecastError when no fields qualify.

tests/test_signal_forecast.py

test_signal_pattern.pyAdd motif detection tests +224/-0

Add motif detection tests

• Covers the six motif detectors and insufficient-point behavior.

tests/test_signal_pattern.py

test_signal_resonance.pyAdd signed alignment tests +280/-0

Add signed alignment tests

• Covers resonance/interference labeling and guards for too-few points/constant fields/non-finite correlations.

tests/test_signal_resonance.py

test_signal_schema.pyAdd series loader tests +354/-0

Add series loader tests

• Validates normalization rules, diagnostics on malformed points/values/frames, and structural SeriesError cases.

tests/test_signal_schema.py

test_signal_trend.pyAdd trend engine tests +336/-0

Add trend engine tests

• Covers per-field differencing, monotonicity/volatility, sparse-field diagnostics, and empty/no-field cases.

tests/test_signal_trend.py

Documentation (8) +1583 / -2
CHANGELOG.mdDocument v0.6.0 five-domain release +19/-0

Document v0.6.0 five-domain release

• Adds a 0.6.0 entry summarizing new domains/verbs, envelope adoption, frame provenance, meaning trend delegation, and explain/overview expansions.

CHANGELOG.md

README.mdReframe README around five coherence domains +235/-2

Reframe README around five coherence domains

• Rewrites README positioning around the five domains, adds domain table and sections, and links to new docs for envelope and series schema.

README.md

learn.pyExtend learn command catalog with new verbs +45/-0

Extend learn command catalog with new verbs

• Adds quality/signal/investiture/frames/assess paths to learn output, including JSON payload path summaries.

coherence/cli/_commands/learn.py

overview.pyList five domains in 'coherence overview' +9/-0

List five domains in 'coherence overview'

• Updates overview verb listing to include new nouns and assess verb in help output.

coherence/cli/_commands/overview.py

catalog.pyExpand explain catalog for five-domain CLI surface +740/-0

Expand explain catalog for five-domain CLI surface

• Adds extensive explain text for new domains/verbs and frame vocabulary concepts, enabling 'coherence explain <path>' coverage.

coherence/explain/catalog.py

domains.mdAdd five-domain reference documentation +216/-0

Add five-domain reference documentation

• Documents each domain’s question, verbs, output shape, and honest limitations, including two-speed envelope treatment for meaning.

docs/domains.md

envelope.mdAdd shared envelope contract documentation +135/-0

Add shared envelope contract documentation

• Documents the five envelope fields, explicit frame absence conventions, schema API, and the two-speed adoption rule (new nouns vs meaning).

docs/envelope.md

signal-series.mdAdd series schema reference documentation +184/-0

Add series schema reference documentation

• Documents the signal series format, robust loader behavior, per-point value rules, and optional per-point frame provenance semantics.

docs/signal-series.md

Other (2) +2 / -1
coherence-cli__public.jsonlRecord five-domain build completion metadata +1/-0

Record five-domain build completion metadata

• Appends a public memory entry capturing the five-domain build completion, test count growth, and key compatibility/verdict notes.

.eidetic/memory/coherence-cli__public.jsonl

pyproject.tomlBump package version to 0.6.0 +1/-1

Bump package version to 0.6.0

• Updates project version from 0.5.1 to 0.6.0.

pyproject.toml

- merge implicit string concatenations (S5799) in overview/quality CLI verbs
- constants for duplicated literals in signal CLI (S1192)
- drop redundant JSONDecodeError from except clause (S5713)
- split validate_envelope and _extract_values into per-field helpers to cut
  cognitive complexity below the threshold (S3776); codes, messages, and
  extraction semantics unchanged (suite-pinned)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
Comment thread coherence/meaning/score.py
Comment thread coherence/cli/_commands/signal.py Outdated
Comment thread coherence/signal/collect.py Outdated
1. Recorded vectors gain a model tie-out (Qodo #1): recorded_vectors.json is
   now {metadata, vectors} — the refresh script stamps the embedding model/
   endpoint it actually ran against, the committed fixture is wrapped post-hoc
   with its known 2026-07-04 provenance (vector values unchanged), and the
   loader exposes load_recorded_metadata() with legacy-format fallback.
2. --json placement no longer matters (Qodo #2): verb-level --json flags use
   default=argparse.SUPPRESS via a shared helper so they never clobber a
   noun-level --json; applied to all six noun groups including meaning.
3. signal collect rejects non-object measurements (Qodo #3): valid JSON that
   is not an object raises SeriesError(collect_measurement_not_an_object)
   naming the offending file — exit 1, never an AttributeError.
4. Duplication: the per-noun file-error guard, remediation strings, and
   reference-date parsing move to cli/_commands/_artifact_io.py; the five
   noun modules keep only their domain-specific branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — commit 4519b36. The recording now carries the model tie-out: recorded_vectors.json is {"metadata", "vectors"}, the refresh script stamps embedding_model/embedding_endpoint from the env it actually ran against (plus date + script), the committed fixture is wrapped post-hoc with its known 2026-07-04 provenance (Qwen/Qwen3-Embedding-0.6B via the local gear; vector values byte-unchanged so the golden tests stand), and tests/_meaning_recorded.py exposes load_recorded_metadata() with legacy-format fallback. New tests: the refresh stamps env-resolved metadata, and the committed fixture must name its source model.

  • coherence-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — commit 4519b36, exactly as suggested: verb-level --json flags now use default=argparse.SUPPRESS (via a shared add_verb_json_flag helper in the new _artifact_io.py), so an absent verb flag never clobbers a noun-level --json. Applied to all six noun groups — quality, signal, investiture, frames, assess, and meaning (which had the same latent pattern). Regression tests pin placement-independence: coherence signal --json trend … and coherence quality --json score … both emit JSON.

  • coherence-cli (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

FIX — commit 4519b36. collect() now type-checks each measurement: valid JSON that is not an object raises SeriesError with the new code collect_measurement_not_an_object, naming the offending file/id — the existing guard maps it to exit 1 with a structured error instead of an AttributeError. Tests added at both levels: engine (collect([[…]]), collect_files on a [] file) and CLI (signal collect list.json → exit 1, stderr names the file).

  • coherence-cli (Claude)

…ity 17 -> under 15)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmwUt5WBBbrUc1vt2RdQYk
@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

@OriNachum OriNachum merged commit 57bc60e into main Jul 6, 2026
8 checks passed
@OriNachum OriNachum deleted the feat/five-domains branch July 6, 2026 23:15
OriNachum added a commit that referenced this pull request Jul 11, 2026
main advanced to 0.6.0 (five-domain engine, #14) while this docs-only branch
sat at 0.5.1, colliding on the version-coordination files:

- pyproject.toml / uv.lock: 0.5.1 vs 0.6.0 -> re-bumped to 0.6.1 (docs-only
  patch on top of main's 0.6.0).
- CHANGELOG.md: main's #13 already took the [0.5.1] slot with different
  content; relocated this branch's note to a fresh [0.6.1] section, dropped
  the now-moot uv.lock-resync "Fixed" line (main's lock was never stale in
  the 0.6.x line), kept main's [0.6.0] and [0.5.1] intact.
- Semantic conflict (textually clean): main added tests/test_docs_language.py
  banning the phrase "universal meaning" in README.md; this branch's note used
  it ("never universal meaning"). Reworded README, CHANGELOG, and the
  embed.py docstring to "no model-independent semantics" to match main's
  house language.

672 tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant