Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
7cde1d2
fix(voice): distinguish carrying and evidence exports
Aug 28, 2026
11b0b82
fix(voice): preserve legacy CSV column position
Aug 28, 2026
5bc7cb3
Merge remote-tracking branch 'origin/main' into fix/voice-export-auth…
Aug 28, 2026
e519028
fix(voice): keep primary evidence non-derivative
Aug 28, 2026
150298e
docs(gaps): record residual-map ownership conflict
Aug 28, 2026
ddcc473
test(voice): assert empty primary derivation evidence
Aug 28, 2026
cfe7a42
docs(gaps): refresh exact-head queue conflict
Aug 28, 2026
6c37425
docs(gaps): refresh stacked plot evidence
Aug 28, 2026
ca4e5f4
docs(gaps): refresh exact-head stack audit
Aug 28, 2026
f5e915f
fix(voice): export assignment evidence authority
Aug 28, 2026
5766b48
docs(gaps): refresh exact-head delivery inventory
Aug 28, 2026
210b21f
docs(gaps): refresh protected queue snapshot
Aug 28, 2026
c73307a
docs(gaps): refresh exact-head queue evidence
Aug 29, 2026
4f96651
docs(gaps): bind residual map owner delivery
Aug 29, 2026
466bfc9
docs(gaps): record PRD authority conflict
Aug 29, 2026
27a3828
merge: synchronize voice export with protected main
Aug 30, 2026
56f2103
fix(voice): keep primary evidence out of derivation UI
Aug 30, 2026
280ba69
docs(gaps): refresh exact-head Voice delivery evidence
Aug 30, 2026
5fb95e4
docs(gaps): distinguish implementation evidence revision
Aug 30, 2026
43dfcca
fix(voice): prove authenticated export authority
Aug 30, 2026
8a1a404
docs(gaps): record authenticated Voice acceptance
Aug 30, 2026
2bf5354
docs(gaps): bind Voice implementation revision
Aug 30, 2026
d56e860
fix(voice): separate carrying post from derivation
Aug 30, 2026
70a533a
docs(gaps): record Voice SHACL root repair
Aug 30, 2026
4fa6330
fix(ontology): bind voice assignment carrying post
Aug 30, 2026
6496d54
docs(gaps): record voice inverse-link repair
Aug 30, 2026
047b730
fix(ontology): reject extra voice assignment owners
Aug 30, 2026
7688e07
docs(gaps): refresh exact-head Voice validation evidence
Aug 30, 2026
dd674eb
codex: address PR review feedback (#780)
Aug 30, 2026
a8f3bc2
docs(gaps): record authenticated Voice acceptance
Aug 30, 2026
a26af45
fix(runtime): restore post evidence status loader
Aug 30, 2026
d8bda6d
docs(gaps): record exact-head rendered acceptance
Aug 30, 2026
16883d9
docs(gaps): refresh exact-head Voice evidence
Aug 30, 2026
c1dd34b
docs(gaps): refresh exact-head Voice queue evidence
Aug 30, 2026
3bff4fe
docs(gaps): distinguish Voice implementation revision
Aug 30, 2026
7dc8f4b
test(voice): preserve multi-Voice JSON-LD relations
Aug 30, 2026
4b45377
fix(voice): keep carrying post visible on mobile
Aug 30, 2026
48392a8
docs(gaps): refresh Voice exact-head evidence
Aug 30, 2026
116593f
docs(gaps): refresh exact-head Voice delivery evidence
Aug 30, 2026
d7df80e
docs(gaps): bind owner workflow repair head
Aug 30, 2026
8a2fab9
docs(gaps): refresh exact-head Voice delivery evidence
Aug 31, 2026
3da03c8
docs(gaps): bind synchronized policy repair head
Aug 31, 2026
e71895c
docs(gaps): refresh Voice delivery evidence
Aug 31, 2026
4a85e8d
docs(gaps): refresh exact-head Voice delivery evidence
Aug 31, 2026
79dbedf
docs(gaps): bind current central policy head
Aug 31, 2026
8ad7f13
docs(gaps): refresh exact-head Voice evidence
Aug 31, 2026
0327602
docs(gaps): refresh exact-head Voice delivery evidence
Aug 31, 2026
781c004
docs(gaps): refresh exact-head Voice delivery evidence
Aug 31, 2026
72c9636
docs(gaps): distinguish evidence parent from PR head
Aug 31, 2026
81b425f
docs(gaps): refresh exact-head Voice evidence
Aug 31, 2026
29c2191
docs(gaps): refresh exact-head Voice loop evidence
Aug 31, 2026
c5490fc
docs(gaps): refresh protected PR loop evidence
Aug 31, 2026
8403a64
docs(gaps): bind overlay to evidence parent
Aug 31, 2026
734bbcc
docs: refresh exact-head delivery evidence
Aug 31, 2026
948d6e1
docs(gaps): refresh exact-head Voice delivery evidence
Aug 31, 2026
10ca7c1
docs(gaps): refresh exact-head Voice delivery evidence
Aug 31, 2026
c9db49d
docs(gaps): refresh exact-head Voice delivery evidence
Sep 1, 2026
44fb786
docs(gaps): refresh exact-head Voice delivery evidence
Sep 1, 2026
39ee1ee
docs(gaps): record current Voice delivery audit
Sep 1, 2026
1d07c96
docs(gaps): refresh exact-head Voice evidence
Sep 1, 2026
0c3044b
test(api): apply shipped migrations in live fixture
Sep 1, 2026
1c3b48f
chore(voice): restack export authority on live main
seonghobae Sep 1, 2026
9928fd6
docs(gaps): refresh exact-head Voice delivery evidence
Sep 1, 2026
df6aac9
docs(gaps): refresh exact-head Voice evidence
Sep 2, 2026
68c4285
Merge protected main queue fix into Voice export lane
seonghobae Sep 3, 2026
0bf2440
chore(voice): converge export lane with protected main
seonghobae Sep 3, 2026
1d8fa26
chore(voice): converge protected Draft-admission contract
seonghobae Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/adr/0252-temporal-primary-voice-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

## Status

Accepted (2026-08-27). Extends ADR 0251 and closes issue #748.
Accepted (2026-08-27). Extends ADR 0256 and closes issue #748.

## Context

ADR 0251 records when a Voice assignment starts, but migration 0237 deletes
ADR 0256 records when a Voice assignment starts, but migration 0237 deletes
the former imported primary when `source_post.voc_type_code` changes. The live
value is honest, yet an authorized knowledge-cutoff read after that update can
no longer recover the primary that was effective at the cutoff. The existing
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ decision from them.
| [`product-requirements.md`](../product-requirements.md) | Product requirements projection across the ADR set; ADRs remain normative, including [0252](0252-temporal-primary-voice-history.md) |
| [`product-technical-gap-baseline.md`](../product-technical-gap-baseline.md) | Product/technical traceability projection across the ADR set; ADRs remain normative |
| [`lineage-bi-research-notes.md`](../lineage-bi-research-notes.md) | [0084](0084-lineage-research-grounding.md), [0062](0062-semantic-unit-embedding.md), [0064](0064-lineage-evidence-and-tree-assembly.md), [0024](0024-rankweave-fusion-fail-closed.md), [0165](0165-quantity-script-display.md), [0167](0167-rankweave-ranking-channel-evidence.md), [0169](0169-ask-batched-lineage-graph.md), [0172](0172-event-lineage-channel-evidence.md), [0202](0202-ask-event-time-filter.md), [0223](0223-explicit-semantic-content-unit-kinds.md), [0238](0238-source-conversation-turn-import-contract.md) |
| [`voice-combination-technical-requirements.md`](../voice-combination-technical-requirements.md) | [0246](0246-expanded-voice-of-x-post-taxonomy.md), [0251](0256-evidence-bearing-voice-combinations.md), [0252](0252-temporal-primary-voice-history.md) |
| [`voice-combination-technical-requirements.md`](../voice-combination-technical-requirements.md) | [0246](0246-expanded-voice-of-x-post-taxonomy.md), [0256](0256-evidence-bearing-voice-combinations.md), [0252](0252-temporal-primary-voice-history.md) |
| [`lineage-bi-research-notes.md`](../lineage-bi-research-notes.md) | [0084](0084-lineage-research-grounding.md), [0062](0062-semantic-unit-embedding.md), [0064](0064-lineage-evidence-and-tree-assembly.md), [0024](0024-rankweave-fusion-fail-closed.md), [0165](0165-quantity-script-display.md), [0167](0167-rankweave-ranking-channel-evidence.md), [0169](0169-ask-batched-lineage-graph.md), [0172](0172-event-lineage-channel-evidence.md), [0202](0202-ask-event-time-filter.md), [0223](0223-explicit-semantic-content-unit-kinds.md) |
| [`PROV_O_IMPLEMENTATION.md`](../PROV_O_IMPLEMENTATION.md) | [0065](0065-prov-o-provenance-boundary.md) |
| [`PROV_O_IMPLEMENTATION_MATRIX.md`](../PROV_O_IMPLEMENTATION_MATRIX.md) | [0065](0065-prov-o-provenance-boundary.md) |
Expand Down
25 changes: 24 additions & 1 deletion docs/product-technical-gap-baseline.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Product & Technical Gap Baseline

> Exact-head Voice export and authority audit: 2026-08-28 KST. Protected
> `main` was `fc13acaa20adca11968238e398d4aafcf62b6cee`; thirteen PRs and nine
> issues were open. The largest directly actionable Voice acceptance gap on
> this head was export ambiguity: the rendered exact-value table already
> offered separate actions for the carrying Post and derivation-evidence Post,
> while CSV exposed only `evidence_post_id`. The current candidate adds explicit
> `carrying_post_id` and `derivation_evidence_post_id` columns without replacing
> the compatibility field. It also repairs an ADR-number collision: Voice
> combinations are governed by ADR 0256, while ADR 0251 governs the distinct
> FJA/I-O-Psychology layer. Protected delivery and authenticated PostgreSQL/UI
> acceptance remain unavailable until this candidate passes its exact-head
> gate and the runtime evidence is collected. Canonical remote names were
> rechecked as `ContextualWisdomLab/LineageWeave`, `RankWeave`, `ThreadWeave`,
> lowercase `disksage`, `TEPP`, `contextual-orchestrator`, and `fast-mlsirm`.
> The 14:20 KST queue audit also found PR #782 proposing ADR 0267 / migration
> 0245 / v2.24.0 on the same protected-main base. Its buyer-visible coordinates
> are backed by additional projection from the frozen local NumPy residual-map
> debt, while ADR 0208 assigns residual interaction maps and their coordinates
> to fast-mlsirm's Rust result contract. The owner already returns person and
> item coordinates, but this candidate does not consume and persist that
> accepted owner artifact. It therefore remains a conflicting candidate, not a
> protected-main capability or a permissible continuation of the product Gap
> slice; no local reimplementation or heuristic substitute is authorized.
>
> Exact-head loop overlay: 2026-08-28 10:00 KST. Protected `main` was
> `edf22ee39aee2a8481f9bda8fff59801821e79c2` (#773 similar-VOC coverage).
> Open ready PRs: #772 (ask_time_axis coverage), #771 (fixtures/vision
Expand All @@ -15,7 +39,6 @@
> share `e = R̂² / R²` (ADR 0266 / migration 0244 / v2.23.0) so
> `e + s + x = 1` is buyer-auditable. Do not persist leftover-map
> coordinates in this slice.

> Exact-head loop overlay: 2026-08-28 KST. Protected `main` was
> `bbb191924e9881a5201f1ecf63c854d92992cc1c`; seven PRs and nine issues were
> open. PR #763 was `b51d3bd8872b` and PR #762 was `e6ca33dba1b5`; both were
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/storybook-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ operator-facing control you can click before changing product CSS.
| `Post/Connect perspective` | Choose one unassigned Voice and an explicit evidence state, then record the open post as its evidence. `Ready`, `Completed`, and `NarrowViewport` cover untouched, successful, and mobile states. | `VoiceAssignmentForm`, `admin-form`, `btn-primary` |
| `Evidence/CitationChip` | Click a cited title to open that source post. | `--color-chip-border`, `--radius-chip`, `CitationChip` |
| `Evidence/OrganizationAliasChip` | Click a cataloged org; the parenthetical is the unique corroborated SKOS companion. | `--color-chip-border`, `--radius-chip`, `OrganizationAliasChip` |
| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation, while `CombinedVoiceEvidence` covers primary-plus-additional Voice assignments and focuses the evidence action distinct from the carrying-Post action. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0251 states. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` |
| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation, while `CombinedVoiceEvidence` covers primary-plus-additional Voice assignments and focuses the evidence action distinct from the carrying-Post action. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0256 states. The audited combined-Voice renders are `docs/screenshots/voice-combination-export-desktop.png` and `docs/screenshots/voice-combination-export-mobile.png`. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` |
| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project/Work-evidence shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The populated scene includes one assertion-backed occupational construct without a person-trait promotion. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0255 states. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` |
| `AnalysisRun/CutoffKnownBody` | Read the cutoff-known sentence, then compare it with the live body below. | `--color-accent-border`, `--space-panel-block`, `--radius-panel`, `CutoffKnownBody` |
| `Analysis/LineageEntityPicker` | Choose which corp to reconstruct, then click Request a lineage reconstruction. | `--space-control-gap`, `--size-control-min`, `--radius-control`, `LineageEntityPicker` |
Expand Down
2 changes: 1 addition & 1 deletion docs/voice-combination-technical-requirements.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Voice-of-X Combination Technical Requirements

This supporting TRD projects ADR 0246, ADR 0251, and ADR 0252. Those ADRs are
This supporting TRD projects ADR 0246, ADR 0256, and ADR 0252. Those ADRs are
normative when this document and an implementation differ.

## Scope
Expand Down
44 changes: 41 additions & 3 deletions frontend/src/ontologyLayout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "./ontologyLayout";

const POST_ID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1";
const EVIDENCE_POST_ID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa2";
const PERSON_ID = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbb1";
const CORP_ID = "cccccccc-cccc-cccc-cccc-ccccccccccc1";
const ONTOLOGY_NAMESPACE = "https://contextualwisdomlab.github.io/LineageWeave/ontology#";
Expand Down Expand Up @@ -126,7 +127,7 @@ describe("ontologyLayout", () => {
truth_status_code: "truth_observed",
recorded_at: "2026-01-10T12:00:00+00:00",
provenance_reference: "Evidence-backed additional voice",
evidence_post_id: POST_ID,
evidence_post_id: EVIDENCE_POST_ID,
};
const row = {
...source.exact_value_rows[0],
Expand All @@ -136,7 +137,7 @@ describe("ontologyLayout", () => {
target_node_id: assignment.voice_type_code,
target_label: assignment.voice_type_label,
target_type_code: "node_voice_type",
evidence_post_id: POST_ID,
evidence_post_id: EVIDENCE_POST_ID,
};
const withVoice = {
...source,
Expand All @@ -152,13 +153,50 @@ describe("ontologyLayout", () => {

const csv = neighborhoodCsv(withVoice);
expect(csv).toContain("Voice of Customer");
expect(csv.split("\n")[0]).toContain("evidence_post_id");
expect(csv.split("\n")[0]).toBe(
"edge_id,source_label,property_label,target_label,truth_status_code,recorded_at,ontology_property_iri,evidence_post_id,carrying_post_id,derivation_evidence_post_id",
);
expect(csv).toContain(POST_ID);
const voiceCsvRow = csv.split("\n").find((row) => row.includes("Voice of Customer"));
expect(voiceCsvRow).toContain(`${EVIDENCE_POST_ID},${POST_ID},${EVIDENCE_POST_ID}`);
expect(filterNeighborhood(withVoice, "customer")!.voice_assignments).toEqual([assignment]);
expect(filterNeighborhood(withVoice, "missing")!.voice_assignments).toEqual([assignment]);
expect(accumulateNeighborhoodPages(source, withVoice).voice_assignments).toEqual([assignment]);
});

it("does not label imported primary evidence as derivation evidence in CSV", () => {
const source = payload();
const primary = {
post_id: POST_ID,
voice_type_code: "voc_customer",
voice_type_iri: "https://example.test/voice/customer",
voice_type_label: "Voice of Customer",
is_primary: true,
truth_status_code: "truth_observed",
recorded_at: "2026-01-10T12:00:00+00:00",
provenance_reference: "Imported primary voice",
evidence_post_id: POST_ID,
};
const primaryRow = {
...source.exact_value_rows[0],
edge_id: `voice-assignment:${POST_ID}:voc_customer`,
property_code: "hasVoiceAssignment",
property_label: "Voice carried by this post",
target_node_id: primary.voice_type_code,
target_label: primary.voice_type_label,
target_type_code: "node_voice_type",
evidence_post_id: POST_ID,
};

const csv = neighborhoodCsv({
...source,
voice_assignments: [primary],
exact_value_rows: [primaryRow],
});

expect(csv.split("\n")[1]).toContain(`${POST_ID},${POST_ID},`);
Comment thread
seonghobae marked this conversation as resolved.
Outdated
});

it("merges JSON-LD properties and multi-value relations for one paged subject", () => {
const source = payload();
const postIri = `${ONTOLOGY_NAMESPACE}node/node_post/${POST_ID}`;
Expand Down
22 changes: 21 additions & 1 deletion frontend/src/ontologyLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ export function layoutOntologyNeighborhood(payload: OntologyNeighborhoodPayload)
}

export function neighborhoodCsv(payload: OntologyNeighborhoodPayload): string {
const derivedVoiceAssignments = new Set(
(payload.voice_assignments ?? [])
.filter((assignment) => !assignment.is_primary)
.map((assignment) => `${assignment.post_id}\u0000${assignment.voice_type_code}`),
);
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
const header = [
"edge_id",
"source_label",
Expand All @@ -147,12 +152,27 @@ export function neighborhoodCsv(payload: OntologyNeighborhoodPayload): string {
"recorded_at",
"ontology_property_iri",
"evidence_post_id",
"carrying_post_id",
"derivation_evidence_post_id",
];
const lines = [header.join(",")];
for (const row of payload.exact_value_rows) {
lines.push(
header
.map((key) => csvCell(String(row[key as keyof typeof row] ?? "")))
.map((key) => {
if (key === "carrying_post_id") {
return csvCell(row.property_code === "hasVoiceAssignment" ? row.source_node_id : "");
}
if (key === "derivation_evidence_post_id") {
const assignmentKey = `${row.source_node_id}\u0000${row.target_node_id}`;
return csvCell(
row.property_code === "hasVoiceAssignment" && derivedVoiceAssignments.has(assignmentKey)
? row.evidence_post_id ?? ""
: "",
);
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
}
return csvCell(String(row[key as keyof typeof row] ?? ""));
Comment thread
seonghobae marked this conversation as resolved.
})
.join(","),
);
}
Comment thread
seonghobae marked this conversation as resolved.
Expand Down
24 changes: 24 additions & 0 deletions tests/test_voice_authority_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Voice composition supporting documents must name their governing ADRs."""

from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]


def test_voice_combination_documents_reference_adr_0256_not_0251() -> None:
"""Keep Voice composition distinct from ADR 0251's I/O-Psychology layer."""
requirements = (ROOT / "docs/voice-combination-technical-requirements.md").read_text()
history = (ROOT / "docs/adr/0252-temporal-primary-voice-history.md").read_text()
adr_index = (ROOT / "docs/adr/README.md").read_text()
storybook_index = (ROOT / "docs/storybook-inventory.md").read_text()

assert "projects ADR 0246, ADR 0256, and ADR 0252" in requirements
assert "Extends ADR 0256" in history
assert "ADR 0256 records when a Voice assignment starts" in history
assert "[0256](0256-evidence-bearing-voice-combinations.md)" in adr_index
assert "[0251](0256-evidence-bearing-voice-combinations.md)" not in adr_index
ontology_row = next(
line for line in storybook_index.splitlines() if "`Evidence/OntologyExplorer`" in line
)
assert "ADR 0184/0222/0256 states" in ontology_row
Loading