Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
e365664
fix: prioritize evidence-bound operations backfill (#716)
seonghobae Aug 27, 2026
40d953f
docs: refresh dashboard repair snapshot
Aug 28, 2026
7db6af6
fix: isolate acceptance profiles and research copy
Aug 28, 2026
f5706e8
revert: keep measured compose profile boundary
Aug 28, 2026
2e558d3
docs: trace final dashboard repair review
Aug 28, 2026
afa8f4b
fix(frontend): localize operations dashboard copy
Aug 28, 2026
f68a0b2
test(frontend): verify dashboard locale switching
Aug 28, 2026
5138c7c
fix(frontend): localize dashboard code labels
Aug 28, 2026
1d8fcc7
fix(frontend): localize workspace navigation
Aug 28, 2026
5ea18ae
docs: refresh TEPP estimator evidence
Aug 28, 2026
09bf6ec
fix: stabilize source evidence response races
Aug 28, 2026
fd7de92
fix(frontend): remove mixed dashboard locale copy
Aug 28, 2026
959695d
fix(dashboard): close measurement and runtime acceptance gaps
Aug 28, 2026
e857c78
docs(gap): refresh exact repair snapshot
Aug 28, 2026
60150d8
fix(worker): continue bounded durable backfill
Aug 28, 2026
b2b46f4
docs(gap): bind durable continuation evidence
Aug 28, 2026
587a01a
fix(orchestrator): retain buildable Rust runtime pin
Aug 28, 2026
ef55c40
feat(orchestrator): scope endpoint routing selector
Aug 28, 2026
94cb65d
fix: keep externalized math boundaries fail closed
Aug 28, 2026
326773c
Merge remote-tracking branch 'origin/fix/propagate-pr716-dashboard-st…
Aug 28, 2026
e63b2a1
build: pin endpoint-aware orchestrator candidate
Aug 28, 2026
ddb3235
fix(seed): omit unavailable calibrated lineage
Aug 28, 2026
5ab8faf
Merge remote-tracking branch 'origin/fix/propagate-pr716-dashboard-st…
Aug 28, 2026
027fda0
build: advance endpoint-aware orchestrator pin
Aug 28, 2026
fdc3038
fix(frontend): keep mobile dashboard metrics readable
Aug 28, 2026
3d38f48
fix(frontend): keep mobile dashboard metrics readable
Aug 28, 2026
f038419
build(orchestrator): pin reviewed catalog expansion
Aug 28, 2026
e44be2f
Merge commit '3d38f48dd' into feat/orchestrator-routing-endpoint-cons…
Aug 28, 2026
d8d66f7
fix(orchestrator): declare gateway bootstrap seed
Aug 28, 2026
a4d6948
test(orchestrator): verify gateway startup expansion
Aug 28, 2026
29f4f8d
test(orchestrator): constrain startup proof to endpoint
Aug 28, 2026
a72cd41
merge: restack dashboard repair onto current parent
Aug 28, 2026
0070cd2
fix: keep external lineage inference fail closed
Aug 28, 2026
e19ca90
merge: synchronize reviewed dashboard parent
Aug 28, 2026
6f9b328
test: align repair stack with owner math boundary
Aug 28, 2026
bc8b1f3
fix(frontend): restore repair-stack contracts
Aug 28, 2026
3ddee07
test(frontend): align locale-aware navigation
Aug 28, 2026
4982455
docs: correct commercial automation gap evidence
Aug 28, 2026
572ef39
merge: synchronize final dashboard parent repair
Aug 28, 2026
f27f427
docs: refresh exact repair-stack snapshot
Aug 28, 2026
7ef8971
merge: restack endpoint consumer onto dashboard repair
Aug 28, 2026
a8b9199
docs: align source research citations with ADR 0268
Aug 28, 2026
8f07eba
merge: refresh endpoint consumer parent evidence
Aug 28, 2026
df22c62
feat: expose post source research in detail view
Aug 28, 2026
5369257
merge: expose source research through endpoint consumer stack
Aug 28, 2026
94927d1
fix: keep private source research actions unavailable
Aug 28, 2026
ee49208
merge: preserve private source research boundary
Aug 28, 2026
2c55d6b
test: preserve dashboard and Ask runtime evidence flows
Aug 28, 2026
3c59742
fix: bind runtime Ask evidence to real corpus and token expiry
Aug 28, 2026
d146a57
test: derive Ask acceptance budget from operator input
Aug 28, 2026
b87b186
fix: preserve public research retry after citation load failure
Aug 28, 2026
c151027
merge: preserve public source research retry
Aug 28, 2026
33da29e
docs: refresh final stacked PR evidence
Aug 28, 2026
fe4077f
fix(orchestrator): install pinned Rust token packer
Aug 28, 2026
84aff39
fix(runtime): verify exact image revisions
Aug 28, 2026
5df8227
fix(runtime): require MCP acceptance profile
Aug 28, 2026
41faae0
fix(runtime): use bounded readiness jobs
Aug 28, 2026
ee9f70b
fix(orchestrator): drop local embedding selector
Aug 28, 2026
760d058
fix(orchestrator): preserve deployment routing
Aug 28, 2026
8998c87
feat(ask): persist public claim admission (#784)
seonghobae Aug 28, 2026
17520eb
fix(runtime): honor orchestrator admission cadence
Aug 28, 2026
360d87e
perf(post-content): bound the ordered backfill scan
Aug 28, 2026
5deeada
merge: align successor with dashboard parent
Aug 28, 2026
640cc55
build(orchestrator): advance admission contract pin
Aug 28, 2026
e9e2508
fix(migrations): give backfill index a unique ordinal
Aug 28, 2026
31e1013
fix(runtime): accept resumed content ledgers
Aug 28, 2026
bcd7b8e
Merge pull request #785 from ContextualWisdomLab/perf/post-content-ba…
seonghobae Aug 28, 2026
02df59b
fix(provenance): reject ambiguous claim bindings
Aug 28, 2026
661eca2
Merge branch 'feat/orchestrator-routing-endpoint-consumer' of https:/…
Aug 28, 2026
d766131
fix(runtime): execute resumed-ledger SQL through stdin
Aug 28, 2026
16db1ad
fix(dashboard): localize evidence actions and verify interaction modes
Aug 28, 2026
ec4b219
Merge remote-tracking branch 'refs/remotes/origin/pr-786-latest' into…
Aug 28, 2026
a04c028
test(dashboard): keep story guidance customer-facing
Aug 28, 2026
b4b00cd
Merge pull request #788 from ContextualWisdomLab/codex/dashboard-ui-c…
seonghobae Aug 28, 2026
b4b03ab
fix(runtime): pin structured-ready orchestrator (#789)
seonghobae Aug 28, 2026
97b241a
fix(runtime): retain partial readiness evidence (#790)
seonghobae Aug 28, 2026
23134fb
feat(dashboard): produce topic influence evidence
Aug 28, 2026
8df36e7
Merge remote-tracking branch 'origin/feat/orchestrator-routing-endpoi…
Aug 28, 2026
d6ed152
feat(journey): admit digest-bound temporal evidence
Aug 28, 2026
f050994
fix(journey): bind temporal evidence to view cutoff
Aug 28, 2026
20052d1
Merge pull request #791 from ContextualWisdomLab/feat/project-journey…
seonghobae Aug 28, 2026
093aa52
fix(dashboard): harden topic influence delivery
Aug 28, 2026
061d074
Merge remote-tracking branch 'origin/feat/orchestrator-routing-endpoi…
Aug 28, 2026
7bc1d71
fix(schema): keep topic job migration ordered
Aug 28, 2026
ae2bf1b
fix(dashboard): count cited case events only
Aug 28, 2026
81413c5
Merge commit '20052d1ec325f95344370c6b08d2812b7b03ba57' into feat/cas…
Aug 28, 2026
53e7306
fix(worker): prevent backfill wake-up starvation
Aug 28, 2026
57ad036
fix(schema): validate UUID provenance bindings
Aug 28, 2026
6852d1d
Merge pull request #793 from ContextualWisdomLab/feat/case-specific-e…
seonghobae Aug 28, 2026
e609fe4
fix(dashboard): align event evidence visibility
Aug 28, 2026
d76a2f7
Merge pull request #795 from ContextualWisdomLab/fix/case-event-evide…
seonghobae Aug 28, 2026
a0a4919
Merge remote-tracking branch 'origin/feat/orchestrator-routing-endpoi…
Aug 28, 2026
8ff5ca6
fix(dashboard): scope events to visible cases
Aug 28, 2026
5933d55
Merge pull request #796 from ContextualWisdomLab/fix/case-event-visib…
seonghobae Aug 28, 2026
1f980cb
Merge remote-tracking branch 'origin/feat/orchestrator-routing-endpoi…
Aug 28, 2026
6afdb14
Merge commit '5933d555616eefc140acfc06cf7262c48ed7d386' into fix/post…
Aug 28, 2026
fe31db8
fix(worker): classify construct failures separately
Aug 28, 2026
8eb99bf
fix(worker): enforce one durable consumer
Aug 28, 2026
f783572
fix(worker): bound outage wake-up retention
Aug 28, 2026
8981c13
fix(ui): localize dashboard next actions
Aug 28, 2026
5cb3c99
fix(worker): fence recovery publication and shutdown
Aug 28, 2026
f0f9a18
fix: harden topic influence admission lifecycle
Aug 28, 2026
2563c90
Merge pull request #794 from ContextualWisdomLab/fix/post-content-rec…
seonghobae Aug 28, 2026
e2601e3
docs: record topic influence lifecycle evidence
Aug 28, 2026
2bb846d
Merge latest topic dashboard base into influence producer
Aug 28, 2026
387ee0f
fix(worker): order recovery by eligibility time
Aug 28, 2026
930e1fe
fix: bind influence transport to exact artifact bytes
Aug 28, 2026
8d6489f
Merge pull request #797 from ContextualWisdomLab/fix/effective-eligib…
seonghobae Aug 28, 2026
f5c24ce
Merge recovery scheduler fix into influence producer
Aug 28, 2026
f870373
fix: reserve declared topic persistence lease
Aug 28, 2026
88b8441
fix: isolate and fence topic influence leases
Aug 28, 2026
5f2d3d4
fix: complete topic lease recovery fencing
Aug 28, 2026
7f6e151
fix: requeue withdrawn topic evidence
Aug 28, 2026
7954661
fix: wake topic admission on provenance changes
Aug 28, 2026
d319649
fix: clear reclaimed topic request identity
Aug 28, 2026
605d11b
fix: reject partial topic provenance
Aug 28, 2026
f73f078
fix: validate optional topic endpoint
Aug 28, 2026
f775d04
fix: localize analysis run next actions
Aug 28, 2026
1e44efa
fix: bound topic admission state transitions
Aug 28, 2026
ed257cf
fix: keep lifecycle next action available
Aug 28, 2026
43418f7
fix: bind influence to posterior projection
Aug 28, 2026
67fec39
fix: close topic evidence admission race
Aug 28, 2026
18e8253
fix: release all incomplete topic evidence
Aug 28, 2026
f72fa74
Merge pull request #792 from ContextualWisdomLab/feat/topic-influence…
seonghobae Aug 28, 2026
3ea01ff
fix: preserve dashboard and claim admission counts
Aug 28, 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
34 changes: 33 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,32 @@ All notable changes to this project are documented here. Format follows

## [Unreleased]

### Added
- Post-content recovery now keys every initial attempt, retry, and stale lease
by its exact eligibility instant, so work that becomes due after the durable
cursor advances is reached without waiting for a full ledger wrap.

- Global Ask public verification now admits only bounded, provenance-bearing
persisted claims attached to exact cited public posts; missing admission
fails closed without token-overlap egress.

### Added

- Temporal topic influence now has a durable external-production path: the
worker binds the exact completed TEPP artifact, posterior draws, and
business-unit/PU/team/person memberships into a content-addressed request,
then persists only a complete, converged, identified, parity-passed
fast-mlsirm result. Missing owner transport, partial rows, or digest mismatch
remains unavailable without local scoring. Time-valid membership slices
remain distinct; incomplete evidence enters an event-woken awaiting state;
expired work is reclaimed only from its declared request/lease contract,
whose lease must strictly exceed the request timeout for persistence; and
every terminal transition matches a unique lease token. Evidence changed
during computation releases a fresh request automatically.
LineageWeave-owned request and membership bytes and producer-owned result
bytes are SHA-256 verified before parsing, so admission never depends on
cross-language JSON reserialization. Other
retries use only an exact remote delay or an explicit operator requeue
(ADR 0210).

- Evidence Operations now presents cited claim, rebid, handover, external,
product, and Voice evidence with explicit unavailable states and source-open
Expand Down Expand Up @@ -224,6 +249,13 @@ All notable changes to this project are documented here. Format follows

### Fixed

- Public-claim provenance validation now selects its sole UUID binding without
calling PostgreSQL's unavailable `min(uuid)` aggregate, so fresh schema
replays accept valid provenance-bound public claims.
- Post-content wake-up recovery now advances through every ready ledger page
with a deterministic keyset, while Valkey trims only entries already
consumed by the worker. Large backfills can no longer replay the same first
page until a later queued record starves or its unread wake-up is trimmed.
- Full-corpus Event Lineage rebuilds now count candidate pairs before provider
work and omit the optional LLM channel above the 5,000-pair ADR budget,
preventing millions of synchronous orchestrator calls while retaining one
Expand Down
20 changes: 20 additions & 0 deletions backend/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class Settings:
source_research_maximum_results: int | None
tepp_transport_url: str
tepp_api_key: str
topic_influence_transport_url: str
topic_influence_api_key: str
topic_influence_request_timeout_seconds: int | None
topic_influence_lease_timeout_seconds: int | None
topic_influence_poll_seconds: int | None
caldav_base_url: str
naruon_calendar_base_url: str
naruon_calendar_service_token: str
Expand Down Expand Up @@ -215,6 +220,21 @@ def load_settings() -> Settings:
),
tepp_transport_url=os.environ.get("TEPP_TRANSPORT_URL", ""),
tepp_api_key=os.environ.get("TEPP_API_KEY", "").strip(),
topic_influence_transport_url=os.environ.get(
"TOPIC_INFLUENCE_TRANSPORT_URL", ""
).strip(),
topic_influence_api_key=os.environ.get(
"TOPIC_INFLUENCE_API_KEY", ""
).strip(),
topic_influence_request_timeout_seconds=_optional_positive_int(
"TOPIC_INFLUENCE_REQUEST_TIMEOUT_SECONDS"
),
topic_influence_lease_timeout_seconds=_optional_positive_int(
"TOPIC_INFLUENCE_LEASE_TIMEOUT_SECONDS"
),
topic_influence_poll_seconds=_optional_positive_int(
"TOPIC_INFLUENCE_POLL_SECONDS"
),
caldav_base_url=os.environ.get("CALDAV_BASE_URL", "").strip(),
naruon_calendar_base_url=os.environ.get("NARUON_CALENDAR_BASE_URL", "").strip(),
naruon_calendar_service_token=os.environ.get(
Expand Down
91 changes: 79 additions & 12 deletions backend/app/global_ask_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
ClaimVerificationClient,
ClaimVerificationResult,
NullClaimVerificationClient,
public_claim_candidates,
)
from lineageweave.embedding_client import EmbeddingClient, NullEmbeddingClient
from lineageweave.http_client import HttpClientError
Expand All @@ -52,6 +51,10 @@
cited_post_summaries,
historical_body_limitations,
)
from lineageweave.public_claim_envelope import (
PersistedPublicClaimEnvelope,
envelope_from_authorized_row,
)
from lineageweave.semantic_query import NullSemanticQueryClient, SemanticQueryClient
from lineageweave.temporal_expressions import resolve_korean_relative_time

Expand Down Expand Up @@ -103,6 +106,33 @@

_logger = logging.getLogger(__name__)

_AUTHORIZED_PUBLIC_CLAIM_ENVELOPES_SQL = """
select envelope.public_claim_envelope_id,
envelope.source_post_id,
envelope.claim_kind_code,
envelope.claim_text
from public_claim_envelope envelope
join source_post post on post.post_id = envelope.source_post_id
join provenance_assertion assertion
on assertion.assertion_id = envelope.provenance_assertion_id
and assertion.relation_code = 'prov_was_derived_from'
where envelope.egress_eligible
and post.visibility_code = 'public'
and envelope.source_post_id = any($1::uuid[])
and exists (
select 1
from provenance_resource_binding evidence
where evidence.resource_id = assertion.object_resource_id
and evidence.node_type_code = 'node_post'
and evidence.node_id = envelope.source_post_id
)
and ($2::timestamptz is null or (
envelope.created_at <= $2 and post.created_at <= $2
))
order by envelope.created_at, envelope.public_claim_envelope_id
limit 4
"""
Comment thread
seonghobae marked this conversation as resolved.


class _SafeJobError(Exception):
"""Failure whose bounded message is safe to persist for the requester."""
Expand Down Expand Up @@ -188,16 +218,20 @@ async def _verify_public_claims(
*,
verify_external: bool,
client: ClaimVerificationClient,
persisted_envelopes: tuple[PersistedPublicClaimEnvelope, ...] = (),
) -> tuple[str, tuple[ClaimVerificationResult, ...]]:
"""Verify only cited claims explicitly marked safe for public egress."""
"""Verify only cited claims explicitly marked safe for public egress.

Only persisted admission envelopes may cross the public verifier. Omitting
them fails closed; question-token overlap is not an admission mechanism.
"""

if not verify_external:
return VERIFICATION_SKIPPED, ()
cited_ids = frozenset(cited_post_ids)
claims = tuple(envelope.verification_candidate() for envelope in persisted_envelopes)
claims = tuple(
claim
for claim in public_claim_candidates(sources, question)
if set(claim.source_post_ids).issubset(cited_ids)
claim for claim in claims if set(claim.source_post_ids).issubset(cited_ids)
)
if not claims:
return VERIFICATION_NO_PUBLIC_CLAIMS, ()
Expand All @@ -219,6 +253,28 @@ async def _verify_public_claims(
)


async def load_authorized_public_claim_envelopes(
conn: asyncpg.Connection,
cited_post_ids: list[str],
*,
knowledge_cutoff: datetime | None,
) -> tuple[PersistedPublicClaimEnvelope, ...]:
"""Load bounded persisted claims for exact cited public evidence posts."""

if not cited_post_ids:
return ()
rows = await conn.fetch(
_AUTHORIZED_PUBLIC_CLAIM_ENVELOPES_SQL,
cited_post_ids,
knowledge_cutoff,
)
return tuple(
envelope
for row in rows
if (envelope := envelope_from_authorized_row(row)) is not None
)


async def load_job_visibility(
conn: asyncpg.Connection, job_id: str, account_id: str
) -> tuple[set[str], set[str], bool, bool]:
Expand Down Expand Up @@ -372,6 +428,7 @@ def can_see(row: asyncpg.Record) -> bool:
[],
verify_external=verify_external,
client=verification_client,
persisted_envelopes=(),
)
delivery = build_ask_delivery("", (), ())
return {
Expand Down Expand Up @@ -433,14 +490,16 @@ def can_see(row: asyncpg.Record) -> bool:
_ASK_RETRY_MESSAGE,
) from exc
cited_ids = list(answer.cited_post_ids)
verification_status, external_claims = await _verify_public_claims(
question_text,
usable_sources,
cited_ids,
verify_external=verify_external,
client=verification_client,
)
async with pool.acquire() as conn:
persisted_envelopes = (
await load_authorized_public_claim_envelopes(
conn,
cited_ids,
knowledge_cutoff=knowledge_cutoff,
)
if verify_external
else ()
)
Comment thread
seonghobae marked this conversation as resolved.
if knowledge_cutoff is None:
lineage_graph = await lineage_graphs_for_posts(conn, can_see, cited_ids)
images = await cited_post_images(conn, cited_ids)
Expand All @@ -452,6 +511,14 @@ def can_see(row: asyncpg.Record) -> bool:
cited_ids,
checked_by=knowledge_cutoff,
)
verification_status, external_claims = await _verify_public_claims(
question_text,
usable_sources,
cited_ids,
verify_external=verify_external,
client=verification_client,
persisted_envelopes=persisted_envelopes,
)
Comment thread
seonghobae marked this conversation as resolved.
cited_posts = cited_post_summaries(usable_sources, cited_ids)
cited_events = cited_post_events(usable_sources, cited_ids)
cited_evidence = cited_post_evidence(usable_sources, cited_ids)
Expand Down
26 changes: 11 additions & 15 deletions backend/app/operations_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,6 @@ async def fetch_operations_dashboard(
)
)
select (select count(*) from visible_post) as total_post_count,
(select count(*)
from post_summary_event summary_event
where exists (
select 1 from classified
where classified.post_id = summary_event.post_id
and ($5::boolean is false
or classified.case_kind_code = 'external_information')
)) as total_event_count,
(select count(distinct post_id) from classified
where case_kind_code = 'external_information') as external_post_count,
(select count(*) from scoped_post
Expand Down Expand Up @@ -225,10 +217,7 @@ async def fetch_operations_dashboard(
coalesce(post.event_occurred_at, post.created_at) as occurred_at,
coalesce(nullif(btrim(post.source_project_name), ''), project.primary_project_name)
as project_name,
coalesce(project.project_names, array[]::text[]) as project_names,
(select count(*)::int
from post_summary_event summary_event
where summary_event.post_id = classification.post_id) as event_count
coalesce(project.project_names, array[]::text[]) as project_names
from operations_case_classification classification
join source_post post on post.post_id = classification.post_id
join source_post evidence_post
Expand Down Expand Up @@ -439,10 +428,17 @@ async def fetch_operations_dashboard(
external = int(metrics["external_post_count"])
case_post_ids: dict[str, set[str]] = {}
case_event_counts: dict[str, int] = {}
counted_case_keys: set[tuple[str, str]] = set()
for row in case_rows:
kind = row["case_kind_code"]
case_post_ids.setdefault(kind, set()).add(str(row["post_id"]))
case_event_counts[kind] = case_event_counts.get(kind, 0) + int(row["event_count"])
post_id = str(row["post_id"])
case_post_ids.setdefault(kind, set()).add(post_id)
key = (post_id, kind)
if key not in counted_case_keys:
case_event_counts[kind] = case_event_counts.get(kind, 0) + len(
milestones.get(key, ())
)
counted_case_keys.add(key)
projected_cases = []
lifecycle_metrics = {
lifecycle_code: {
Expand Down Expand Up @@ -493,7 +489,7 @@ async def fetch_operations_dashboard(
"period_end": period_end.isoformat() if period_end else None,
"period_time_axis_code": "event_occurred_at",
"total_post_count": total,
"total_event_count": int(metrics["total_event_count"]),
"total_event_count": sum(case_event_counts.values()),
Comment thread
seonghobae marked this conversation as resolved.
"external_post_count": external,
"external_percent": external * 100 / total if total else 0.0,
"pending_analysis_count": int(metrics["pending_analysis_count"]),
Expand Down
Loading