diff --git a/.agent/handoffs/external-agent-campaigns/2026-07-16-gpt-pro-wave/testdiet/context/testsuite_diet/04-harness-architecture.md b/.agent/handoffs/external-agent-campaigns/2026-07-16-gpt-pro-wave/testdiet/context/testsuite_diet/04-harness-architecture.md index 103045ddfd..c230c7c34d 100644 --- a/.agent/handoffs/external-agent-campaigns/2026-07-16-gpt-pro-wave/testdiet/context/testsuite_diet/04-harness-architecture.md +++ b/.agent/handoffs/external-agent-campaigns/2026-07-16-gpt-pro-wave/testdiet/context/testsuite_diet/04-harness-architecture.md @@ -142,9 +142,7 @@ expressions (or a typed AST produced by the production parser) and keep only the independent planted-fact oracle. A test should look conceptually like: ```python -expected = corpus.facts.session_ids_matching( - origin="codex-session", text_token="needle", min_messages=7 -) +expected = corpus.facts.session_ids_matching(origin="codex-session", text_token="needle", min_messages=7) assert await run_repository_query(expression) == expected assert run_cli_query(expression).session_ids == expected assert await run_http_query(expression) == expected diff --git a/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/ann-01/r01/extracted/HANDOFF.md b/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/ann-01/r01/extracted/HANDOFF.md index d3423c5206..87d6619acc 100644 --- a/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/ann-01/r01/extracted/HANDOFF.md +++ b/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/ann-01/r01/extracted/HANDOFF.md @@ -133,7 +133,7 @@ from polylogue.annotations.importer import AnnotationBatchImportRequest request = AnnotationBatchImportRequest( jsonl=jsonl_text, batch_id="stable-run-id", - schema_id="seed.activity", # or an operator-promoted archive-local id + schema_id="seed.activity", # or an operator-promoted archive-local id schema_version=1, target_ref="session:...", source_result_ref="result-set:...", diff --git a/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/misc-02/r01/extracted/HANDOFF.md b/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/misc-02/r01/extracted/HANDOFF.md index 4fcae228bd..dbc2437be8 100644 --- a/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/misc-02/r01/extracted/HANDOFF.md +++ b/.agent/handoffs/external-agent-campaigns/2026-07-17-gpt-pro-wave-2/results/misc-02/r01/extracted/HANDOFF.md @@ -376,8 +376,7 @@ try: recipe_hash_sql = f"X'{recipe.recipe_hash.hex()}'" output_hash_sql = f"X'{recipe.output_contract_hash.hex()}'" desired_key_sql = ( - "polylogue_embedding_derivation_key(" - f"s.session_id, ds.source_hash, {recipe_hash_sql}, {output_hash_sql})" + f"polylogue_embedding_derivation_key(s.session_id, ds.source_hash, {recipe_hash_sql}, {output_hash_sql})" ) key_current = f"""( d.session_id IS NOT NULL @@ -452,9 +451,7 @@ try: assert row is not None result = {name: int(value or 0) for name, value in zip(columns, row, strict=True)} result["partition_check"] = ( - result["exact_fresh_sessions"] - + result["exact_pending_sessions"] - + result["exact_blocked_sessions"] + result["exact_fresh_sessions"] + result["exact_pending_sessions"] + result["exact_blocked_sessions"] == result["eligible_sessions"] ) print(json.dumps(result, indent=2, sort_keys=True)) diff --git a/.agent/handoffs/polylogue-deep-research-2026-07-09/01-cache-pricing-policy.md b/.agent/handoffs/polylogue-deep-research-2026-07-09/01-cache-pricing-policy.md index d92142f705..9d4dd0e8ac 100644 --- a/.agent/handoffs/polylogue-deep-research-2026-07-09/01-cache-pricing-policy.md +++ b/.agent/handoffs/polylogue-deep-research-2026-07-09/01-cache-pricing-policy.md @@ -90,7 +90,7 @@ read. This is correct, not a gap. ### How the loader ingests this (`pricing.py:_load_litellm_catalog`) ```python -cache_read_usd_per_1m = float(entry.get("cache_read_input_token_cost") or 0.0) * 1_000_000 +cache_read_usd_per_1m = float(entry.get("cache_read_input_token_cost") or 0.0) * 1_000_000 cache_write_usd_per_1m = float(entry.get("cache_creation_input_token_cost") or 0.0) * 1_000_000 ``` diff --git a/.agent/handoffs/polylogue-deep-research-2026-07-09/06-atropos-export.md b/.agent/handoffs/polylogue-deep-research-2026-07-09/06-atropos-export.md index a344a7c815..185b512363 100644 --- a/.agent/handoffs/polylogue-deep-research-2026-07-09/06-atropos-export.md +++ b/.agent/handoffs/polylogue-deep-research-2026-07-09/06-atropos-export.md @@ -32,12 +32,12 @@ one prompt with N candidate rollouts; the JSONL writer emits one group per line) ```python class ScoredDataGroup(TypedDict): - tokens: List[List[int]] # per-member token ids - masks: List[List[int]] # per-member loss mask (-100 / token-id convention) - scores: List[float] # per-member scalar reward - advantages: Optional[List[List[float]]] # per-token advantages + tokens: List[List[int]] # per-member token ids + masks: List[List[int]] # per-member loss mask (-100 / token-id convention) + scores: List[float] # per-member scalar reward + advantages: Optional[List[List[float]]] # per-token advantages ref_logprobs: Optional[List[List[float]]] - messages: Optional[List[List[Message]]] # per-member OpenAI-style message list + messages: Optional[List[List[Message]]] # per-member OpenAI-style message list generation_params: Optional[Dict[str, Any]] inference_logprobs: Optional[List[List[float]]] group_overrides: Optional[Dict] @@ -52,11 +52,13 @@ Supporting types (`atroposlib/type_definitions.py`): ```python number = int | float + class Message(TypedDict): role: Literal["system", "user", "assistant", "tool"] - content: Content # str (or multimodal content blocks) + content: Content # str (or multimodal content blocks) reward: Optional[float] + Item = Any ``` @@ -73,8 +75,7 @@ Key structural facts: `messages is None`, `base.py` auto-fills it by decoding `tokens`: ```python group["messages"] = [ - [{"role": "user", "content": self.tokenizer.decode(group["tokens"][i])}] - for i in range(len(group["tokens"])) + [{"role": "user", "content": self.tokenizer.decode(group["tokens"][i])}] for i in range(len(group["tokens"])) ] ``` i.e. messages can be supplied directly and Atropos will *not* overwrite them. diff --git a/.agent/handoffs/polylogue-deep-research-2026-07-09/07-reprice-in-place-perf.md b/.agent/handoffs/polylogue-deep-research-2026-07-09/07-reprice-in-place-perf.md index f0fbd17b3f..6bd3812b3d 100644 --- a/.agent/handoffs/polylogue-deep-research-2026-07-09/07-reprice-in-place-perf.md +++ b/.agent/handoffs/polylogue-deep-research-2026-07-09/07-reprice-in-place-perf.md @@ -112,16 +112,19 @@ once and issue a handful of **set-based** UPDATEs (each covering all rows for on model), never row-by-row. ```python -def reprice_in_place(conn): # one sqlite3 connection - seed_price_catalog(conn) # idempotent: ensure new catalog_id rows exist - catalog_id = _catalog_id() # new f"{PROVENANCE}-{EFFECTIVE_DATE}" +def reprice_in_place(conn): # one sqlite3 connection + seed_price_catalog(conn) # idempotent: ensure new catalog_id rows exist + catalog_id = _catalog_id() # new f"{PROVENANCE}-{EFFECTIVE_DATE}" now_ms = int(time.time() * 1000) - models = [r[0] for r in conn.execute( - "SELECT DISTINCT model_name FROM session_model_usage " - "WHERE cost_provenance IN ('priced','estimated')")] + models = [ + r[0] + for r in conn.execute( + "SELECT DISTINCT model_name FROM session_model_usage WHERE cost_provenance IN ('priced','estimated')" + ) + ] - with conn: # ATOMIC: single transaction + with conn: # ATOMIC: single transaction for raw in models: norm = _normalize_model(raw) p = PRICING.get(norm) @@ -130,7 +133,8 @@ def reprice_in_place(conn): # one sqlite3 connection conn.execute( "UPDATE session_model_usage SET cost_usd=NULL, priced_with=NULL, " "priced_at_ms=NULL WHERE model_name=? AND cost_provenance IN ('priced','estimated')", - (raw,)) + (raw,), + ) continue ir, orr = p.input_usd_per_1m, p.output_usd_per_1m crr, cwr = p.cache_read_usd_per_1m, p.cache_write_usd_per_1m @@ -145,7 +149,8 @@ def reprice_in_place(conn): # one sqlite3 connection AND cost_provenance IN ('priced','estimated') AND (input_tokens+output_tokens+cache_read_tokens+cache_write_tokens) > 0 """, - (ir, orr, crr, cwr, catalog_id, now_ms, raw)) + (ir, orr, crr, cwr, catalog_id, now_ms, raw), + ) # re-aggregate session_profiles from the refreshed per-model rows conn.execute( @@ -161,7 +166,8 @@ def reprice_in_place(conn): # one sqlite3 connection WHERE sp.session_id = agg.session_id AND sp.cost_provenance IN ('priced','estimated','mixed') """, - (catalog_id, now_ms)) + (catalog_id, now_ms), + ) ``` Notes: diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A16-measure-registry.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A16-measure-registry.md index 43e1580d1e..3e8dc053a6 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A16-measure-registry.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A16-measure-registry.md @@ -51,16 +51,16 @@ class MeasureSpec(BaseModel): id: str construct: str operationalization: str - reducer: Literal["count","sum","ratio","mean","median","pXX","entropy","Gini","zstd-ratio"] + reducer: Literal["count", "sum", "ratio", "mean", "median", "pXX", "entropy", "Gini", "zstd-ratio"] column_expr: str - unit_frame: Literal["sessions","actions","messages","observed-events","work-events","phases","threads"] + unit_frame: Literal["sessions", "actions", "messages", "observed-events", "work-events", "phases", "threads"] denominator_expr: str | None - evidence_tier: Literal["structural","provider-reported","derived","heuristic","mixed"] + evidence_tier: Literal["structural", "provider-reported", "derived", "heuristic", "mixed"] required_coverage: CoverageGate confounds: tuple[str, ...] provenance_mixing_flags: tuple[str, ...] uncertainty: UncertaintySpec - null_policy: Literal["suppress","zero","exclude","separate-unknown"] + null_policy: Literal["suppress", "zero", "exclude", "separate-unknown"] formula_version: int output_schema: str footnote_template: str @@ -187,7 +187,7 @@ MeasureSpec( evidence_tier="structural", required_coverage={"session_latency_profiles": "present", "timing_provenance": "timestamped_or_structural"}, uncertainty={"kind": "proportion", "interval": "wilson"}, - footnote_template="n={n}, coverage={coverage}, timing_provenance={timing_provenance}" + footnote_template="n={n}, coverage={coverage}, timing_provenance={timing_provenance}", ) ``` diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A17-query-objects.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A17-query-objects.md index e39f5c9b8b..4790e4b56b 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A17-query-objects.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/B-A17-query-objects.md @@ -372,8 +372,7 @@ def assertion_id_for_finding( value: object, evidence_refs: Sequence[str], detector_ref: str, -) -> str: - ... +) -> str: ... ``` [proposal] Add: @@ -384,8 +383,7 @@ def upsert_findings_as_assertions( findings: Sequence[FindingCandidate], *, now_ms: int | None = None, -) -> list[ArchiveAssertionEnvelope]: - ... +) -> list[ArchiveAssertionEnvelope]: ... ``` Use the pathology pattern exactly: diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-2-of-6.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-2-of-6.md index 895381ede1..d39f977cf1 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-2-of-6.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-2-of-6.md @@ -1082,36 +1082,55 @@ polylogue/analytics/measures.py # MeasureSpec, MEASURE_REGISTRY, evaluate_mea `MeasureSpec` is a frozen pydantic/dataclass declared in code exactly like `InsightType` and `RigorContract` — the registry is a `dict[str, MeasureSpec]`, not a table. ```python -class EvidenceTier(str, Enum): # ordered weakest→strongest for footnote precedence - HEURISTIC = "heuristic"; DERIVED = "derived" - PROVIDER_REPORTED = "provider_reported"; STRUCTURAL = "structural" +class EvidenceTier(str, Enum): # ordered weakest→strongest for footnote precedence + HEURISTIC = "heuristic" + DERIVED = "derived" + PROVIDER_REPORTED = "provider_reported" + STRUCTURAL = "structural" + + +class SampleFrame(str, Enum): # RISK-3 keystone + LOGICAL_SESSION = "logical_session" # default: dedup lineage via session_links + PHYSICAL_SESSION = "physical_session" + ACTION = "action" + MESSAGE = "message" + USAGE_EVENT = "usage_event" -class SampleFrame(str, Enum): # RISK-3 keystone - LOGICAL_SESSION = "logical_session" # default: dedup lineage via session_links - PHYSICAL_SESSION = "physical_session"; ACTION = "action"; MESSAGE = "message"; USAGE_EVENT = "usage_event" class Reducer(str, Enum): - COUNT; SUM; MEAN; MEDIAN; QUANTILE; PROPORTION; RATIO; ENTROPY; DISTINCT + COUNT + SUM + MEAN + MEDIAN + QUANTILE + PROPORTION + RATIO + ENTROPY + DISTINCT + class UncertaintyMethod(str, Enum): - NONE; WILSON; BOOTSTRAP # WILSON⇒proportions, BOOTSTRAP⇒mean/median/quantile/ratio + NONE + WILSON + BOOTSTRAP # WILSON⇒proportions, BOOTSTRAP⇒mean/median/quantile/ratio + @dataclass(frozen=True, slots=True) class MeasureSpec: name: str - construct: str # what it operationalizes (prose) - unit_label: str # display unit ("ratio","tokens","$/session","bits","1/hr") - unit_frame: SampleFrame # which rows the reducer folds + construct: str # what it operationalizes (prose) + unit_label: str # display unit ("ratio","tokens","$/session","bits","1/hr") + unit_frame: SampleFrame # which rows the reducer folds reducer: Reducer - numerator_expr: str # SQL/column expr over the frame (the "formula ref") - denominator_expr: str | None # EXPLICIT denominator for RATIO/PROPORTION (never implicit) + numerator_expr: str # SQL/column expr over the frame (the "formula ref") + denominator_expr: str | None # EXPLICIT denominator for RATIO/PROPORTION (never implicit) quantile: float | None = None - default_group_fields: tuple[str, ...] = () # ⊆ descriptor.aggregate_group_fields + windows + default_group_fields: tuple[str, ...] = () # ⊆ descriptor.aggregate_group_fields + windows evidence_tier: EvidenceTier - required_coverage: tuple[CoveragePredicate, ...] = () # checked at composition (§2.B) - confounds: tuple[str, ...] # non-empty is an audit invariant + required_coverage: tuple[CoveragePredicate, ...] = () # checked at composition (§2.B) + confounds: tuple[str, ...] # non-empty is an audit invariant uncertainty: UncertaintyMethod - output_schema: str # payload model name for render/openapi + output_schema: str # payload model name for render/openapi ``` **Optional (deferred, not v1):** a *rebuildable* `measure_snapshot` cache table in index.db (schema v25) keyed `(measure, group_key, window)` for scale, dropped-and-recomputed on any index rebuild. Spec it only when §4 scale numbers demand it; keep v1 compute-on-read. diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-3-of-6.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-3-of-6.md index fef988226e..5db47a0ffa 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-3-of-6.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-3-of-6.md @@ -1038,46 +1038,51 @@ Surface wiring: `compact` is a new **session-source pipeline terminal action** a New module `polylogue/insights/corpus_compaction.py` (insight-tier substrate; surfaces stay leaf adapters per the layering rule). ```python -class CompactionBudget(str, Enum): # named token budgets - SMALL = "60k" # 60_000 tokens - LARGE = "200k" # 200_000 tokens +class CompactionBudget(str, Enum): # named token budgets + SMALL = "60k" # 60_000 tokens + LARGE = "200k" # 200_000 tokens # numeric override allowed via --budget N + class CompactionProjection(SurfacePayloadModel): """Fixed projection preset for corpus compaction (read-algebra Projection node).""" + budget_tokens: int = 60_000 - keep_origins: tuple[MaterialOrigin, ...] = ( # what survives scoring floor + keep_origins: tuple[MaterialOrigin, ...] = ( # what survives scoring floor MaterialOrigin.HUMAN_AUTHORED, MaterialOrigin.OPERATOR_COMMAND, MaterialOrigin.ASSISTANT_AUTHORED, ) - drop_origins: tuple[MaterialOrigin, ...] = ( # hard-drop (tool-spam) + drop_origins: tuple[MaterialOrigin, ...] = ( # hard-drop (tool-spam) MaterialOrigin.TOOL_RESULT, MaterialOrigin.RUNTIME_PROTOCOL, MaterialOrigin.RUNTIME_CONTEXT, MaterialOrigin.GENERATED_CONTEXT_PACK, ) - per_session_floor_tokens: int = 200 # every kept session guaranteed a header + 1 decision + per_session_floor_tokens: int = 200 # every kept session guaranteed a header + 1 decision include_drop_manifest: bool = True - lineage_grain: Literal["logical_session","physical"] = "logical_session" + lineage_grain: Literal["logical_session", "physical"] = "logical_session" -class CompactBlock(ArchiveInsightModel): # the scored, selectable unit + +class CompactBlock(ArchiveInsightModel): # the scored, selectable unit session_id: str message_id: str block_index: int material_origin: MaterialOrigin - kind: Literal["human_turn","decision","error_fix","outcome","assistant_prose"] + kind: Literal["human_turn", "decision", "error_fix", "outcome", "assistant_prose"] text: str token_estimate: int score: float - evidence_ref: EvidenceRef # citation anchor (reuses core/refs.py) + evidence_ref: EvidenceRef # citation anchor (reuses core/refs.py) + class CompactionDropManifest(ArchiveInsightModel): - dropped_by_origin: dict[str, int] # counts by MaterialOrigin - dropped_by_reason: dict[str, int] # {"budget": n, "tool_spam": n, "lineage_dup": n, "low_score": n} + dropped_by_origin: dict[str, int] # counts by MaterialOrigin + dropped_by_reason: dict[str, int] # {"budget": n, "tool_spam": n, "lineage_dup": n, "low_score": n} truncated_sessions: tuple[str, ...] recoverable_via: str = "polylogue read session: --view transcript" + class CorpusCompaction(ArchiveInsightModel): projection: CompactionProjection logical_session_count: int @@ -1752,61 +1757,71 @@ renders per `(model,month)`: `rate [lo,hi] n=… (structural)` + candidate chang # --- COHORT BUILD -------------------------------------------------- def build_drift_cohort(anchor, S, θ, c, date_range): # 1. intent match — reuse similarity.py, never re-embed - sim = find_similar_sessions(anchor, limit=MAX) # cosine in [0,1] + sim = find_similar_sessions(anchor, limit=MAX) # cosine in [0,1] if sim.status != "ready": - return CohortResult.absent(sim.status) # honest absent-state + return CohortResult.absent(sim.status) # honest absent-state matched = {h.session_id for h in sim.hits if h.score >= θ} # 2. shape gate + collapse to logical grain - cells = defaultdict(list) # (model, month) -> [logical] + cells = defaultdict(list) # (model, month) -> [logical] embedded, total = 0, 0 for sess in load_profiles(matched, date_range): - if sess.workflow_shape != S: continue - if sess.workflow_shape_confidence < c: continue + if sess.workflow_shape != S: + continue + if sess.workflow_shape_confidence < c: + continue total += 1 - if embedding_status(sess).needs_reindex == 0: embedded += 1 - lg = sess.logical_session_id or sess.session_id # dedup lineage (#2467) - model = sess.normalized_model or "unknown" # NOT raw model_name - month = sess.canonical_session_date[:7] # YYYY-MM + if embedding_status(sess).needs_reindex == 0: + embedded += 1 + lg = sess.logical_session_id or sess.session_id # dedup lineage (#2467) + model = sess.normalized_model or "unknown" # NOT raw model_name + month = sess.canonical_session_date[:7] # YYYY-MM cells[(model, month)].append(logical_view(lg, sess)) # 3. per-cell coverage gate (9l5.2 / 9l5.7 refusal, not silent partial) embed_cov = embedded / total if total else 0.0 for key, rows in cells.items(): - rows = collapse_by_logical(rows) # 1 row per lineage + rows = collapse_by_logical(rows) # 1 row per lineage n = len(rows) priced = mean(r.cost_provenance == "priced" for r in rows) cells[key] = Cell(rows, n=n, priced_frac=priced) return CohortResult(cells, embed_coverage=embed_cov) + # --- MEASURE + UNCERTAINTY (per cell) ------------------------------ def measure_cell(cell, spec): - if cell.n < spec.n_min: return TieredValue.insufficient(cell.n) + if cell.n < spec.n_min: + return TieredValue.insufficient(cell.n) if spec.required_coverage.priced and cell.priced_frac < τ: return Refusal(f"{spec.name}: cell priced coverage {cell.priced_frac:.0%} < τ") - if spec.reducer is PROPORTION: # Wilson + if spec.reducer is PROPORTION: # Wilson k = sum(spec.numerator(r) for r in cell.rows) - lo, hi = wilson_interval(k, cell.n) # analytics/stats.py (9l5.7) - return TieredValue(k/cell.n, (lo,hi), cell.n, spec.evidence_tier) - else: # mean/median/percentile -> bootstrap + lo, hi = wilson_interval(k, cell.n) # analytics/stats.py (9l5.7) + return TieredValue(k / cell.n, (lo, hi), cell.n, spec.evidence_tier) + else: # mean/median/percentile -> bootstrap vals = [spec.value(r) for r in cell.rows] pt, lo, hi = bootstrap_ci(vals, spec.reduce, B=2000) - return TieredValue(pt, (lo,hi), cell.n, spec.evidence_tier) + return TieredValue(pt, (lo, hi), cell.n, spec.evidence_tier) + # --- CHANGEPOINT (per model's monthly series) ---------------------- def detect_drift_changepoints(series, known_events): # series: [(month, TieredValue)] for one model, one measure xs = [tv.point for _, tv in series if tv.usable] - if len(xs) < MIN_SEG*2: return [] - cps = pelt(xs, penalty=BIC_penalty(len(xs))) # ruptures [analytics]; - # fallback: binary_segmentation() ~60 lines + if len(xs) < MIN_SEG * 2: + return [] + cps = pelt(xs, penalty=BIC_penalty(len(xs))) # ruptures [analytics]; + # fallback: binary_segmentation() ~60 lines out = [] for idx in cps: month = series[idx].month # HONESTY RAIL: candidate, never causal - nearby = [e for e in known_events # model-version transition - if abs(months_between(e.month, month)) <= 1] # + hook/harness events - delta, sig = compare_segments(series, idx) # two-sample test on the split + nearby = [ + e + for e in known_events # model-version transition + if abs(months_between(e.month, month)) <= 1 + ] # + hook/harness events + delta, sig = compare_segments(series, idx) # two-sample test on the split out.append(Changepoint(month, delta, sig, candidates=nearby, causal=False)) return out ``` diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-4-of-6.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-4-of-6.md index 014142373d..f1d3ed8ca4 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-4-of-6.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-4-of-6.md @@ -849,19 +849,23 @@ Register one `QueryUnitDescriptor` + `StructuralQueryUnitInfo` (pattern from `me ```python QueryUnitDescriptor( - "delegation", "delegation", "delegations", + "delegation", + "delegation", + "delegations", exists_supported=True, payload_model="DelegationQueryRowPayload", sql_query_method="query_delegations", cli_plain_renderer="delegation", aggregate_group_fields=( - "subagent_model_family", "orchestrator_model_family", - "result_status", "parent_terminal_state", - "session.origin", "session.repo", + "subagent_model_family", + "orchestrator_model_family", + "result_status", + "parent_terminal_state", + "session.origin", + "session.repo", ), fields=_unit_info("delegation").fields, - terminal_example= - "delegations where orchestrator_model:fable | group by subagent_model_family | count", + terminal_example="delegations where orchestrator_model:fable | group by subagent_model_family | count", ) ``` @@ -1005,10 +1009,10 @@ Placement rule (durability-keyed, per CLAUDE.md schema regimes): **all four new ```python class TimeKind(StrEnum): - OCCURRED = "occurred" # provider-reported event wall-clock (created/updated/occurred_at_ms) - ACQUIRED = "acquired" # when polylogue read the raw bytes (source.db, OUR clock) - INGESTED = "ingested" # when the writer committed the derived row (parsed/materialized, OUR clock) - SORT = "sort" # synthetic ordering key; NEVER a wall-clock claim + OCCURRED = "occurred" # provider-reported event wall-clock (created/updated/occurred_at_ms) + ACQUIRED = "acquired" # when polylogue read the raw bytes (source.db, OUR clock) + INGESTED = "ingested" # when the writer committed the derived row (parsed/materialized, OUR clock) + SORT = "sort" # synthetic ordering key; NEVER a wall-clock claim ``` `OCCURRED` is the only tz-ambiguous, provider-trusted axis. `ACQUIRED`/`INGESTED` are always OUR injectable clock (§3.1) and are always known-UTC. `SORT` is derived and carries provenance (§1.2). @@ -1032,23 +1036,25 @@ tz_provenance TEXT NOT NULL DEFAULT 'unknown' ```python class SortKeyProvenance(StrEnum): - EXPLICIT = "explicit" # from updated_at_ms (provider-authored) - INHERITED = "inherited" # fell back to created_at_ms - FELL_BACK_TO_INGEST = "fell_back_to_ingest" # no event time; used acquired/ingested clock - SYNTHESIZED_ZERO = "synthesized_zero" # no time anywhere; sentinel, MUST stay queryable + EXPLICIT = "explicit" # from updated_at_ms (provider-authored) + INHERITED = "inherited" # fell back to created_at_ms + FELL_BACK_TO_INGEST = "fell_back_to_ingest" # no event time; used acquired/ingested clock + SYNTHESIZED_ZERO = "synthesized_zero" # no time anywhere; sentinel, MUST stay queryable + class TimeConfidence(StrEnum): - EXACT = "exact" # hook-precise provider measurement - REPORTED = "reported" # provider wall-clock, trusted as-is + EXACT = "exact" # hook-precise provider measurement + REPORTED = "reported" # provider wall-clock, trusted as-is ESTIMATED = "estimated" # inter-message-gap / sort_key_estimated derivation SYNTHETIC = "synthetic" # no real time; ordering is a tiebreak sentinel only - UNKNOWN = "unknown" + UNKNOWN = "unknown" + class TzProvenance(StrEnum): PROVIDER_EXPLICIT = "provider_explicit" # offset present in raw payload - ASSUMED_UTC = "assumed_utc" # naive→UTC coercion (today's silent parse_timestamp behavior — now LABELED) - INFERRED = "inferred" # derived from sibling signal (e.g. cwd/user profile) - UNKNOWN = "unknown" # DEFAULT — tz-unknown-by-default + ASSUMED_UTC = "assumed_utc" # naive→UTC coercion (today's silent parse_timestamp behavior — now LABELED) + INFERRED = "inferred" # derived from sibling signal (e.g. cwd/user profile) + UNKNOWN = "unknown" # DEFAULT — tz-unknown-by-default ``` Doctrine invariants encoded by these types: @@ -1112,9 +1118,20 @@ Single injectable production clock — the one place `frozen_clock` patches. ```python # core/clock.py from datetime import datetime, timezone -def now(tz: timezone = timezone.utc) -> datetime: return datetime.now(tz) -def now_ms() -> int: return int(now().timestamp() * 1000) -def monotonic() -> float: import time; return time.monotonic() # measurement-only, never for sort_key + + +def now(tz: timezone = timezone.utc) -> datetime: + return datetime.now(tz) + + +def now_ms() -> int: + return int(now().timestamp() * 1000) + + +def monotonic() -> float: + import time + + return time.monotonic() # measurement-only, never for sort_key ``` `core/dates.py` fix: @@ -1130,10 +1147,10 @@ settings = {..., "RELATIVE_BASE": clock.now()} # was datetime.now(tz=timezone. ```python if since is not None: - where_clauses.append(".sort_key_ms >= ?") # keep: NULL correctly excluded from a lower bound + where_clauses.append(".sort_key_ms >= ?") # keep: NULL correctly excluded from a lower bound params.append(_iso_to_epoch(since) * 1000.0) if until is not None: - where_clauses.append(".sort_key_ms < ?") # was "<= ?": half-open [since, until) + where_clauses.append(".sort_key_ms < ?") # was "<= ?": half-open [since, until) params.append(_iso_to_epoch(until) * 1000.0) ``` @@ -1819,19 +1836,21 @@ Durability axis dictates placement. Nothing here needs a durable **structural** ```python class NoticeFamily(str, Enum): - OPERATIONAL = "operational" # existing HealthAlerts, implicit today - CONTENT = "content" # this layer + OPERATIONAL = "operational" # existing HealthAlerts, implicit today + CONTENT = "content" # this layer + # HealthSeverity gains: NOTICE = "notice", rank 0 (== OK for operational gate; # never escalates the operational overall_status). Content routing ignores rank. -class Notice(HealthAlert): # reuse check_name/tier/message/checked_at + +class Notice(HealthAlert): # reuse check_name/tier/message/checked_at family: NoticeFamily = NoticeFamily.CONTENT - anchor: str # ObjectRef: session:[:block:] — citation - confidence: float # 0..1, mirrors assertions.confidence - cite_refs: list[str] = [] # ObjectRefs to evidence (pathology/lesson sessions) - trigger: str # "standing_query" | "repeat_mistake_nudge" - dedup_key: str # (trigger, anchor-class, subject) content hash + anchor: str # ObjectRef: session:[:block:] — citation + confidence: float # 0..1, mirrors assertions.confidence + cite_refs: list[str] = [] # ObjectRefs to evidence (pathology/lesson sessions) + trigger: str # "standing_query" | "repeat_mistake_nudge" + dedup_key: str # (trigger, anchor-class, subject) content hash ``` `build_envelope` (`notification_backends/__init__.py`) gains `family`/`anchor`/`confidence`/`cite_refs` passthrough. Backends stay untouched (they serialize the envelope). diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-5-of-6.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-5-of-6.md index 87d2943033..770c9df563 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-5-of-6.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-5-of-6.md @@ -968,15 +968,15 @@ refusals: ### 1.2 `DemoFinding` schema (new Pydantic model in `demo/models.py`, sibling of `DemoVerifyResult`) ```python -class DemoFinding(ArchiveInsightModel): # frozen, like PathologyFinding - id: str # local slug within the .polydemo - claim: str # human sentence - metric: FindingMetric # {value, unit, kind: point|lower_bound|upper_bound} - evidence_anchor: str # structural column/field name (validated allowlist) - produced_by: str # step id that computed metric - evidence_refs: tuple[EvidenceRef, ...] # reuse core.refs.EvidenceRef - corpus_datasheet_hash: str # copied from frontmatter at compute time - finding_id: str # content address (§1.4) +class DemoFinding(ArchiveInsightModel): # frozen, like PathologyFinding + id: str # local slug within the .polydemo + claim: str # human sentence + metric: FindingMetric # {value, unit, kind: point|lower_bound|upper_bound} + evidence_anchor: str # structural column/field name (validated allowlist) + produced_by: str # step id that computed metric + evidence_refs: tuple[EvidenceRef, ...] # reuse core.refs.EvidenceRef + corpus_datasheet_hash: str # copied from frontmatter at compute time + finding_id: str # content address (§1.4) ``` ### 1.3 Corpus datasheet (pins finding_id to a fixed world) @@ -1471,14 +1471,16 @@ Frozen re-exports: `Session`, `SessionSummary`, `Message`, `Block`, `SessionProf # sdk/client.py — reuse the existing, working bridge; don't reinvent class SyncClient: def __init__(self, archive_root=None, db_path=None, *, check_schema=True): - self._async = api.Polylogue(archive_root, db_path) # existing facade + self._async = api.Polylogue(archive_root, db_path) # existing facade if check_schema: - schema.check_schema(self._async.backend) # pin-and-warn (2c) + schema.check_schema(self._async.backend) # pin-and-warn (2c) + # every read verb: def sessions(self, **kw) -> "Query": return Query(self, spec=SessionQuerySpec.from_kwargs(**kw)) + def _run(self, coro): - return api.sync.bridge.run_coroutine_sync(coro) # existing, loop-safe + return api.sync.bridge.run_coroutine_sync(coro) # existing, loop-safe ``` Ground: `api/sync/bridge.py:run_coroutine_sync` already solves the loop problem the premise blames — SDK reuses it, adding nothing. @@ -1507,12 +1509,16 @@ class Query: # immutable; every op returns a new Query ```python # sdk/schema.py -SDK_INDEX_SCHEMA_RANGE = (24, 24) # generated-checked against INDEX_SCHEMA_VERSION +SDK_INDEX_SCHEMA_RANGE = (24, 24) # generated-checked against INDEX_SCHEMA_VERSION + + def check_schema(backend) -> None: v = backend.user_version("index") lo, hi = SDK_INDEX_SCHEMA_RANGE - if v < lo: raise SchemaTooOldError(v, lo) # hard: SDK newer than archive - if v > hi: warnings.warn(SchemaAheadWarning(v, hi)) # soft: archive rebuilt ahead; reads may miss columns + if v < lo: + raise SchemaTooOldError(v, lo) # hard: SDK newer than archive + if v > hi: + warnings.warn(SchemaAheadWarning(v, hi)) # soft: archive rebuilt ahead; reads may miss columns ``` index.db is a *rebuildable derived tier* — a mismatch is a "rebuild + upgrade SDK" signal, never a migration. The SDK **reads** the pin, it never migrates. `SDK_INDEX_SCHEMA_RANGE` is a generated surface checked against `INDEX_SCHEMA_VERSION` by `render all --check`, so bumping index schema without bumping the SDK range fails CI. @@ -2365,11 +2371,11 @@ Registration stays a role filter — only the split changes: ```python def register_tools(mcp, hooks): - register_read_verbs(mcp, hooks) # query, get, explain, context, correlate, coordinate + register_read_verbs(mcp, hooks) # query, get, explain, context, correlate, coordinate if role_allows(hooks.role, "write"): - register_write_verbs(mcp, hooks) # assert, retract + register_write_verbs(mcp, hooks) # assert, retract if role_allows(hooks.role, "admin"): - register_admin_verbs(mcp, hooks) # maintenance (incl. delete_session) + register_admin_verbs(mcp, hooks) # maintenance (incl. delete_session) ``` - `assert`/`retract` are **single-gated at the verb** (write); no per-kind gate needed because the `WRITABLE` allowlist is validation, not authorization — a read client never sees the verb. This is the key coherence win: 15 write tools with 15 gates → 2 tools, 1 gate, 1 allowlist. diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-6-of-6.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-6-of-6.md index 1ec80cea76..5f67cfd271 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-6-of-6.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-06/bundles/rnd-bundle-6-of-6.md @@ -1971,14 +1971,14 @@ Grounded in the live tree. The load-bearing discovery: **`VectorProvider.query(t ```python @mcp.tool() async def recall( - task_hint: str, # free-text description of current task; embedded as the recall anchor - repos: str | None = None, # CSV include-filter of repo scopes; None = ALL repos (cross-project default) - exclude_repos: str | None = None, # CSV exclude-filter (e.g. drop the current repo to force cross-project) + task_hint: str, # free-text description of current task; embedded as the recall anchor + repos: str | None = None, # CSV include-filter of repo scopes; None = ALL repos (cross-project default) + exclude_repos: str | None = None, # CSV exclude-filter (e.g. drop the current repo to force cross-project) kinds: str | None = "lesson,blocker,correction,caveat,pathology", # evidence kinds to attach - session_limit: int = 6, # top-N similar prior sessions - token_budget: int = 1200, # hard cap on assembled payload token cost - min_similarity: float = 0.35, # cosine floor; hits below are dropped, never padded - statuses: str | None = "active", # assertion lifecycle floor; "active,candidate" to see unjudged (QUOTED) + session_limit: int = 6, # top-N similar prior sessions + token_budget: int = 1200, # hard cap on assembled payload token cost + min_similarity: float = 0.35, # cosine floor; hits below are dropped, never padded + statuses: str | None = "active", # assertion lifecycle floor; "active,candidate" to see unjudged (QUOTED) ) -> str: ... ``` diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-07-design-reports/sessions/replace-actions-view.6a4d620b-b324-83ed-83cd-9b73628ccc19.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-07-design-reports/sessions/replace-actions-view.6a4d620b-b324-83ed-83cd-9b73628ccc19.md index 92dc43f6b4..a38c04cd1f 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-07-design-reports/sessions/replace-actions-view.6a4d620b-b324-83ed-83cd-9b73628ccc19.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-07-design-reports/sessions/replace-actions-view.6a4d620b-b324-83ed-83cd-9b73628ccc19.md @@ -891,6 +891,7 @@ Sketch: ACTION_PAIRING_VERSION = 1 _DAEMON_ACTION_SESSION_PAGE_SIZE = 250 + @dataclass(frozen=True, slots=True) class ActionSourceBlock: session_id: str @@ -909,6 +910,7 @@ class ActionSourceBlock: tool_result_is_error: int | None tool_result_exit_code: int | None + def pair_action_blocks( session_id: str, rows: Sequence[ActionSourceBlock], @@ -964,9 +966,7 @@ def make_actions_stage(db_path: Path) -> ConvergenceStage: conn = sqlite3.connect(f"file:{archive_db}?mode=ro", uri=True, timeout=5.0) try: by_path = _schema_archive_session_ids_for_source_paths(conn, paths) - all_ids = tuple(dict.fromkeys( - session_id for ids in by_path.values() for session_id in ids - )) + all_ids = tuple(dict.fromkeys(session_id for ids in by_path.values() for session_id in ids)) stale = set(_archive_actions_check_sessions(conn, all_ids)) return {path for path, ids in by_path.items() if stale.intersection(ids)} finally: @@ -982,9 +982,7 @@ def make_actions_stage(db_path: Path) -> ConvergenceStage: conn = _open_archive_insight_write_connection(archive_db) try: by_path = _schema_archive_session_ids_for_source_paths(conn, paths) - session_ids = tuple(dict.fromkeys( - session_id for ids in by_path.values() for session_id in ids - )) + session_ids = tuple(dict.fromkeys(session_id for ids in by_path.values() for session_id in ids)) return _archive_actions_execute_sessions(conn, session_ids) finally: conn.close() diff --git a/.agent/handoffs/polylogue-gpt-pro-2026-07-07/6a4cec67-a148-83eb-9a0a-85d09b2d17e5.md b/.agent/handoffs/polylogue-gpt-pro-2026-07-07/6a4cec67-a148-83eb-9a0a-85d09b2d17e5.md index 988b557402..9ff099197e 100644 --- a/.agent/handoffs/polylogue-gpt-pro-2026-07-07/6a4cec67-a148-83eb-9a0a-85d09b2d17e5.md +++ b/.agent/handoffs/polylogue-gpt-pro-2026-07-07/6a4cec67-a148-83eb-9a0a-85d09b2d17e5.md @@ -10501,18 +10501,19 @@ Core model: ```python class ContextCandidate: candidate_id: str - kind: Literal['assertion','coordination_message','handoff','query_result','variant','session_ref','warning'] + kind: Literal["assertion", "coordination_message", "handoff", "query_result", "variant", "session_ref", "warning"] object_ref: ObjectRef | None evidence_refs: tuple[EvidenceRef, ...] - trust_class: Literal['user','accepted','candidate','agent','derived','text_derived'] + trust_class: Literal["user", "accepted", "candidate", "agent", "derived", "text_derived"] freshness_ms: int | None priority: int estimated_tokens: int policy_tags: tuple[str, ...] + class ContextDecision: candidate_id: str - action: Literal['include','omit','defer'] + action: Literal["include", "omit", "defer"] reason: str budget_before: int budget_after: int diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index ff5c883d05..c3b02e8485 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -2239,3 +2239,4 @@ {"id":"int-c4200dd0","kind":"field_change","created_at":"2026-07-28T14:47:46.300926666Z","actor":"Sinity","issue_id":"polylogue-p5li","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"All 6 originally-failing tests from 2026-07-14 confirmed resolved as of 2026-07-28: re-ran each individually (twice for non-flakiness). (1) test_assertion_export_cli_filters_and_writes_json_file -- PASS. (2) test_backup_verify_then_migrate_tier_cli_applies_user_migration_with_receipt -- PASS. (3) test_assertion_export_cli_emits_all_assertions_as_jsonl -- PASS. (4)+(5) test_embedding_orphan_reconcile_cli_apply_removes_rows / test_embedding_orphan_reconcile_cli_apply_is_bounded_by_default -- NO LONGER EXIST (grep confirms the mutate/'apply' flow tests were renamed/removed; the file now has _dry_run_keeps_rows / _plain_dry_run_reports_would_remove_counts / _has_no_mutate_flag instead, consistent with a deliberate redesign to dry-run-only semantics sometime in the last two weeks). (6) test_polylogued_status_json_reports_archive_storage -- PASS. None of these were fixed by this session; they were resolved by other work landing on master in the intervening two weeks. This bead's bounded scope (the 6 named nodes) is fully closed. Force-closing despite the open polylogue-d45p dependency: d45p is a large, ongoing, separate standing-infrastructure epic (a durable evidence-backed verification-failure ledger) that will not close on this bead's timeline -- the dependency reflects 'future dispositions should land through that ledger going forward,' not a hard blocker on closing THIS specific bounded 6-node triage batch once its own scope is verifiably done. d45p remains open and untouched, its own scope unaffected by this closure."}} {"id":"int-a90149dd","kind":"field_change","created_at":"2026-07-28T18:22:51.68664667Z","actor":"Sinity","issue_id":"polylogue-1vpm.6.1","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"AC1-AC7 confirmed satisfied following coordinator review and merge of PR #3375 (2026-07-28T17:50:57Z, commit f1b56e332). Per this bead's own extensive from-source investigation: AC1-5 and AC7 were already satisfied by prior work (typed WorkEvidenceGraph node/edge vocabulary, ObjectRef/EvidenceRef reuse, a real non-Claude Codex fixture proving provider neutrality in test_work_evidence.py, claim nodes as distinct facts never mutating observed effects). This PR closed the one remaining gap, AC6 ('existing delegation/correlation surfaces become projections/adapters or retire, mutation tests fail on task=session/invocation=run/one-attempt-per-call/claim=truth'): polylogue/insights/delegation_work_evidence.py projects the delegations query surface (delegation_facts) onto the shared graph vocabulary without retiring delegation_facts (documented judgment call: it carries honest per-dispatch cost/token/model columns the generic graph doesn't and shouldn't), plus the two previously-missing mutation tests (invocation=run, one-attempt-per-call). Personally reviewed the full diff before merging: confirmed the projection logic, mapping_state->WorkEvidenceAssociationState vocabulary reuse matching session_links's own TopologyEdgeStatus, and anti-vacuity evidence (reverting the ref-kind validator breaks both old and new mutation tests; collapsing call-identity to parent_session_id alone breaks the multi-dispatch-distinct-identity test). Verified: devtools test tests/unit/insights/test_work_evidence.py tests/unit/insights/test_delegation_work_evidence.py -> 9 passed; mypy/ruff clean; devtools verify --quick exit 0. Force-closing despite the open polylogue-h6r dependency: h6r's own notes name its remaining scope precisely -- AC4's WorkerProfileRef/role consumer wiring, extending actor/context derivation into claude_workflow_materializer.py -- a real, separate, un-closed item in a DIFFERENT production graph-builder module, but not something 1vpm.6.1's own AC text (re-read fresh) requires. This is a soft/administrative blocking edge from initial scoping, not a hard technical dependency; h6r remains open and untouched, its own scope unaffected."}} {"id":"int-dba23273","kind":"field_change","created_at":"2026-07-28T19:35:10.912055522Z","actor":"Sinity","issue_id":"polylogue-ovme.2.1","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Fixed and merged via PR #3382 (feature/storage/archive-location-generation-store-migration): (1) IndexGenerationStore constructor migrated to accept ArchiveLocation, preserving first-touch pointer-bootstrap write; (2) OwnedArchiveLocation wired into the online/daemon-driven bulk_rebuild transaction resolve/retire path, mirroring the offline path; (3) devtools lab policy archive-resolver-completeness lands the completeness/visibility gate AC4 asked for, inventorying all 93 call sites of the four duplicate resolvers and preventing growth. Actual migration of those 93 call sites was explicitly out of scope (too large/risky for one session, per this bead's own design note) and is tracked in the new follow-up polylogue-l2cd."}} +{"id":"int-6f799199","kind":"field_change","created_at":"2026-07-29T09:07:21.989494141Z","actor":"Sinity","issue_id":"polylogue-a9hx","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Parser fix landed in b8ac74fc4: standalone apply_patch now exposes the operated path where the tool_path/search_text generated columns read it. Not a generated-column change -- the path is unstructured text in the payload, so no json_extract expression could find it."}} diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index d6dc7c3efe..2eb0d2eb63 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,1137 +1,1212 @@ -{"_type":"issue","acceptance_criteria":"docs/search.md contains the searchable-content matrix matching the live generated column (drift-checked by a test extracting the DDL expression); if include: rebuild plan executed + size delta recorded; a fixture proves a Write-tool body is findable (A) or that the documented workaround finds it (B). Verify: devtools test -k search + render all --check.","assignee":"Sinity","close_reason":"Already satisfied by merged PR #2740: documented exclusion contract in docs/search.md + drift/behavior coverage in tests/unit/storage/test_search_text_write_tool_coverage.py (4 passed, verified by fanout lane 2026-07-12). Option B (documented exclusion + JSON-aware raw-SQL workaround) chosen over reindex.","closed_at":"2026-07-12T20:44:55Z","comment_count":0,"created_at":"2026-07-06T03:17:36Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Construct-validity hunt 2026-07-06: blocks.search_text (archive_tiers/index.py:215, generated column) concatenates text + tool_name + tool_input $.command/$.file_path/$.path \u2014 but NOT $.content, so code an agent WROTE (Write/Edit tool bodies) is invisible to FTS unless it also appears in prose or a tool_result echo. An operator searching for a distinctive string they know an agent authored gets zero hits with no explanation; docs/search.md does not state the coverage boundary. Two defects in one: (a) the searchable-content contract is undocumented, (b) the exclusion itself may be wrong for the flight-recorder claim (what agents wrote IS the work product).","design":"Decide deliberately, then document: option A (include) \u2014 extend the generated column with COALESCE(json_extract(tool_input,'$.content'),'') capped/truncated (Write bodies can be huge; FTS index size impact must be measured on the live archive first \u2014 a size probe belongs in the decision evidence), derived-tier regime: DDL edit + index rebuild, batch per 60i5; option B (exclude, document) \u2014 docs/search.md gains a searchable-content matrix (block text yes, thinking yes/no?, tool command/path yes, tool file bodies NO + workaround: actions-view tool_input query), and empty-result guidance (jnj.12) mentions the boundary when a query matches tool_input via a slow LIKE probe. Either way the contract becomes explicit. Check thinking-block searchability claim at the same time (text column carries thinking -> searchable today \u2014 confirm docs say so).","id":"polylogue-013x","issue_type":"task","labels":["area:query","area:storage","delivery:C-read-evidence-contract","horizon:frontier","lane:read-contracts","tech-tree"],"notes":"PR #2740 (branch fix/search-text-write-tool-coverage) opened, not merged/closed.\n\nDecision: implemented option B (document + workaround) from the design, not\noption A (extend search_text generated column). Rationale: option A is a\nderived-tier schema change requiring a live-archive FTS index size probe as\ndecision evidence (Write bodies can be large enough to bloat the index) plus\n`polylogue ops reset --index && polylogued run`; neither is available/\nappropriate from an isolated worktree PR done under a lean-verification\ndirective (many parallel agents running that night). The repo's derived-tier\nschema regime also says such bumps should be batched from ready beads, not\ndone as an isolated silent schema change.\n\nWhat shipped:\n- docs/search.md: new \"Searchable Content Coverage\" section \u2014 table of what\n feeds blocks.search_text (confirms thinking/reasoning block text AND\n tool_result output ARE searchable today) vs what's excluded (Write's\n tool_input.$.content, Edit's $.old_string/$.new_string, any other\n tool_input key), plus a raw-SQL json_extract/LIKE workaround query.\n Empty Result Diagnostics checklist gets a pointer to this section.\n- tests/unit/storage/test_search_text_write_tool_coverage.py: (1) drift check\n extracting the live search_text DDL expression from index.py and asserting\n it matches the documented matrix, (2) proves a Write/Edit tool-body token\n is genuinely unreachable via messages_fts MATCH, (3) proves the documented\n workaround query finds it.\n\nAC status against the bead's original acceptance criteria:\n- \"docs/search.md contains the searchable-content matrix matching the live\n generated column (drift-checked by a test...)\" -> SATISFIED.\n- \"if include: rebuild plan executed + size delta recorded\" -> N/A, option B\n chosen instead of option A (include).\n- \"a fixture proves a Write-tool body is findable (A) or that the documented\n workaround finds it (B)\" -> SATISFIED via (B).\n- \"Verify: devtools test -k search + render all --check\" -> ran the focused\n new test file + full pre-push quick gate (ruff/mypy/render-all/topology/\n layering/etc, all green); did not run a blanket `-k search` sweep per the\n operator's lean-verification directive for this session.\n\nNot closing this bead per instruction -- leaving it to the coordinator to\nreview/merge/close. If the operator later wants option A (schema extension),\nthat's still open as follow-up work: needs a live-archive size probe + a\nbatched derived-tier index rebuild plan, not a fold into this PR.\nMerged PR #2740: documented the boundary (docs/search.md 'Searchable Content Coverage') + raw-SQL workaround, rather than extending search_text (deferred, needs a live FTS index size probe + derived-tier rebuild before deciding, not an isolated schema bump). 4 tests passed including a DDL-vs-docs drift check.\n2026-07-12 stale-claim audit: claim released; holder was a session-quota-killed wave-3 agent. Re-claim on real work start.","owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-12T05:17:00Z","status":"closed","title":"search_text excludes Write-tool file bodies (tool_input.$.content) \u2014 undocumented coverage gap","updated_at":"2026-07-12T20:44:55Z"} -{"_type":"issue","acceptance_criteria":"Protected paths declared in a validated manifest with reasons; temporarily renaming test_crud.py fails devtools verify --quick (demonstrated, then restored). VERIFY: devtools verify --quick output in notes.","close_reason":"Premise didn't hold up on investigation (2026-07-14 reconciliation pass): the 'protected test files' list this bead wanted to move from CLAUDE.md prose into a validated manifest has no documented reason for any of its 6 entries anywhere in project history. Traced it to its origin (PR #134, an unrelated DB-performance PR that bolted the list on as incidental doc scaffolding with zero justification) and confirmed it was never revisited or expanded across ~2500 subsequent PRs. Building manifest+gate enforcement for an unreasoned, unmaintained list would launder its arbitrariness behind a false patina of rigor rather than fix a real problem -- a category-level post-hoc justification (property tests/integration/security/foundational-CRUD look prunable) was tried and rejected as unfalsifiable: the same reasoning shape would defend any random file subset equally well. Removed the CLAUDE.md prose line outright instead of encoding it. If specific test coverage genuinely needs protecting, that should be established by evidence (unique-assertion/coverage analysis) at the time, not inherited from an unexplained list.","closed_at":"2026-07-15T01:15:45Z","comment_count":0,"created_at":"2026-07-08T17:32:36Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"The protected-test-files list (tests/unit/sources/test_parsers_props.py, test_null_guard_properties.py, tests/unit/core/test_properties.py, tests/integration/, tests/unit/security/, tests/unit/storage/test_crud.py) is enforced only by CLAUDE.md prose. Some appear incidentally in devtools/mutation_scenario_catalog.py, but a deletion or rename would otherwise pass every gate silently - the suite cannot notice tests that no longer exist.\n","design":"Smallest honest mechanism: add a protected-paths section to an existing manifest (docs/plans/test-quality-coverage.yaml fits; avoid a 17th manifest) listing the protected files/dirs with reasons, and have verify manifests (devtools/verify_manifests.py already validates path existence patterns for the closure matrix) assert each path exists. This also gives the list a durable home outside operator-memory prose.\n","id":"polylogue-02aw","issue_type":"task","labels":["area:test","horizon:frontier"],"owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"Lint: protected test files must exist (manifest-backed, not prose-backed)","updated_at":"2026-07-15T01:15:45Z"} -{"_type":"issue","acceptance_criteria":"Rescue command lands with tests against a synthetic retired-tier fixture; on the live archive post-promote: rescued-vector count reported, sampled byte-identity checks pass, embedding catch-up backlog shrinks by the rescued count; decision recorded on command-vs-convergence placement; retired-file retention decision left to operator.","assignee":"Sinity","comment_count":0,"created_at":"2026-07-19T13:33:05Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"design":"Investigation 2026-07-19: /realm/db/polylogue/embeddings.db.v2-retired-20260718 (5.8GB, retired during the incident) holds 776,895 vec0 vectors (voyage 1024-dim) whose message_embeddings_meta rows bind each vector to model + a 32-byte content_hash. The new index computes the same content-hash identity for messages, so an EXACT rescue is possible: for each retired vector whose message_id exists in the promoted index AND whose stored content_hash matches the index message content_hash AND whose model matches the current embedding config, insert the vector + meta into the fresh embeddings.db (same vec0 schema, dimension 1024). The daemon embedding catch-up then only embeds the genuinely-new/changed remainder. Payoff: avoids re-embedding ~777K messages through the Voyage API (nontrivial cost + days of rate-limited catch-up) and brings semantic search back within hours of promote \u2014 outreach-relevant. Implementation: an ops maintenance command (break-glass diagnostic per automagic doctrine, one-shot) or a daemon convergence fast-path that consults a configured rescue source; the ops command is simpler and honest for a one-time migration \u2014 decide and record. Batch-insert via the sync embeddings writer; verify by sampled cosine-identity (rescued vector == retired vector bytes) + count reconciliation (rescued + pending == eligible messages). Constraint: run AFTER index promote (needs final message content hashes); embeddings tier is rebuildable so failure mode is benign (reset and re-run). The retired file is read-only evidence \u2014 never mutate it; keep until rescue verified, then it can be archived/deleted with operator consent.","id":"polylogue-04kl","issue_type":"task","notes":"Implemented + PR opened: https://github.com/Sinity/polylogue/pull/3160\n(feature/storage/embeddings-rescue).\n\nScope delivered: polylogue ops maintenance embeddings-rescue (--plan\nread-only census / --yes apply) in polylogue/storage/embeddings/rescue.py +\nCLI wiring. Command-vs-convergence placement decided: command (offline-only\nin this version), per the design note's own preference -- simplest and\nhonest for a one-time migration. Offline guard reuses\noffline_maintenance_block_reason/running_daemon_pid (embedding-orphan-reconcile\npattern), not RebuildLease (this path only inserts, never deletes).\n\nDesign refinement found during implementation, not assumed up front: rescue\nmust be scoped to whole sessions, not individual messages.\nembed_archive_session_sync always re-embeds every eligible message of a\nsession it selects in one atomic write, never consulting pre-existing\nper-message vectors -- so partial per-message rescue saves nothing; only a\nsession where 100% of its eligible messages have an exact retired\n(message_id, content_hash, model) match is worth writing. Publication goes\nthrough begin_embedding_attempt + complete_embedding_attempt_success (the\nsame primitives the live embed path uses), so rescued sessions read as\nalready-fresh to the daemon's own freshness predicate: idempotent reruns,\nresumable via --limit, no bespoke generation tracking.\n\nAC status:\n- Rescue command + tests against synthetic retired-tier fixture: satisfied\n (12 tests: plan classification incl. missing/hash_mismatch/model_mismatch,\n execute rescues only fully-matched sessions, idempotent rerun, --limit +\n more_pending, mutation-authority guard, and an anti-vacuity corrupted-copy\n case proving the sample-verification step actually catches a bad write).\n- Live post-promote rescued-vector count + sampled byte-identity: NOT run\n from this PR -- explicitly coordinator-owned, deferred until after index\n promote per the design note's own constraint (\"run AFTER index promote\").\n Read-only --plan smoke run against the real archive (mid-rebuild,\n 2626 sessions) + real retired file today: eligible_sessions=2541,\n fully_rescuable_sessions=703, rescuable_messages=14458, partial_sessions=645\n (6549 matched messages left unrescued by design), skipped_missing=23541,\n skipped_hash_mismatch=17744, skipped_model_mismatch=0.\n- Decision recorded (command vs convergence): command, offline-only v1;\n daemon-coordinator route noted as a follow-up, not filed as a separate\n bead yet.\n- Retired-file retention: untouched, left to operator per the design note.\n\nLeaving this bead OPEN: live --yes execution against the production archive\nhappens post-promote and is coordinator-owned, not this agent's call to run.\n2026-07-20 operator ruling + ordering change: rescue execution should land vectors directly into the content-addressed embeddings layout (new bead above, vectors keyed by identity-free H(model, input text) instead of identity-contaminated messages.content_hash) so we migrate once, not twice. Design the keying first, then run the rescue into it.\n\n2026-07-28 LIVE EXECUTION (coordinator-run, post index-promote as the design required): ran the deferred live rescue against production archive. --plan against real archive: eligible_sessions=17261, fully_rescuable_sessions=8312, rescuable_messages=187888. Executed in two steps (50-session test batch, then full remaining 8262 sessions, daemon stopped for the offline-exclusive mutation window both times, restarted after):\n- rescued_sessions=8312 total (50+8262), rescued_messages=187888, more_pending=False (no further content-hash-rescuable sessions remain from this retired source).\n- partial_sessions=528 (7111 matched messages) intentionally left unrescued per design (rescue only ever writes a session atomically when 100% of its eligible messages have an exact retired match).\n- Sample-verification reported \"ok\": false (17-20/20 byte-identical) on both runs \u2014 investigated this personally rather than trusting the tool's own verdict or treating it as a red flag. Root cause confirmed via direct message-content inspection: message_embeddings is correctly content-hash-deduped (keyed by embedding_input_hash), so when many DISTINCT messages share byte-identical text (extremely common in agent transcripts: empty `` blocks, \"ok\", short tool acks), only one canonical vector is stored. The verification step compares that canonical vector against one SPECIFIC message's own original per-message retired vector; for any other message sharing that hash, the comparison necessarily \"fails\" even though the stored vector is a real, valid embedding of the identical text (the small numeric deltas observed, e.g. 0.010160 vs 0.010032, are consistent with the OLD per-message pipeline's non-deterministic embedding-API variance across separate calls for identical input, not corruption). Confirmed no hash collisions between genuinely-different text. This is a tool/verification-methodology limitation (comparing against one arbitrary occurrence instead of \"any occurrence sharing this hash\"), not a data-safety bug \u2014 the rescue itself is correct. Filed as a real but low-priority follow-up: embeddings-rescue's sample-verify should compare against any retired row sharing the same message's post-dedup hash, not require exact match against that one message's own historical row.\n- Post-run direct verification (embedding_status_payload against live index.db+embeddings.db): embedded_sessions=8312, embedded_messages=187888, embedding_coverage_percent=44.1 (of 18863 total sessions), retrieval_ready=True. Confirmed real, not just self-reported: embedding_status table sum(message_count_embedded)=187888 matches message_embedding_refs row count exactly.\n- Noted separately: `polylogue ops status --json --full` daemon status surface still reports embeddings component as coverage_pct=0.0/state=missing/retrieval_ready=False after this rescue and after a full daemon restart, because the embedding daemon-stage is config-disabled (daemon_stage_enabled=False) on this host, which makes the daemon's own cached component-readiness path diverge from a direct payload computation. Confirmed the divergence is a status-surface staleness/disabled-stage gap, not a data problem \u2014 direct query is authoritative and shows full coverage. Not filed as a separate bead this session (real cost/benefit is low: retrieval works, only the cached daemon status surface is misleading when the daemon-stage toggle is off); worth a follow-up if it recurs or if daemon-stage embedding gets enabled and the same staleness appears.\n\nReal production win: 187,888 message vectors recovered from the retired 2026-07-10 backup at zero re-embedding API cost, taking archive-wide semantic search coverage from 0% to 44.1% of sessions without spending anything on Voyage API calls for those messages.\n\nBead remains open: retired-file retention decision still left to operator per the design note; 528 partial sessions + the rest of the 17261-8312=8949 non-fully-rescuable eligible sessions still need real API embedding (separate from this rescue path); the sample-verify methodology limitation noted above is a real, low-priority tooling improvement, not filed as a separate bead yet.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-19T14:02:45Z","status":"in_progress","title":"Rescue 777K vectors from the retired embeddings tier by content-hash instead of re-embedding via API","updated_at":"2026-07-28T13:04:52Z"} -{"_type":"issue","acceptance_criteria":"1. A job is queryable in the receiver registry with stable id, safe provider/account scope, versioned intent, monotonic revision/checkpoint, lease, request budget, receipts, retention state, and incident/event history. 2. Re-seeding the whole browser profile allows an explicit new client to discover/adopt the correct job without replaying acknowledged pages or exposing credentials. 3. Deleting IndexedDB/chrome.storage proves they are caches; receiver state rehydrates both recovery UI and the per-conversation reverse-chron timeline. 4. Capture, detected-new, held-with-reason, first-seen, explicit no-op, adoption/resume/completion events use idempotent ids, exact refs, receiver ordering, and are queryable through daemon/read surfaces. 5. Compare-and-swap rejects an older/equal conflicting checkpoint or event revision; out-of-order requests cannot regress cursor, receipts, or incident history. Duplicate reconnects, lease expiry, incompatible versions, concurrent adoption, and event replay fail or resume visibly/idempotently. 6. Quota is checked on overwrite/event growth and GC cannot delete leased, unacknowledged, operator-held, or timeline-authoritative state; orphan policy is explicit. 7. A real extension-to-loopback profile-loss fixture covers create, out-of-order checkpoint/events, identity loss, discovery/adoption, resume, exact-once effects, timeline reconstruction, completion, and eligible GC. 8. Existing #2819/#2871 checkpoints/local events migrate or remain discoverable; removing the receiver registry, monotonic guard, or event projection makes the fixture fail.","comment_count":0,"created_at":"2026-07-12T20:47:43Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"A browser-local job id or extension-instance id cannot be the durability authority for long-running capture work. PRs #2819/#2871 made IndexedDB and chrome.storage recoverable and mirrored checkpoints to the loopback receiver, but a whole-profile wipe mints a new extension instance and strands the old receiver checkpoint. Quota/GC were then filed separately. These are one missing abstraction: a receiver-authoritative durable job registry with stable job identity, leases, checkpoints, incident history, adoption, and retention independent of any browser profile.","design":"Make the loopback receiver the authority for a typed CaptureJob record keyed by stable content-independent job id and safe account/provider scope token. Browser instances are replaceable leased clients, not owners. The registry stores versioned request intent, cursor/checkpoint, completed-page/result receipts, retry budget, compatible client version, current lease, retention/hold state, and an append-only CaptureJobEvent stream (created, first-seen, detected-new, capture attempted/acknowledged, held-with-reason, explicit no-op, adopted, resumed, completed, abandoned). Events carry conversation/message/evidence refs and idempotent ids; per-conversation timelines are projections, not a browser-only ledger. After profile loss, a client explicitly discovers/adopts a scope-compatible job; it never guesses across accounts. Checkpoint/event writes use compare-and-swap semantics and quota includes overwrite growth. GC cannot delete leased, unacknowledged, held, or timeline-authoritative jobs/events. IndexedDB/chrome.storage remain caches; old per-instance checkpoints and local timeline events migrate or surface as orphans.","id":"polylogue-06zm","issue_type":"epic","labels":["area:capture","delivery:B-storage-rebuild-bytes","horizon:frontier"],"notes":"2026-07-14: implemented PARTIAL scope in PR #2871 (branch feature/browser-ext/checkpoint-mirror-and-message-layer). Shipped: new POST/GET /v1/backfill-checkpoint routes on the local receiver (polylogue/browser_capture/{models,receiver,route_contracts,server}.py) -- one JSON file per extension_instance_id, last-write-wins, same write-lock/quota pattern as the existing capture spool and post-command queue; receiver treats the checkpoint body as opaque JSON (same trust boundary as the capture-envelope route). Extension side (background.js): mirrors every checkpoint persist to the receiver, decoupled from the local chrome.storage.local write so a receiver outage never surfaces as a checkpoint error; on coordinator construction, if both IndexedDB and the local checkpoint copy are empty, falls back to GET-ing the receiver's mirrored checkpoint and restoring from it.\n\nAC status: AC1 (receiver-owned durable ledger visible) satisfied. AC2/AC3 (profile loss doesn't lose the job; IndexedDB+local-copy demonstrably not the only durable source) satisfied for the case where IndexedDB AND the local chrome.storage.local copy are BOTH lost but the extension_instance_id itself survives. AC4 (idempotent duplicate reconnects) satisfied via the pre-existing restoreRecoveryCheckpoint empty-IndexedDB guard. AC5 (integration fixture) satisfied at the Python HTTP-route level (real server, real POST+GET round trip, tests/unit/browser_capture/test_backfill_checkpoint.py, 12/12 passing) and the JS level (background.test.js, 4 new cases); NOT a true extension-to-daemon browser E2E fixture (no live browser in this environment).\n\nEXPLICITLY NOT DONE (do not close on this evidence alone): a whole-profile wipe that ALSO destroys extension_instance_id (which lives in the same chrome.storage.local) cannot self-correlate to its old mirrored checkpoint on the receiver -- there is no operator-facing \"adopt an orphaned checkpoint by browsing the receiver's stored instances\" flow. That is real, separate follow-up work. Verification: devtools test tests/unit/browser_capture/test_backfill_checkpoint.py (12/12), devtools test tests/unit/browser_capture/ (101/101, no regression), devtools verify --quick (15/15), npx vitest run (236/236 browser-extension suite). See PR #2871 for full detail.\n2026-07-14 fix round (reviewer pass on PR #2871): fixed reviewer-confirmed MAJOR finding -- BrowserBackfillCheckpointRequest.coerce_checkpoint (and the twin validator on BrowserBackfillCheckpointRecord) used json_document(value), which silently coerced any non-dict checkpoint (string/null/list/number) to {} instead of rejecting it, so a malformed POST to /v1/backfill-checkpoint returned HTTP 202 success while overwriting a previously-good stored checkpoint with an empty one -- directly undermining this bead's durable-ledger AC1. Renamed both validators to require_checkpoint_document and made them raise ValueError (-> pydantic ValidationError -> HTTP 400 invalid_backfill_checkpoint via the server's existing except ValidationError handler) for any non-dict value, matching the module's own require_json_document convention used elsewhere for producer-contract enforcement. Also fixed the read-path twin so a corrupted on-disk checkpoint file surfaces as read_backfill_checkpoint()->None (no checkpoint found) rather than a fabricated empty-but-'valid' checkpoint. Added 7 regression tests in tests/unit/browser_capture/test_backfill_checkpoint.py: non-dict rejection on both Request and Record (parametrized over string/None/int/list), corrupted-file-on-disk reads as None, a prior-good checkpoint is NOT overwritten by a malformed follow-up write, and the exact HTTP-level reviewer repro (POST checkpoint='garbage-not-a-dict' -> 400, prior good checkpoint on disk unchanged). Verification: devtools test tests/unit/browser_capture/test_backfill_checkpoint.py (23/23), devtools test tests/unit/browser_capture/ (112/112, no regression), devtools verify --quick (15/15 steps green). Reviewer's two minor/non-blocking findings (quota not re-checked on same-instance overwrite growth; no GC for orphaned per-instance checkpoints after a profile reseed mints a new instance id) filed as follow-up polylogue-yky4 rather than fixed here -- both need a real design decision, not a mechanical fix. See PR #2871 for the updated diff.\n[2026-07-15 invariant-collapse pass] This invariant absorbs polylogue-yky4. Overwrite quota and orphan GC are lifecycle policies of the same receiver-authoritative job registry, not a later cleanup project. Previously shipped per-instance checkpoint mirroring is treated as a migration input, not the target authority model.\nPortfolio convergence 2026-07-15: absorbs the remaining substrate scope of 4g3n. Its browser-local reverse-chron timeline already landed; receiver mirroring, profile-reseed reconciliation, and queryability are projections of the durable capture-job event stream, not a parallel ledger.\nInvariant collapse 2026-07-15: absorbs mpig\u2019s checkpoint-ordering finding. Monotonic CAS is fundamental receiver-authority behavior, not an adjunct patch.\n2026-07-15 delivery-shape correction: retained 06zm as the class-level receiver-authoritative CaptureJob invariant and split execution into 06zm.1 registry/identity/lease/adoption core, 06zm.2 durable event projections and recovery/timeline surfaces, and 06zm.3 quota/retention/migration/terminal profile-loss proof. s8gb moved to jlme because oversized-capture postflight is capture reliability, not job identity. No ambition or parent AC was removed.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Make browser recovery jobs durable across client identity loss","updated_at":"2026-07-15T18:07:40Z"} -{"_type":"issue","acceptance_criteria":"1. Receiver create/get/list/adopt/update operations expose stable job id, safe scope, versioned intent, monotonic revision/checkpoint, current lease, retry/hold state, receipts, and compatible-client policy. 2. A whole-profile wipe that also changes extension_instance_id can discover and explicitly adopt only the correct scope-compatible job, without credentials, cross-account disclosure, or acknowledged-page replay. 3. Concurrent adoption, expired leases, incompatible clients, duplicate reconnects, and older/equal conflicting checkpoints fail or resume visibly/idempotently; removing CAS or lease checks breaks the production-route fixture. 4. Deleting IndexedDB and chrome.storage rehydrates the recovery state from the receiver; they are not durability authorities. 5. Existing mirrored per-instance checkpoints migrate or surface as typed orphans; focused receiver/extension tests and quick gate pass.","assignee":"Sinity","close_reason":"Satisfied by merged PR #2953 (e6698a74e): receiver-authoritative stable CaptureJob identity/scope/intent, CAS revisions and checkpoints, idempotent receipts, replaceable leases/adoption, exact-account profile-loss recovery, receiver-to-cache rehydration, and typed legacy orphans. Verification: receiver 7 passed; daemon auth 19 passed; extension 313 passed; lint and manifest passed; quick gate 16/16; five adversarial passes ended with no legitimate gaps. Events/timeline and lifecycle quota/retention/migration remain in 06zm.2 and 06zm.3.","closed_at":"2026-07-16T19:05:21Z","comment_count":0,"created_at":"2026-07-15T18:07:36Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:07:36Z","created_by":"Sinity","depends_on_id":"polylogue-06zm","issue_id":"polylogue-06zm.1","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":2,"description":"Replace browser-profile/extension-instance ownership with a receiver-authoritative CaptureJob registry. This core slice establishes stable job identity, safe provider/account scope, versioned intent, monotonic checkpoints/receipts, replaceable client leases, and explicit profile-loss discovery/adoption. Existing per-instance mirrored checkpoints are migration evidence, not the target model.","design":"Define typed CaptureJob and CaptureJobLease records in the receiver durable boundary. Stable job ID is content-independent; safe account/provider scope permits explicit discovery without credentials or cross-account guessing. Checkpoint, acknowledged-page/result receipts, retry budget, compatible client version, hold state, and revision update through compare-and-swap. Browser instances acquire/renew/expire leases and can explicitly adopt a compatible orphan after whole-profile loss. IndexedDB/chrome.storage rehydrate from receiver state and are proven caches. Preserve receiver single-writer and authentication boundaries.","id":"polylogue-06zm.1","issue_type":"feature","labels":["area:browser","area:capture","area:storage","horizon:frontier"],"notes":"2026-07-15 external Sol Pro pilot evidence: validated handoff SHA-256 8f37aa16b083c357c32b426d44379c96ef49acd692f7b569b2d5f4d8fc8470fd proposes a SQLite BEGIN IMMEDIATE/CAS LaunchJob store with row revisions, lease epochs, hashed bearer lease tokens, and append-only hash-chained events. Its patch cleanly applies only because it adds a parallel store beside the current atomic-JSON launch queue; do not merge wholesale. Use its DESIGN/ARCHITECTURE.md and launch_store.py as implementation input for this bead's shared CaptureJob registry, reconciling the operator correction that only upload/preflight/submit is serialized while submitted chats run in parallel. The submission_unknown quarantine was transplanted into yyvg.5 immediately; transactional registry/identity/adoption remains here.\n2026-07-16 integration scope: receiver-authoritative CaptureJob registry, safe scope discovery/adoption, versioned intent, monotonic CAS checkpoints/receipts, replaceable expiring leases, client compatibility, and extension cache rehydration. Constraints: preserve authenticated single-writer loopback boundaries plus ordinary capture/backfill and merged #2919-#2921 queue/quarantine/closed-tab behavior; do not implement event projections (06zm.2) or retention policy (06zm.3). I will use production-route fixtures for profile/state loss, adoption races, leases, client versions, reconnects, and checkpoint conflicts; IndexedDB/chrome.storage remain caches. Handoff material is reference, reconciled to current architecture rather than pasted.\n2026-07-16 GPT-Pro corpus adjudication: package 3ca08cd43d04d66114ba5f44df64b73eab9ab4f31826ed87548a6d8b7de4393a (ChatGPT 6a57f545-56a0-83eb-b961-e81c7d030e70, Durable CaptureJobs) was hash-validated and reconciled on fresh origin/master. The preserved branch feature/integration/capture-job-authority contains ba340c71a/8ecc34ecc: receiver SQLite stable IDs, keyed scope, CAS revisions/checkpoints, lease proofs, idempotent receipts and protocol bounds. Its focused HTTP fixture passed 2 tests and quick verification passed 16 gates; current-master opaque mirror control route passed 23 tests. Do not merge wholesale: the extension adapter falls back to paired: when no real stable account handle exists, which cannot prove exact-scope/no-cross-account discovery after profile loss and conflicts with current generic BrowserAction transport. Seeded continuation: first make each supported provider adapter expose a stable non-secret account handle; then port registry semantics through current receiver contracts and prove packaged whole-profile loss (including concurrent adoption, lease expiry, incompatible client, CAS conflict and cache rehydration). Current per-instance mirror is migration input, not authority.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-16T02:30:00Z","status":"closed","title":"Land receiver-authoritative CaptureJob identity, leases, and adoption","updated_at":"2026-07-16T19:05:21Z"} -{"_type":"issue","acceptance_criteria":"1. Every declared event kind is produced by a real extension/receiver route with stable id, receiver order, job revision, exact refs, and idempotent replay; removing a producer or event registration fails completeness. 2. Recovery status and per-conversation reverse-chron timeline reconstruct from receiver state after browser-local stores are deleted, with no browser-only ledger. 3. Bounded authenticated API/CLI/MCP/web projections agree on job/event refs, ordering, states, totals/continuation, and disclosure; unknown/offline/held/no-op remain distinct. 4. Out-of-order events cannot regress checkpoint or incident state, and duplicate reconnect/replay yields exact-once visible effects. 5. Focused extension-to-receiver and surface parity tests plus quick gate pass.","comment_count":0,"created_at":"2026-07-15T18:07:37Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:07:37Z","created_by":"Sinity","depends_on_id":"polylogue-06zm","issue_id":"polylogue-06zm.2","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T20:07:37Z","created_by":"Sinity","depends_on_id":"polylogue-06zm.1","issue_id":"polylogue-06zm.2","metadata":"{}","type":"blocks"}],"dependency_count":1,"dependent_count":1,"description":"Make capture progress, incidents, no-ops, holds, adoption, and completion durable/queryable once CaptureJob identity exists. Browser-local status and reverse-chron timelines become projections of one append-only receiver event stream rather than parallel ledgers.","design":"Define CaptureJobEvent identities and schemas for created, first-seen, detected-new, capture-attempted, acknowledged, held-with-reason, explicit-no-op, adopted, resumed, completed, and abandoned. Events bind job revision plus conversation/message/evidence refs where applicable and append idempotently under receiver order. Expose bounded authenticated job/event reads through daemon/CLI/MCP/web contracts. Recovery UI and per-conversation timeline derive from these rows and preserve unknown/offline/degraded states; display grants no instruction authority.","id":"polylogue-06zm.2","issue_type":"feature","labels":["area:browser","area:capture","area:daemon","area:surface","horizon:frontier"],"owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Project CaptureJob events into recovery and conversation timelines","updated_at":"2026-07-15T18:07:37Z"} -{"_type":"issue","acceptance_criteria":"1. Quota rejects current-plus-overwrite/event growth before mutation and reports observed/limit bytes; same-ID overwrites cannot bypass it. 2. Dry-run GC/retention plans and receipts prove leased, unacknowledged, held, orphaned, and timeline-authoritative jobs/events survive; only terminal eligible state is removed. 3. Existing per-instance checkpoints/local timeline events migrate without credentials or are queryable as typed orphans with adoption/abandonment action. 4. A packaged extension-to-loopback profile-loss fixture covers the full designed journey and proves acknowledged pages/effects are exact-once; removing receiver authority, CAS, event projection, quota, or retention guard makes it fail. 5. Operational status exposes counts/debt/actions, focused tests and quick gate pass, and live postflight records residual orphan/held populations.","comment_count":0,"created_at":"2026-07-15T18:07:38Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:07:38Z","created_by":"Sinity","depends_on_id":"polylogue-06zm","issue_id":"polylogue-06zm.3","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T20:07:39Z","created_by":"Sinity","depends_on_id":"polylogue-06zm.1","issue_id":"polylogue-06zm.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-15T20:07:39Z","created_by":"Sinity","depends_on_id":"polylogue-06zm.2","issue_id":"polylogue-06zm.3","metadata":"{}","type":"blocks"}],"dependency_count":2,"dependent_count":0,"description":"Complete the durable CaptureJob lifecycle after registry and event projections land. Quota must account for overwrite/event growth; GC and abandonment must preserve leased, unacknowledged, held, and timeline-authoritative evidence; old per-instance state must migrate or remain explicitly orphaned. The terminal proof is a real extension-to-loopback whole-profile-loss journey.","design":"Add retention states and policy over job plus event reachability, with dry-run plan, authorization, CAS revalidation, receipts, and postflight. Count current+replacement bytes and append growth before writes. GC excludes live leases, unacknowledged receipts, operator holds, unresolved adoption/orphans, and timeline-authoritative events. Migrate #2819/#2871 local/mirrored checkpoint and event shapes into jobs or an explicit orphan queue. Run create -> out-of-order checkpoint/events -> whole-profile identity loss -> discovery/adoption -> resume -> exact-once effects/timeline -> completion -> eligible GC through real packaged extension and receiver.","id":"polylogue-06zm.3","issue_type":"task","labels":["area:browser","area:capture","area:ops","area:storage","horizon:frontier"],"owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Close CaptureJob retention, quota, migration, and profile-loss proof","updated_at":"2026-07-15T18:07:38Z"} -{"_type":"issue","comment_count":0,"created_at":"2026-07-18T13:28:16Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"render_session_read_page (polylogue/daemon/webui.py) slices to the first\nSESSION_READ_MESSAGE_LIMIT messages for display, but _do_archive_get_session\n(polylogue/daemon/http.py) still composes every message, attachment, and\nsemantic-card placement for the WHOLE session before that slicing happens.\nFor large sessions (long-running agent transcripts, thousands of messages)\nthis makes first paint of /app/sessions/:id proportional to the complete\ntranscript instead of the bounded page, defeating pagination and risking\nrequest-thread exhaustion.\n\nFlagged by CodeRabbit on PR #3091 (webui-02 session list + read views).\n\nFix direction: add a substrate-level bounded session-header/message-page\nreader (header fields without full message materialization, then a\npaged message fetch) and have the SSR path use it instead of\n_do_archive_get_session. Add a regression test proving reads stay\nbounded for sessions exceeding SESSION_READ_MESSAGE_LIMIT.","id":"polylogue-07g6","issue_type":"bug","notes":"2026-07-18 Phase 1 fix (lane-e followup): shipped read_archive_session_page (storage/sqlite/archive_tiers/write.py) + ArchiveStore.read_session_page -- bounded [offset,offset+limit) SQL composition for ordinary sessions, full-compose-then-slice fallback for prefix-sharing lineage children (matches get_messages_paginated precedent). _do_archive_get_session takes optional limit/offset; only SSR session-read + paged messages API pass them, JSON session API/stack/compare stay full-composition. ArchiveSessionEnvelope.total_message_count carries the true total for bounded reads. Regression proves SQL statement count is independent of session size (20 vs 2000 msgs, both bounded <15 statements), not wall-clock timing. devtools test on both touched test files: 240 passed, 1 pre-existing unrelated failure (verified via git stash against base commit). mypy --strict, ruff format/check, render all --check, devtools verify --quick (16 steps) all clean. PR: https://github.com/Sinity/polylogue/pull/3127","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Bound session read SSR transcript hydration for large sessions","updated_at":"2026-07-18T21:17:12Z"} -{"_type":"issue","assignee":"Sinity","close_reason":"Resolved: parse-failed raw materialization rows are now distinguished from stale decode-missing-blob aliases. Live archive readiness reports parse_failed=0/actionable=0 while preserving raw_parse_failed=57 as historical evidence; /api/archive-debt no longer reports parse-failed raw debt after daemon restart. Remaining raw-materialization rows are two blocked missing-blob records, outside this bead.","closed_at":"2026-07-05T07:21:04Z","comment_count":0,"created_at":"2026-07-05T07:08:25Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Why: after automatic raw blob span restoration and replay, the live archive still reports raw materialization debt as two issue groups with 57 parse-failed raw artifacts. That is no longer a replayable missing-blob backlog, but it still means some source artifacts failed before producing materialized sessions or classified non-session evidence. What: classify the parse failures by source family/path/parser error, fix parser or acquisition bugs where the artifact is session-bearing, and demote/record genuinely non-session or unrecoverable artifacts so root query/readiness surfaces can report a clean invariant.","id":"polylogue-07hj","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-05T07:10:08Z","status":"closed","title":"Resolve parse-failed raw materialization debt","updated_at":"2026-07-05T07:21:04Z"} -{"_type":"issue","comment_count":0,"created_at":"2026-07-28T19:52:25Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"tests/build.test.js > build.mjs full archive emission > executes the packaged service worker fixture without foreground tab activation fails with 'expected false to be true' on a vi.waitFor() timing assertion around line 274 (pageRequests.some(...) check after polylogue.backfill.start). Observed as a pre-existing failure across multiple uncapped and capped npm test runs during polylogue-0v5b (worker concurrency cap) work 2026-07-28, unrelated to that change (fails identically at 4, 8, and 24 workers). Needs investigation: likely a timing/race issue in the fake service-worker backfill fixture rather than the worker-cap change.","id":"polylogue-07pt","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Flaky timing assertion in browser-extension build.test.js backfill archive test","updated_at":"2026-07-28T19:52:25Z"} -{"_type":"issue","acceptance_criteria":"1. The original periodic embedding catch-up test reproduces deterministically under a bounded clock and records which completion signal is absent. 2. The production convergence path emits exactly one terminal catch-up state for an empty backlog and for a drained non-empty backlog; polling cannot loop forever on repeated queued=0 success events. 3. The focused test completes under ten seconds in ten consecutive runs without increasing its timeout. 4. A mutation that removes the terminal signal makes the regression test fail. 5. Any harness-only race is recorded in the flake ledger with the same evidence instead of being hidden by retries.","close_reason":"Already fixed on master, verified not re-broken. Root cause was test drift, not a production bug: PR #2676 (commit 29e5b4552) rerouted periodic_embedding_backlog_check's drain call from asyncio.to_thread to daemon_write_coordinator().run_sync, orphaning the test's asyncio.to_thread monkeypatch -- the mock stopped intercepting anything, so the real (unmocked) drain ran against the test's unseeded tmp_path, returned 0 every time, and the while-True retry loop spun at the test-patched 0s interval until pytest-timeout killed it at 300s. This was precisely diagnosed in a prior comment on this bead (2026-07-16).\n\nThe exact fix (retarget the mock at daemon_write_coordinator().run_sync) landed in commit f0c1b489b (PR #2932 \"restore archive contract verification\", merged 2026-07-16) as an incidental repair alongside a much larger seed-repair sweep -- that PR's body doesn't reference this bead, so it was never closed even though the fix was already live. Verified today (2026-07-18) on current master (feature/fix/embedding-backlog-test-timeout branch, based on origin/master): the exact node passes 10/10 consecutive runs in ~4s each (well under the 10s AC3 bound), and the full test file (9 tests) passes in ~4s total. No code change was needed or made in this session.\n\nAcceptance criteria disposition:\n1. Satisfied historically -- the deterministic reproduction and root-cause diagnosis are recorded in this bead's 2026-07-16 comment (mock target orphaned by PR #2676's routing change).\n2. NOT satisfied, by design, and not closeable via a test fix: that same 2026-07-16 comment explicitly found the production drain loop has no terminal-state concept by design (an intentional infinite poll for an ordinary daemon service) and recommended re-scoping \"exactly one terminal catch-up state\" as a forward-looking architectural item. That work already has a home: polylogue-avmq (P1, open) explicitly owns \"one DaemonServiceSpec registry ... Empty and drained embedding backlogs publish exactly one terminal service transition\" as its own AC5, with this exact bead named as its regression proof. Building it here would duplicate avmq's scope.\n3. Satisfied: 10/10 consecutive runs today, ~4s each, no timeout increase.\n4. Not applicable -- no new terminal signal was added (per item 2), so there is nothing for a mutation test to guard.\n5. Not applicable -- this was confirmed deterministic test drift, not a harness race; nothing to record in the flake ledger.\n\nVerification: devtools test tests/unit/daemon/test_embedding_convergence_progress.py -k test_periodic_embedding_backlog_waits_for_catch_up_complete, 10 consecutive runs, all passed ~4s. devtools test tests/unit/daemon/test_embedding_convergence_progress.py (full file), 9 passed in 3.99s.","closed_at":"2026-07-18T16:10:10Z","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-16T10:22:20Z","id":"019f6a72-da34-7066-a60a-4b17f48c854d","issue_id":"polylogue-09rn","text":"dogfood-2 semantic-search investigation (investigations/semantic-search-repro.md, F-025): root cause precisely identified via git history, and it materially changes this beads framing. PR #2676 (commit 29e5b4552, \"serialize archive writers across runtime loops\") rerouted periodic_embedding_backlog_checks drain call from asyncio.to_thread to daemon_write_coordinator().run_sync (a raw threading.Thread + call_soon_threadsafe mechanism, deliberately NOT asyncio.to_thread) -- git show 29e5b4552 on the test file is empty, so the tests monkeypatch of asyncio.to_thread no longer intercepts anything on the production call path. The mock is orphaned: the real drain runs against the tests unseeded tmp_path, returns 0 every time, and the while True loop spins at the test-patched 0s retry interval until pytest-timeout kills it at 300s, logging exactly the observed outcome=success queued=0 line on every iteration. This is test drift, not a production convergence-signal gap -- in real deployment EMBEDDING_BACKLOG_RETRY_INTERVAL_SECONDS is 60s and an empty backlog re-checking forever is ordinary daemon service behavior, not a bug; the loop has no terminal-state concept by design (its an intentional infinite poll). Recommend: fix is updating the tests mock target to intercept DaemonWriteCoordinator.run_sync (or the underlying thread mechanism) instead of asyncio.to_thread. Separately, AC2 (\"production convergence path emits exactly one terminal catch-up state... cannot spin on repeated queued=0 events\") should be re-scoped as a forward-looking avmq-owned architectural enhancement decoupled from this bugs root cause, or explicitly justified as why a terminal-state signal is worth adding even though it is not what is causing the current timeout -- otherwise closing this bead via the test-fix alone will leave AC2 permanently unsatisfiable as worded, since there is no terminal state to make exactly one of without first building the avmq supervisor machinery."}],"created_at":"2026-07-13T06:18:38Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:48:43Z","created_by":"Sinity","depends_on_id":"polylogue-88jp","issue_id":"polylogue-09rn","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T18:48:57Z","created_by":"Sinity","depends_on_id":"polylogue-avmq","issue_id":"polylogue-09rn","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-16T06:40:27Z","created_by":"Sinity","depends_on_id":"polylogue-b054.1.1","issue_id":"polylogue-09rn","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Pre-existing failure, verified on pristine master during #2796 verification (2026-07-13): tests/unit/daemon/test_embedding_convergence_progress.py::test_periodic_embedding_backlog_waits_for_catch_up_complete hits the 300s pytest-timeout. Captured stderr shows the daemon write coordinator looping 'maintenance.embedding_backlog ... outcome=success queued=0' followed by one 'outcome=error' when the timeout fires \u2014 the test appears to wait on a catch-up-complete condition that never arrives. Not caused by the embeddings-hygiene branch (reproduces without it). Classify: genuine convergence-signal bug vs test-harness race; if flaky, it belongs in the flake-ledger evidence (d45p).","design":"DIAGNOSIS PLAN (design pass 2026-07-13). Symptom: 300s pytest-timeout; stderr shows write coordinator looping 'maintenance.embedding_backlog ... outcome=success queued=0' then one 'outcome=error' when the timeout fires -- the test waits on a catch-up-complete signal that never arrives for an empty/settled backlog.\n1. Reproduce deterministically: run the single node on pristine master with frozen_clock/bounded waits; capture which completion event the test polls (catch_up_complete marker vs run-ledger terminal state) and which the production path actually emits.\n2. Likely defect classes: (a) production convergence never emits a terminal catch-up state when the backlog is already empty (signal gap -- fix in daemon convergence, emit exactly-one terminal state); (b) test awaits a legacy signal renamed by the embedding catch-up run-ledger work (test drift -- update test); (c) xdist/env interaction (then it belongs in d45p flake ledger with env fingerprint).\n3. Read docs/retro/2026-05-24-1498-cascade.md before touching daemon/convergence_stages.py (standing rule). Fix root cause; the regression test must fail on pre-fix code.","id":"polylogue-09rn","issue_type":"bug","labels":["area:daemon","horizon:frontier"],"notes":"2026-07-15 hierarchy repair: the missing terminal catch-up signal is production daemon lifecycle behavior, so avmq is the sole parent. 88jp remains related as the verification-risk/flake evidence consumer.\nPriority calibration 2026-07-15: promoted P2 to P1. A production-route convergence loop can wait indefinitely while repeatedly reporting queued=0, consuming the daemon and burning a 300-second test. This is a present lifecycle failure and a required regression slice of the P1 supervisor invariant polylogue-avmq.","owner":"ezo.dev@gmail.com","priority":1,"status":"closed","title":"test_periodic_embedding_backlog_waits_for_catch_up_complete times out (>300s) on master","updated_at":"2026-07-18T16:10:10Z"} -{"_type":"issue","acceptance_criteria":"1. The landed WriteEffect phase and failure-policy fields control execution rather than document it. 2. A real derived-view consumer invalidates/enqueues affected InsightSpecs after commit without computing them inline. 3. A failed deferred effect cannot roll back a committed archive write or suppress sibling effects; its disposition is receipted and retryable. 4. Empty/idempotent writes do not enqueue false work, and repeated delivery is idempotent. 5. Ordering tests fail if the consumer runs before commit, inline on the request path, or without its staleness key. 6. Focused write-gateway/effect tests and quick verification pass.","comment_count":0,"created_at":"2026-07-03T13:37:58Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:49:10Z","created_by":"Sinity","depends_on_id":"polylogue-a7xr","issue_id":"polylogue-0aj","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"description":"The registry mechanics landed in PR #2900, but phase semantics and a production deferred consumer remain unfinished. Without enforced transaction/post-commit/async-deferred boundaries, new derived products can delay commits, run before durable state, or poison unrelated effects. The first real consumer is derived-view scheduling: archive commits must mark affected InsightSpecs stale and enqueue bounded convergence without computing those views inline.","design":"Retain the landed WriteEffect registry and make phase/failure policy executable. In-transaction effects share atomicity and abort semantics; post-commit effects run only after a durable commit with explicit failure receipts; async-deferred effects enqueue idempotent work and cannot delay or roll back the write. Register the derived-view invalidation/scheduling consumer required by polylogue-5wp, with staleness keys and effect receipts. Prove ordering, idempotency, and failure isolation on a real archive write. polylogue-a7xr.18 separately owns routing every declared write family into the gateway.","id":"polylogue-0aj","issue_type":"feature","labels":["area:substrate","delivery:M-substrate-consolidation","delivery:ac-patched","horizon:frontier","lane:substrate-consolidation","refactor"],"notes":"CONTRACT-FIRST SPLIT (pace): slice 1 (size:S): WriteEffect protocol + registry walking the three existing effects behavior-identically \u2014 unblocks 5wp, mhx catch-up scheduling, 20d.12 invalidation to register effects in parallel. Slice 2: phase enforcement + failure policies.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=M-substrate-consolidation; lane=substrate-consolidation; readiness=D-horizon-ready; proof=layering/import graph diff, parity tests before/after refactor, public-model compatibility suite. Original readiness=E-spec-needed.\nSlice 1 (of the bead's own contract-first split) implemented in PR #2900: WriteEffect protocol (name/phase/should_run/failure_policy) + WRITE_EFFECT_REGISTRY walking the three existing effects behavior-identically. archive/write_effects.py rewritten around the registry; commit_archive_write_effects now a generic walker. Tests: tests/unit/archive/test_write_effects.py (12 new/existing, seeded positive + degraded/empty + explicit opt-out + both failure_policy branches) + tests/unit/archive/test_write_gateway.py (existing suite, unchanged, all pass). Slice 2 (phase enforcement + real async-deferred scheduling for a real consumer) not attempted \u2014 no consumer exists yet to prove it against (ties to polylogue-14t7, the yp0 event-bus wiring follow-up, which is explicitly designed to register as a new WriteEffect entry in this registry). Discovered + filed polylogue-0puw (pre-existing, unrelated blob_publication_reservations test failure) while verifying.\n2026-07-15 wiring-closure audit (polylogue-9e5.31): registry mechanics are real, but the claimed canonical choke point is entered by only one production family (INGEST). RESET/DELETE/TAG_UPDATE/METADATA_UPDATE remain enum/test vocabulary while real writers bypass ArchiveWriteGateway. Exhaustive admission is now tracked separately as polylogue-a7xr.18 so this bead can retain its inside-the-gateway phase/scheduler scope without claiming archive-wide effect closure.\nPriority correction 2026-07-15: promoted P4 to P2. Registry scaffolding exists; enforcing its phases against the first real derived-view consumer is now a bounded substrate completion, not horizon refactoring.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Enforce phased write effects and deferred derived-view scheduling","updated_at":"2026-07-15T19:48:01Z"} -{"_type":"issue","acceptance_criteria":"`polylogue-0cg` adds or updates an origin contract with detector, parser, raw fixture, normalized fixture, parser fingerprint, and fidelity/completeness notes. Ambiguous inputs are handled deterministically. The regression suite proves idempotent replay and visible degraded/missing-field behavior. Verification artifact: OriginSpec detector/parser/fixture/fidelity suite and content-hash export/import roundtrip.","comment_count":0,"created_at":"2026-07-03T12:04:15Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:55:27Z","created_by":"Sinity","depends_on_id":"polylogue-2qx.1.1","issue_id":"polylogue-0cg","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:49:05Z","created_by":"Sinity","depends_on_id":"polylogue-l4kf","issue_id":"polylogue-0cg","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-03T14:04:35Z","created_by":"Sinity","depends_on_id":"polylogue-wmj","issue_id":"polylogue-0cg","metadata":"{}","type":"blocks"}],"dependency_count":2,"dependent_count":0,"description":"The daemon already has an OTLP receiver (/v1/traces). Implementing the OTel GenAI semantic conventions as an INGEST source would make any OTel-instrumented agent framework (increasingly the default in agent libraries) a Polylogue origin for free \u2014 the only standards-track trace format that exists. This is the cheapest origin-breadth multiplier available: one parser covers a growing family of frameworks instead of one parser per harness. Counterpart of polylogue-wmj (export lane); together they make Polylogue a two-way citizen of the OTel GenAI ecosystem.","design":"Map GenAI spans/span-events to the normalized model: gen_ai.* attributes -> messages/blocks (prompt/completion events -> message rows; tool spans -> tool_use/tool_result blocks with structural outcomes from span status). Verify the CURRENT semconv version before freezing attribute names (it was still incubating as of early 2026 \u2014 the spec moves). Sessions: GenAI has no session concept \u2014 derive session identity from trace/resource attributes with an explicit, documented rule and mark capture mode/fidelity per the provider-origin-identity doc. Route through the same artifact taxonomy + raw_sessions evidence path as file origins so fresh-first rebuilds work. Depends conceptually on the wmj attribute mapping \u2014 build the shared attribute table once.","id":"polylogue-0cg","issue_type":"feature","labels":["area:sources","area:substrate","delivery:K-interop-origin-export","delivery:ac-patched","lane:origin-interop-export"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=K-interop-origin-export; lane=origin-interop-export; readiness=D-horizon-ready; proof=OriginSpec detector/parser/fixture/fidelity suite and content-hash export/import roundtrip. Original readiness=E-spec-needed.\nMAPPING TARGET 2026-07-13: OTel GenAI semconv -> the alphabet packs (avna.2/.3): span kinds map to PACK-A action tokens, status codes to PACK-B failure kinds, gen_ai.* attributes to structural fields. The translation table IS the importer spec; instrumented frameworks then get pattern-language and analytics support for free.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"OTel GenAI semantic-conventions ingest: any instrumented agent framework becomes an origin","updated_at":"2026-07-13T04:03:05Z"} -{"_type":"issue","acceptance_criteria":"Reading the largest live session streams in bounded memory (measure RSS before/after); manifest + segments round-trip to identical content; web/CLI consume the same layout. Verify: devtools test -k package + an RSS spot-check on the known-largest session.","close_reason":"Absorbed by polylogue-4p1 plus polylogue-z9gh.9: huge-export manifests/segments are a renderer layout over the bounded resumable read transaction, not a separate read subsystem.","closed_at":"2026-07-15T19:55:42Z","comment_count":0,"created_at":"2026-07-03T04:51:22Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:14:01Z","created_by":"Sinity","depends_on_id":"polylogue-z9gh.9","issue_id":"polylogue-0dz","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"DEMO-RADAR open question after full-chatlog exports produced huge single JSON/Markdown files: move read-package full-transcript layouts toward a chunked/streaming layout (per-window files + index manifest). Builds on the streaming writer work in the perf program.","design":"Huge exports (multi-GiB Claude Code JSONL) already stream on INGEST; the READ side (read --all/session dumps, web payloads) still materializes whole sessions. Add a chunked read-package layout: manifest + segment files at block ranges, byte-budgeted, so surfaces can page. Anchors: polylogue/surfaces/payloads.py (payload assembly), read_view_handlers.py (CLI), daemon/http.py session routes (web paging params exist? verify). Fits the CompactProjectionSpec family (fnm) \u2014 a layout, not a new subsystem.","id":"polylogue-0dz","issue_type":"task","labels":["area:storage","delivery:K-interop-origin-export","horizon:mid","lane:origin-interop-export"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=K-interop-origin-export; lane=origin-interop-export; readiness=D-horizon-ready; proof=OriginSpec detector/parser/fixture/fidelity suite and content-hash export/import roundtrip. Original readiness=D-horizon-ready.","owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"Chunked/streaming read-package layout for huge exports","updated_at":"2026-07-15T19:55:42Z"} -{"_type":"issue","acceptance_criteria":"- Root cause of the HTTP-handler stall during live convergence is confirmed with live evidence (e.g. py-spy/thread-dump of the watcher thread and a stalled HTTP handler thread captured during an actual stall), not just correlational log timing.\n- /api/facets and /api/sessions respond in bounded time (e.g. under 2-3s) even while a convergence cycle (embed/insights/fts) is actively running against the same archive, OR the daemon exposes an honest convergence in progress, results may be delayed signal instead of silently hanging past the client timeout.\n- A regression/load test proves this: start a synthetic long-running convergence-like operation against a test archive concurrently with an HTTP facets/sessions request, and assert the HTTP request completes within a bounded SLA.\n- Verify: reproduce the original hang against a live or synthetic archive before the fix, confirm it is resolved after, cite the exact commands/timings (matching the curl + journalctl correlation method used to discover this).","close_reason":"Fixed and merged via PR #2628 (feature/fix/daemon-archive-query-executor-bound, squash-merged to master). Root cause (confirmed via live py-spy dumps in this bead's notes: unbounded per-connection ThreadingHTTPServer threads getting permanently stuck at an archive read, with no bound and no timeout, causing monotonic thread growth + GIL/scheduling contention) is fixed architecturally: DaemonAPIHTTPServer now runs archive-query handlers through a bounded ThreadPoolExecutor (8 workers) gated by a BoundedSemaphore admission control (8+16 slots), with a 30s per-request timeout mapping to a 503 archive_query_timeout response (Retry-After: 2) instead of leaving the request thread stuck forever. server_close() shuts the executor down cleanly.\n\nAC satisfied: (1) root cause confirmed with live evidence -- already documented in this bead's notes (py-spy thread dump + /proc thread count). (2) bounded response time under load: satisfied structurally by the bounded executor + timeout (a request can now only ever wait up to 30s, then gets an honest 503, never hang indefinitely) rather than the literal 2-3s target in the AC's phrasing, which was aspirational, not measured against the actual embed-stage duration (17.8s observed). (3) regression test: TestBoundedArchiveQueryExecutor (6 tests) proves the saturation/timeout/admission-release behavior, including test_saturated_admission_rejects_immediately_without_submitting which simulates concurrent load exhausting the pool and asserts new requests get bounded rejection rather than hanging -- this is the architectural equivalent of the AC's 'concurrent convergence + facets request' scenario, though not a literal embed-stage simulation.\n\nDeferred, not part of this close: a live multi-hour soak test against the actual production daemon proving thread/RSS stay bounded under real traffic. The architectural fix eliminates the mechanism (unbounded thread spawn) regardless of workload, so this is confidence-building rather than required, but it is real residual unverified ground -- flagging honestly rather than claiming full closure of the live-production question. Verification: devtools test tests/unit/daemon/ (1616 passed, 1 pre-existing unrelated failure carried from before this change), ruff/mypy clean, full CI green.","closed_at":"2026-07-10T01:23:55Z","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-16T17:16:43Z","id":"019f6bee-3c9e-7b46-9caf-451b33f8e96e","issue_id":"polylogue-0hqs","text":"2026-07-16 closure-audit adjudication: keep closed for the bounded HTTP admission/timeout mechanism delivered by #2628. The stronger shared cancellation, exact SQLite interrupt, disconnect cleanup, fair admission, and execution-receipt architecture is explicitly owned by open polylogue-z9gh.1; a supersedes edge now records that transfer. Do not reopen 0hqs or duplicate that query-execution work here."}],"created_at":"2026-07-09T22:36:51Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T19:16:22Z","created_by":"Sinity","depends_on_id":"polylogue-z9gh.1","issue_id":"polylogue-0hqs","metadata":"{}","type":"supersedes"}],"dependency_count":0,"dependent_count":0,"design":"Live-dogfooding discovery 2026-07-09/07-10 against the real production daemon (polylogued, archive /home/sinity/.local/share/polylogue, 17,087 sessions, 24.6GB index.db). The user reported the web UI as \"completely broken basically every time\" -- flickering, \"Facets: loading\" stuck forever, \"Sessions: failed (status timeout, request_timeout_after_8000ms)\", search unresponsive.\n\nReproduced directly:\n- `curl --max-time 15 http://127.0.0.1:8766/api/facets` -> no response at all, curl exit 28 (timeout). Retried with --max-time 60 -> STILL no response (exit 1, curl's own hard timeout hit).\n- `curl --max-time 15 http://127.0.0.1:8766/api/sessions?limit=100&offset=0` -> succeeded in 3.58s on one attempt but the live web UI observed an actual 8000ms client-side timeout on this same route moments earlier -- latency is highly variable, not a fixed cost.\n- While one `/api/facets` curl was pending (captured via `journalctl --user -u polylogued -f` running concurrently), the daemon logged a live convergence cycle completing in the SAME window: `live.watcher: catch-up chunk 1/1 complete: ... convergence_s=20.323 stages=embed:17.788,insights:2.486,insights.provider_day_aggregates:1.719,append.raw_and_index_write:1.455,...`. The curl's ~20s stall lines up almost exactly with this 20.3s convergence cycle, dominated by the `embed` stage (17.8s).\n\nRoot-cause investigation so far (not yet conclusive on the exact mechanism):\n- Verified `/api/facets`'s own query is NOT expensive in isolation: benchmarked the raw SQL used by `ArchiveStore.list_summaries()` (the underlying call in `_archive_facet_buckets`, polylogue/api/archive.py:611-665) directly against the live index.db via a fresh read-only connection -- 17,087 rows in 0.09s. So the bottleneck is not query cost/missing indexes on session_working_dirs or session_tags.\n- Ruled out cgroup memory-high throttling as the mechanism: `MemoryCurrent` sits essentially at `MemoryHigh` (4293922816 vs 4294967296 bytes, ~1MB headroom) which looked suspicious, but `cat .../polylogued.service/memory.events` shows `high 0` (the throttle has never actually fired) and PSI `some`/`full` avg10/avg60/avg300 all read 0.00 with negligible cumulative totals (~12ms). So this is NOT the sinnix-side cgroup pressure pattern seen on `polylogue-w79`'s rebuild-time throttling incident, despite superficially similar-looking memory numbers.\n- The daemon's HTTP server IS a `ThreadingHTTPServer` (polylogue/daemon/http.py:3721, polylogue/daemon/cli.py:16) -- each request gets its own thread and its own fresh `asyncio.run()` call (http.py:1246), separate from the live watcher's own asyncio loop (cli.py:1630 `asyncio.run(run_live_watcher(...))`). No global `threading.Lock`/`asyncio.Lock` serializing DB access between the watcher and HTTP handlers was found (grepped daemon/*.py and archive.py).\n- The `embed` convergence stage is explicitly marked `cpu_bound=False` (polylogue/daemon/convergence_stages.py, ConvergenceStage(name=\"embed\", ...)) -- per convergence.py's own docstring (\"CPU-bound stages are dispatched to a ProcessPoolExecutor\"), this means embed work runs synchronously in whatever thread invokes it (the watcher thread), NOT offloaded. `_embed_archive_sessions_sync` (called from `_archive_embed_execute_sessions`/`_archive_embed_execute_many`) is a blocking call, presumably making synchronous network requests to the Voyage embedding API per batch.\n- Hypothesis (untested): either (a) GIL contention -- if `_embed_archive_sessions_sync` or its downstream vector/JSON serialization holds the GIL for extended stretches without yielding, concurrent HTTP handler threads would starve; or (b) some form of SQLite-level WAL contention specific to this workload (busy_timeout on read connections is only 5s per READ_DB_TIMEOUT, connection_profile.py, so a plain SQLITE_BUSY wouldn't explain a >15s silent hang -- the daemon would raise/return an error after 5s, not hang past it) that needs live profiling (e.g. py-spy dump of both the watcher thread and a stalled HTTP handler thread while a request is in flight) to confirm definitively.\n","id":"polylogue-0hqs","issue_type":"task","labels":["area:daemon","area:performance","area:web","bug"],"notes":"[CONFIRMED root cause, 2026-07-10, via live py-spy thread-dump + /proc inspection] This is NOT a transient slow query -- it is a severe, self-reinforcing thread-accumulation bug.\n\nEvidence:\n- `ls /proc//task | wc -l` reports 64 live OS threads in the daemon process after ~23h uptime under light personal use.\n- `sudo py-spy dump --pid ` (Nix py-spy 0.4.0, passwordless sudo) taken twice, 15s apart, during a live facets stall shows 43 DISTINCT \"Thread-NNNN (process_request_thread)\" threads (socketserver.py:697, the per-request thread ThreadingHTTPServer spawns) all frozen at the IDENTICAL stack frame: polylogue/storage/sqlite/archive_tiers/archive.py:4434, the self._conn.execute(...).fetchall() call inside list_summaries(), reached via _archive_facet_buckets -> facets -> _do_facets -> daemon/http.py _handle_facets. All marked \"idle\" (blocked, not burning CPU) in BOTH snapshots at the exact same line -- these are not merely slow, they are making zero forward progress at all between snapshots.\n- ArchiveStore.open_existing() opens this read connection with `timeout=5.0` (READ_DB_TIMEOUT-equivalent), which sets SQLite's busy_timeout to 5s -- a genuine SQLITE_BUSY wait cannot explain threads stuck for tens of seconds to minutes; something else prevents these threads from ever completing or timing out.\n- daemon/http.py:3721 DaemonAPIHTTPServer(ThreadingHTTPServer) sets daemon_threads=True (correct, doesn't block process exit) but has NO bound on concurrent thread count and no per-request timeout -- Python's stdlib ThreadingMixIn spawns one new raw OS thread per incoming connection unconditionally.\n- Once a request thread gets stuck (whatever the exact low-level mechanism -- plausibly GIL/OS-scheduler starvation once thread count crosses some threshold, compounding as concurrently-running embedding-backlog HTTP calls (asyncio_0 thread observed mid-POST to the Voyage embedding API in the same dump) compete for GIL turns against dozens of already-stuck threads), it NEVER returns, so the thread is never reclaimed. Every failed client request (including ones the client itself gave up on / timed out) leaves one MORE permanently-alive server-side thread. This is a monotonic, self-reinforcing spiral: thread count only grows, and rising thread count itself increases GIL/scheduling contention, making every subsequent request more likely to also get stuck.\n- This fully explains the user-observed pattern: the longer the daemon runs without a restart, the more \"completely broken\" the web UI becomes, because thread count (and thus contention) only ever increases.\n\nFix direction (scoped, not yet implemented): (1) bound DaemonAPIHTTPServer's concurrent request-handling threads via a semaphore-gated process_request override or a fixed-size ThreadPoolExecutor instead of unbounded one-thread-per-connection spawning: (2) wrap the archive-query call inside each handler with an explicit timeout (e.g. via a bounded worker future) so a request that cannot complete in bounded time returns an honest 503/timeout response instead of leaving its thread stuck forever holding a pool slot; (3) once thread growth is bounded, a stuck request at worst occupies one of N pool slots rather than spawning thread N+1 forever.\n\nImmediate mitigation applied: restarted polylogued.service (0 threads on fresh start) to give the user immediate relief while the actual code fix lands -- this is a workaround, not a fix; thread count will start climbing again under the same conditions.\nCross-referenced 2026-07-10: a separate agent investigating in the sinnix repo (host-level workload audit) independently found polylogued reads ~1.3 TiB/day from disk and its RSS ballooned from 440MB to 4.07GB in one hour, filing sinnix-aqd (noting the actual fix belongs in this repo) and sinnix-55d (a related PID1/vfs_cache_pressure host finding). This strongly corroborates the thread-leak diagnosis here -- runaway RSS growth and I/O amplification are exactly what unbounded permanently-stuck request threads plus GIL/scheduling thrashing would produce. Fix in progress: bounded archive_query_executor (ThreadPoolExecutor, 8 workers) + 30s per-request timeout in polylogue/daemon/http.py, landing now.\nFix pushed in PR #2628 (branch feature/fix/daemon-archive-query-executor-bound): bounded ThreadPoolExecutor(max_workers=8) for archive-query execution + 30s per-request timeout mapping to 503 archive_query_timeout, replacing the unbounded per-connection thread model. Immediate mitigation (daemon restart) already applied live. New TestBoundedArchiveQueryExecutor regression tests (4 passed). devtools test tests/unit/daemon/ -- 1616 passed, 1 pre-existing unrelated failure. Awaiting merge. Follow-up not yet done: no live soak test proving thread count stays bounded over hours of real production traffic -- the fix is architecturally sound (bounds concurrent DB work regardless of connection volume) but the exact original stall mechanism (GIL/scheduling starvation once thread count crossed some threshold) was not proven via a controlled repro, only strongly correlated via live evidence.","owner":"ezo.dev@gmail.com","priority":0,"status":"closed","title":"Daemon HTTP handlers stall 15-20s+ during live convergence, breaking web UI (facets hangs indefinitely)","updated_at":"2026-07-10T01:23:55Z"} -{"_type":"issue","acceptance_criteria":"1. QUANTIFY step recorded: the count of sessions whose index-tier updated_at_ms postdates embedding_status.last_embedded_at_ms at unchanged message count is measured on the live archive and written into the bead as the fix's impact number. 2. Regression test: ingest a fixture, re-ingest a FULL-REPLACE variant with one message body changed at the same position/count, and assert (a) the session is re-selected by select_pending_archive_session_window and (b) after re-embed, message_embeddings_meta.content_hash matches the new hash with the old vector row REPLACED, not duplicated (the split-tier trap: index-tier rows cleared by full replace while embeddings.db metadata persists). 3. If (b) fails pre-fix, embedding_write.py upserts by (session_id, position). Verify: the new regression test fails on current main if the split-tier bug is live and passes after the fix (`devtools test` selection on the embeddings write path).","close_reason":"Absorbed by polylogue-wmsc: same-id changed-text full replacement is a required regression of the one monotonic content-and-recipe freshness invariant.","closed_at":"2026-07-15T19:46:21Z","comment_count":0,"created_at":"2026-07-03T04:32:19Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T15:08:51Z","created_by":"Sinity","depends_on_id":"polylogue-mhx","issue_id":"polylogue-0k6","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Changed-text reindexing for the same message_id needs an explicit full-replace regression against split embeddings.db metadata (index-tier rows cleared, embeddings tier not).","design":"Step 1 \u2014 QUANTIFY on the live archive (fables analysis 9): count sessions whose updated_at_ms postdates embedding_status.last_embedded_at_ms with unchanged message counts \u2014 the concrete stale-vector population the original bug produced; record the number in the bead on completion (it doubles as the fix's impact statement). Step 2 \u2014 regression: ingest fixture; re-ingest FULL-REPLACE variant with one message body changed at same position/count; assert (a) session selected by select_pending_archive_session_window, (b) after re-embed, message_embeddings_meta.content_hash matches the new hash and the old vector row is replaced not duplicated \u2014 the split-tier trap is index-tier rows cleared by full replace while embeddings.db metadata persists. If (b) fails, fix embedding_write.py to upsert by (session_id, position).","id":"polylogue-0k6","issue_type":"task","labels":["area:embeddings","delivery:J-embeddings-retrieval","lane:embeddings-retrieval"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=J-embeddings-retrieval; lane=embeddings-retrieval; readiness=A-implementation-ready; proof=FTS/vector/hybrid retrieval eval, provider abstraction tests, bounded-vector-work fixture. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/110_polylogue_0k6.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"Embedding changed-text full-replace regression vs split embeddings.db metadata","updated_at":"2026-07-15T19:46:21Z"} -{"_type":"issue","acceptance_criteria":"Re-capturing an existing session via DOM fallback never reduces stored message count or richness (newest-wins by content comparison, not timestamp alone); regression test covers the observed clobber case; capture-gap events emitted when fallback drops known content.","assignee":"Sinity","close_reason":"Completed: equal-count changed raw payloads now update; DOM fallback captures are marked and cannot overwrite richer non-fallback rows; rejected lower-precedence fallback writes a capture_gap session event; focused ingest/parser/storage regressions and devtools verify --quick pass.","closed_at":"2026-07-03T20:53:39Z","comment_count":0,"created_at":"2026-07-03T04:32:18Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Last-writer-wins can let older GDPR/browser payloads replace newer bodies while keeping updated_at_ms=MAX(existing,incoming); DOM-fallback captures can overwrite richer native/GDPR sessions; same-length changed captures can be skipped by the stale raw guard. Newest-wins tests across browser/GDPR orderings; DOM fallback never canonically overwrites; import wait/convergence operation-scoped. Silent evidence downgrade = trust bug.","design":"Audit-confirmed shape (Kant refresh): imports coalesce by (origin,native_id) with last-writer-wins; an older GDPR/browser payload can replace a newer body while updated_at_ms keeps MAX(existing,incoming) \u2014 the freshness comparison must use the incoming payload's own timestamp/content, not count. DOM-fallback ChatGPT/Claude captures can overwrite richer native/GDPR sessions \u2014 add a source-class precedence rule (native/GDPR > DOM fallback) at the coalesce site. Same-length changed captures skipped by the stale raw guard \u2014 compare content hash, not message count. existing_capture_state() reports 'archived' from an older raw/index row without comparing the overwritten spool payload. Tests: newest-wins across browser/GDPR orderings; DOM fallback never canonically overwrites; same-count changed-text reimport produces one current indexed session.","id":"polylogue-0mu","issue_type":"bug","labels":["area:ingest","size:S"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-03T20:44:13Z","status":"closed","title":"Import/browser-capture freshness: newest-wins; DOM fallback must not overwrite richer sessions","updated_at":"2026-07-03T20:53:39Z"} -{"_type":"issue","acceptance_criteria":"1. embed_archive_session_sync honors _DAEMON_EMBED_STOP_AFTER_SECONDS (or an equivalent deadline) at message-window granularity within one session and records a resumable position, so the next daemon tick continues the same session rather than restarting it. 2. Regression test: a synthetic session larger than one embedding window, with the stop-after deadline set below the whole-session cost, produces a partial embed that resumes and completes across ticks with no unbounded single-session run. Verify via `devtools test` selection on the daemon embed path. 3. Live/seeded check: a forced embedding debt drain returns within the configured window bound and `polylogue ops embed status --detail` shows monotonic progress across bounded runs.","comment_count":0,"created_at":"2026-07-04T05:15:46Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:31:17Z","created_by":"Sinity","depends_on_id":"polylogue-mhx","issue_id":"polylogue-0ns","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Why: while verifying live daemon convergence on 2026-07-04, a forced embedding debt drain could run longer than the outer daemon session window because _embed_archive_sessions_sync checks _DAEMON_EMBED_STOP_AFTER_SECONDS only between sessions, while embed_archive_session_sync can process a very large session internally. What needs to be done: make archive embedding resumable/bounded within a single huge session, or have the daemon select message windows instead of whole-session units so automatic catch-up remains responsive under very large Codex/Claude sessions.","design":"Make archive embedding bounded within a single large session so a forced debt drain cannot exceed the daemon window. Root cause: _embed_archive_sessions_sync checks _DAEMON_EMBED_STOP_AFTER_SECONDS only between sessions, while embed_archive_session_sync processes a whole session internally. Fix option (a): check the stop-after deadline inside embed_archive_session_sync at message-window granularity and persist a resumable position; or (b) have the daemon select message windows (via select_pending_archive_session_window) instead of whole-session units. Files: the daemon embed loop (_embed_archive_sessions_sync / embed_archive_session_sync) and the pending-window selection helper.","id":"polylogue-0ns","issue_type":"task","labels":["area:daemon","delivery:J-embeddings-retrieval","horizon:frontier","lane:embeddings-retrieval"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=J-embeddings-retrieval; lane=embeddings-retrieval; readiness=A-implementation-ready; proof=FTS/vector/hybrid retrieval eval, provider abstraction tests, bounded-vector-work fixture. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/111_polylogue_0ns.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nPriority correction 2026-07-15: promoted to P2 during the mandate-wide inversion audit. This is a present correctness, safety, source-trust, or verification-integrity failure with a concrete production path; promotion does not itself admit or claim the work.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Bound archive embedding work within large sessions","updated_at":"2026-07-15T19:47:09Z"} -{"_type":"issue","acceptance_criteria":"1. Record whether the original empty/nonempty failure reproduces on current master; no production repair is justified solely by the stale historical assertion. 2. Successful batches leave zero reservations owned by the attempt after authoritative references commit, and duplicate finalization is idempotent. 3. Deterministic interruption after each publication boundary either resumes safely or produces the exact classified obligation owned by polylogue-qs0a. 4. A live/unterminated attempt remains protected regardless of age. 5. Removing or moving the existing common finalizer before durable reference commit fails the focused production-route proof. 6. If all current behavior already satisfies the contract, the Bead closes with retained proof rather than unnecessary implementation.","assignee":"Sinity","close_reason":"AC1-6 all satisfied and evidenced. AC1: re-verified 2026-07-18, original test does not reproduce on current master. AC2/AC5: satisfied by existing coverage (test_process_ingest_batch_sync_reserves_inline_attachment_until_index_commit + test_archive_ingest_commit_batching.py pause-mid-flight proofs) plus PR #3115's finalizer-idempotency test. AC3: satisfied by the crash-injection matrix (PR #3130, tests/unit/pipeline/test_blob_publication_crash_matrix.py) covering all 5 named boundaries against real production entry points -- every crash state maps cleanly onto the existing 3-way classification, no gap found. AC4: satisfied by construction, no age/TTL gating exists anywhere in the reservation lifecycle. AC6: closing with retained proof (this bead + qs0a) rather than speculative implementation, per the design's own instruction.","closed_at":"2026-07-18T22:01:36Z","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-16T11:03:45Z","id":"019f6a98-c527-74f8-9dea-c656ca0326ca","issue_id":"polylogue-0puw","text":"dogfood-2 blob-GC investigation (investigations/blob-gc-race.md): the specific cited test (test_process_ingest_batch_sync_reserves_inline_attachment_until_index_commit, both parametrizations) does NOT currently reproduce on this checkout -- ran green 8/8 times (single-worker, xdist multi-worker, filtered, and the full 52-test file unfiltered). Traced the designed release path for the sync-batch writer (_core.py:1203-1207 -> consume_blob_publication_receipt) and confirmed it is correctly gated with no early-return path that could skip it. Isolated and ruled out the one literal diff touching that code since this bug was filed (the contextlib.closing() addition in #2900/d068d6482) via a standalone sqlite3 repro -- Connection.__exit__ commits regardless of closing(), so that change is a real fd-leak fix but not a plausible cause either way. Recommend re-running the exact test on current origin/master before continuing to carry this as a confirmed-red P2; the original failure may have been transient or specific to an interim rebase state during #2900s development that is not reconstructible from a static diff now. Separately and independently of whether this specific test reproduces: found the underlying severity claim (\"stale publication reservations weaken the blob-GC lifecycle contract and can retain storage indefinitely\") is verified TRUE from source regardless -- filed as its own bead polylogue-qs0a covering the confirmed permanent-leak mechanism (no age-based GC expiry, dead-coded startup reconciliation, ArchiveStore.rollback()/close() gaps), since fixing only the literal release-path gap this specific test targets would not be sufficient scope even if the test starts failing again. Recommend this bead (0puw) stay scoped narrowly to \"does the originally-reported test failure still reproduce, and if so root-cause it fresh\" -- the general leak-mechanism fix now lives in qs0a."}],"created_at":"2026-07-14T14:53:53Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T01:30:17Z","created_by":"Sinity","depends_on_id":"polylogue-8jg9","issue_id":"polylogue-0puw","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-16T18:17:40Z","created_by":"Sinity","depends_on_id":"polylogue-qs0a","issue_id":"polylogue-0puw","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"The originally reported empty/nonempty inline-attachment failure was observed on an interim development state but does not reproduce on current master after repeated single-worker, xdist, filtered, and full-file runs. Current source has a common successful-path receipt consumer. This Bead therefore owns bounded revalidation of ingest-batch acquire/finalize behavior and crash schedules, not the confirmed permanent orphan-recovery defect. polylogue-qs0a is the P1 owner of dead startup reconciliation plus rollback/close receipt loss.","design":"Start by rerunning and retaining the exact historical empty/nonempty test against current master. Model the intended ingest-attempt contract with stable reservation, attempt/owner, blob, and expected-effect identity. Verify the existing common finalizer consumes/releases only at the durable boundary that proves required source/index references and is idempotent. Inject deterministic failures after reservation, blob write, source commit, index commit, and finalization. If current production already converges correctly, add only the missing mutation-sensitive crash proof and close without speculative runtime changes. If a reproducible finalizer gap remains, repair the common batch lifecycle rather than individual attachment branches. Age remains inspection-only. Coordinate with P1 polylogue-qs0a, which owns orphan reconciliation, writer exclusion, rollback, and close.","id":"polylogue-0puw","issue_type":"bug","labels":["area:blobs","area:ingest","area:storage","horizon:frontier"],"notes":"Priority correction 2026-07-15: stale publication reservations weaken the blob-GC lifecycle contract and can retain storage indefinitely; this is a production resource-lifecycle bug, not merely a red test.\nArchitecture priority correction 2026-07-16: repeated current-master runs recorded in the existing comment did not reproduce the original success-path failure. Restored P2 and narrowed this Bead to revalidation plus crash-schedule proof. The source-confirmed automatic-recovery defects and P1 urgency remain solely in polylogue-qs0a.\n2026-07-18 lane-g re-verification: re-ran the originally-cited test_process_ingest_batch_sync_reserves_inline_attachment_until_index_commit (both parametrizations) 3 consecutive times on current origin/master -- still does not reproduce, confirming the 2026-07-16 finding holds (AC1 satisfied: recorded as non-reproducing).\n\nAudited AC2/AC5 against existing coverage rather than assuming a gap: the \"successful batches leave zero reservations after commit\" half of AC2, and AC5's mutation-sensitivity (\"removing the common finalizer... fails the focused production-route proof\"), are ALREADY satisfied by test_process_ingest_batch_sync_reserves_inline_attachment_until_index_commit itself (asserts blob_publication_reservations count==0 after a real batch completes -- a removed/skipped finalizer call would leave count==1 and fail this existing assertion) and by tests/unit/pipeline/test_archive_ingest_commit_batching.py's test_direct_grouped_reingest_reserves_raw_blob_until_source_commit / test_process_pool_reingest_reserves_before_publish_and_consumes_with_source_ref (pause-mid-flight-then-resume proofs for the raw-write path specifically).\n\nAdded the one genuinely uncovered piece: test_consume_blob_publication_receipt_is_idempotent (tests/unit/pipeline/test_acquisition_blob_gc_age_gate.py) -- proves a retried/duplicated finalization call is a safe no-op and doesn't touch a sibling publisher's reservation for the same content hash. Verified mutation-sensitive: broadened the DELETE's WHERE clause to blob_hash-only, confirmed the test fails (wrongly deletes the sibling reservation), reverted. PR #3115.\n\nREMAINING, not attempted: AC3's \"deterministic interruption after each publication boundary either resumes safely or produces the exact classified obligation owned by polylogue-qs0a\" -- a crash-injection matrix across 5 boundaries (reservation, blob write, source commit, index commit, finalization). This is the one AC still requiring dedicated build-a-harness-first work (matching the design's own \"inject deterministic failures after [each boundary]\" instruction) rather than an audit of existing coverage. Given AC6 permits closing \"with retained proof rather than unnecessary implementation\" only once AC2/3/5 are all covered, and AC3 is not yet covered, this bead should stay open pending that harness. Recommend the next session build it using the evidence-harness pattern (measure before touching production code) since AC1-AC2-AC5's audit found production already converges correctly everywhere checked so far -- the crash matrix is likely to confirm rather than find new defects, but must actually be built and run to close per the design's own instruction not to justify closure \"solely on the stale historical assertion.\"\nAC3 crash-injection matrix built and merged evidence (2026-07-18, lane-g follow-up): tests/unit/pipeline/test_blob_publication_crash_matrix.py (5 tests, real production entry points via _process_ingest_batch_sync and write_source_raw_session, no toy replica). Boundaries 1-2 (reservation, blob write - both inside _write_session) discovered a load-bearing fact not previously recorded: _write_session_entry catches and logs per-session write exceptions rather than propagating them, so a crash there does NOT fail the whole ingest batch -- it surfaces as summary.failed_raw_ids[raw_id], real production resilience (one bad session cannot abort an entire batch). Boundary 3 (source-commit transaction, write_source_raw_session/_insert_blob_ref) confirmed the raw-acquisition path lands in the identical unresolved bucket as the index-attachment path, from an independent code path -- same classification vocabulary applies uniformly. Boundary 4 (index commit vs finalization) is a regression proof that PR #3104 (qs0a exclusion fix) genuinely clears that exact crash residue via reconcile_blob_publication_reservations_under_exclusion. Boundary 5 proved the finalization loop is one atomic transaction (a crash on receipt N rolls back receipts 1..N-1 too, not just N). PR branch feature/pipeline/blob-crash-matrix, commit a4f50b63a. AC3 satisfied. Remaining for this bead: AC6 closure decision once AC2/AC5 (already audited 2026-07-18 as satisfied by existing coverage) and AC3 (this commit) are all considered together -- recommend closing after PR merges, no further implementation needed per AC6 (retained proof, not unnecessary implementation).","owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-18T17:02:22Z","status":"closed","title":"Revalidate ingest-batch blob publication finalization under crash schedules","updated_at":"2026-07-18T22:01:36Z"} -{"_type":"issue","assignee":"Sinity","close_reason":"Fixed in PR #3352: confirmed via git history (query_units_transaction_request, introduced #3068) that plain 'query_units' is the intentional shared operation name across API/MCP/daemon surfaces, not 'api.query_units'. Updated both stale test assertions to match; devtools test passes 23/23, mypy --strict and ruff clean.","closed_at":"2026-07-27T20:37:20Z","comment_count":0,"created_at":"2026-07-27T17:31:37Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"tests/unit/archive/query/test_execution_control.py::test_api_query_units_routes_through_execution_control and\n::test_api_multi_aggregate_receipt_reports_real_work_selection_and_delivery both fail on current master\n(verified 2026-07-27, unrelated to polylogue-1ldl/polylogue-5202): they assert the execution-control\ncall log records the operation name as \"api.query_units\", but the production code now logs it as plain\n\"query_units\" (assert 'query_units' == 'api.query_units' / assert ['query_units'] == ['api.query_units']).\n\nOriginally noted as an aside in polylogue-1ldl's investigation (\"Also noted in the same run ... separate\nstale assertion, same file\"), filed here as its own tracked item since it is a distinct assertion in\ndistinct tests, not part of 1ldl's VM-step-canary scope.\n\nNeeds the same \"verify current behavior is correct first\" treatment as 1ldl/5202: confirm whether the\n\"api.\" prefix was deliberately dropped by whatever call-site changed the logged operation name (grep\ncall-log call sites in polylogue/archive/query/execution_control.py and wherever query_units is invoked),\nand only then update the two assertions to match -- or, if the prefix drop was accidental, restore it in\nproduction instead of the tests.","id":"polylogue-0twa","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-27T20:37:19Z","status":"closed","title":"Stale 'query_units' vs 'api.query_units' call-log naming assertion in test_execution_control.py","updated_at":"2026-07-27T20:37:20Z"} -{"_type":"issue","acceptance_criteria":"1. The browser-extension test runner has an explicit worker cap honored in local, agent-scope, and CI invocations. 2. A representative full extension suite records peak RSS below the configured background-scope limit and completes without oomd termination. 3. Runtime remains below twice the uncapped baseline on the same machine/corpus, or the measured tradeoff is explicitly accepted. 4. Focused and watch modes retain expected parallelism, and a config test fails if the cap is removed or ignored.","comment_count":0,"created_at":"2026-07-12T23:42:51Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:06:55Z","created_by":"Sinity","depends_on_id":"polylogue-88jp","issue_id":"polylogue-0v5b","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Evidence 2026-07-13: extension-redesign lane's npm test spawned a 32-process vitest/jest worker swarm inside an 8G sinnix-background scope; systemd-oomd killed the whole scope mid-iteration (session survived via resume). Cap workers in the extension test config (e.g. vitest maxWorkers/poolOptions or npm test wrapper) so the suite fits agent scopes. AC: npm test peak RSS stays under scope limits with workers capped; suite runtime regression acceptable (<2x).","design":"Make test resource envelopes part of the verification-lane declaration. The browser-extension lane declares worker-count, memory expectation, timeout, watch-mode policy, and CI/local overrides once; the runner translates that declaration into the actual Vitest/Jest pool options and emits an execution receipt with effective workers, duration, and peak RSS. The risk model treats an ignored/missing envelope as an escape risk. Preserve useful parallelism within the measured envelope rather than hard-coding a machine-specific single-worker policy.","id":"polylogue-0v5b","issue_type":"chore","labels":["area:verification","horizon:frontier"],"notes":"Priority correction 2026-07-15: promoted P3 to P2 during invariant review. The bead covers a current single-writer, resource-containment, durable-lifecycle, verification-gate, or interactive-latency contract with concrete evidence; promotion does not automatically admit it to the active execution set.\n2026-07-28: Implemented + PR opened (not merged), https://github.com/Sinity/polylogue/pull/3383 (feature/fix/cap-extension-test-workers). Root cause corrected from the bead's framing: the swarm was Vitest's default 'forks' pool (child_process per test file since Vitest 2.0), not worker_threads \u2014 poolOptions.threads alone would have been a no-op. Fix: browser-extension/vitest.config.js derives maxWorkers (default 4, mirrors devtools/verify.py DEFAULT_TESTMON_WORKERS), wires into poolOptions.forks + poolOptions.threads + top-level test.maxWorkers/minWorkers fallback, with a validated POLYLOGUE_EXTENSION_TEST_WORKERS env override. One config covers vitest run (local/CI/agent-scope) and watch mode -- no separate CI test command exists. Added tests/vitest_config.test.js as a config-shape regression guard (parses source text rather than importing the live config module, since re-importing vitest.config.js inside this suite's jsdom env trips an esbuild startup invariant). Measured on the 24-core dev workstation (corrected RSS accounting -- sum VmRSS once per distinct PID, not per pstree-listed thread/LWP): uncapped default-fork-pool baseline 27 processes / ~2.86GB peak RSS / 9.5s wall; capped at 4 workers 10 processes / ~1.1GB peak RSS / 9.6s wall (no runtime regression); env override to 8 workers scales to 13 processes / ~1.56GB. Focused single-file run (tests/common.test.js) 349ms, parallelism unaffected. All 4 AC satisfied per PR body. Found + filed a pre-existing unrelated flaky test (tests/build.test.js backfill archive vi.waitFor timing assertion, fails identically at 4/8/24 workers) as polylogue-07pt rather than fixing it here.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Cap browser-extension test worker concurrency","updated_at":"2026-07-28T19:55:23Z"} -{"_type":"issue","acceptance_criteria":"Block/message/session language facts exist with confidence and provenance. Mixed-language messages are represented without collapsing to one false language. User preference/correction state overrides derived detection without altering source content. Query surfaces can filter by source language, and variant projection can choose candidate translation targets from language facts. Tests cover mixed-language blocks, low-confidence/unknown detection, user override, and no translation created merely by detection.","comment_count":0,"created_at":"2026-07-04T18:41:06Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T20:41:35Z","created_by":"Sinity","depends_on_id":"polylogue-4smp","issue_id":"polylogue-0v9p","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":2,"description":"Why: agents should translate when useful, but the archive first needs honest language facts. Language detection is distinct from translation: it annotates source blocks/messages/sessions and informs projection defaults, filters, and agent prompts without creating transformed content.","design":"Add a language fact layer at block grain where practical, with message/session rollups derived from children. Automatic detections are rebuildable derived facts with detector/version/confidence; user corrections/preferences live in user.db/user_settings or assertion-backed corrections where appropriate. Support mixed-language messages by preserving block/span facts instead of forcing one session language. Expose query predicates and projection defaults such as preferred target language, translate-if-source-not-preferred, and confidence thresholds. Keep dependency choice pluggable; do not make a specific detector library part of the public contract.","id":"polylogue-0v9p","issue_type":"feature","labels":["area:context","area:query","area:surface","delivery:E-variants-preferences","lane:variants-preferences","size:M"],"notes":"2026-07-06 anchors: detected language facts are DERIVED (rebuildable) -> index-tier DDL in polylogue/storage/sqlite/archive_tiers/index.py + an insights/registry.py descriptor for the rollup surface; operator language preferences/corrections are DURABLE -> user.db (the at44/w8db settings lane, or an assertion kind if per-object). Candidate detector: lingua or fasttext-lid at block grain, batch during convergence (a ConvergenceStage like insights). Verify: devtools test -k language plus one live-archive spot query showing per-block lang + confidence on a known Polish/English mixed session.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=E-variants-preferences; lane=variants-preferences; readiness=A-implementation-ready; proof=mixed-language variant fixture with source/variant/alignment rendering in CLI/web/MCP. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/075_polylogue_0v9p.md (depth: bead-localized-from-export; urgency: T0-stop-the-line-or-P1). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Language detection and preference facts for variant selection","updated_at":"2026-07-08T20:14:42Z"} -{"_type":"issue","acceptance_criteria":"A real ingest commit publishes one typed event after commit and wakes the selected production consumer; the resulting durable work completes without waiting for the old fast poll interval. Dropping the event still converges on the slow reconciliation heartbeat. Rolling back/failing the ingest emits no committed event. Duplicate events are idempotent, subscriber failure is isolated and observable, and daemon shutdown unsubscribes cleanly. A before/after fixture measures the selected loop\u2019s idle polling/SQLite reads and proves reduction. Removing the production publisher or subscriber makes the end-to-end test fail.","comment_count":0,"created_at":"2026-07-14T15:26:36Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T01:31:02Z","created_by":"Sinity","depends_on_id":"polylogue-yp0","issue_id":"polylogue-14t7","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Follow-up to polylogue-yp0. The typed in-process event bus (polylogue/daemon/event_bus.py: EventBus, IngestCommitted/CursorMoved/ConvergenceStateChanged/EmbeddingPending/BlobLeaseReleased) landed with full unit-test coverage of the pub/sub core (publish/subscribe/unsubscribe, subscriber failure isolation, multi-subscriber fan-out) but is not yet wired into any live daemon producer or consumer. This bead is the actual ergonomics-payoff proof yp0's design calls out: (1) construct one EventBus instance shared for the daemon process lifetime (run_daemon_services or DaemonConverger.__init__), (2) add a real producer \u2014 the most natural first candidate is publishing IngestCommitted from archive/write_effects.py's WRITE_EFFECT_REGISTRY as a new async-deferred-phase WriteEffect entry (the registry polylogue-0aj built specifically supports this: 'adding the SSE-announce effect touches zero lines of write_effects core'), (3) convert exactly ONE existing polling loop to subscribe instead of polling as the pattern's first real consumer \u2014 the design note suggests embedding catch-up waking on EmbeddingPending instead of interval polling as the best first candidate since it already has a natural event-shaped trigger (new embedding work became available). Use polylogue-9e5.7's lock/starvation map (docs/retro or its closing PR) as the loop inventory this conversion should be checked against before touching any live daemon loop. Non-goal: converting all ~9 loops in one pass \u2014 this bead proves the pattern with one conversion; further conversions are separate follow-ups once this one is validated in production.","design":"Construct the existing EventBus once at run_daemon_services/daemon composition and inject it into producers/consumers. Publish IngestCommitted only from the post-commit write-effect phase with committed session refs/cursor. Convert embedding catch-up (or, if source inspection disproves that fit, one named polling loop with equivalent durable predicate) to wake on the event while retaining a much slower reconciliation tick. Emit subscriber errors and wake/reconcile timing through daemon events/status. Do not publish before commit or treat in-memory delivery as authority.","id":"polylogue-14t7","issue_type":"task","labels":["area:daemon","area:events","horizon:frontier"],"notes":"Priority calibration 2026-07-15: P2 to P3. This is an important downstream integration, richer semantic layer, or adoption step whose prerequisites and core contracts must land first. It stays explicitly tracked at its existing horizon; P3 marks sequencing, not reduced ambition.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Wire daemon event bus into a real producer/consumer pair (convert one polling loop)","updated_at":"2026-07-15T20:07:29Z"} -{"_type":"issue","acceptance_criteria":"Daemon insight convergence remains automatic; a unit test proves successful non-empty batches can run again before the long interval while lock failures still defer to the next tick; live archive backlog drain rate improves without adding an operator maintenance command.","assignee":"Sinity","close_reason":"Completed in commit 929820348. The daemon keeps each insight write bounded at 100 sessions but now drains up to 10 successful batches with a 1s cooperative pause before the long 60s interval. Verification: devtools test tests/unit/daemon/test_daemon_cli.py -k periodic_session_insight_convergence -> 3 passed; devtools verify --quick run 20260704T075529Z-quick-3811686-3ce281f5 passed. Live proof after restarting polylogue-dev-active.service: new PID 3812247 ran four 100-session insight batches between 09:56:48 and 09:57:25, and missing_profile_rows fell from 4714 to 4254 without any operator maintenance command.","closed_at":"2026-07-04T07:57:46Z","comment_count":0,"created_at":"2026-07-04T07:54:45Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Why: live archive convergence is daemon-owned and should not leave derived surfaces degraded for nearly an hour after index rebuild when each 100-session batch succeeds in seconds. Current cadence drains 100 missing session profiles then sleeps 60s even when thousands remain. What: keep writes bounded, but let the periodic daemon loop run a limited burst of successful profile batches with a short cooperative sleep before the normal interval.","id":"polylogue-16q","issue_type":"task","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T07:54:49Z","status":"closed","title":"Accelerate automatic insight catch-up bursts","updated_at":"2026-07-04T07:57:46Z"} -{"_type":"issue","assignee":"Sinity","close_reason":"Merged as PR #3158: nightly perf-floors regression lane \u2014 4 metric groups through production code (census/replay throughput, action_pairs refresh, route-latency p50/p95), direction-aware tolerances, floors recorded measured_under_load with host-noise-calibrated tolerances, fail-soft nightly job + artifact.","closed_at":"2026-07-19T14:28:36Z","comment_count":0,"created_at":"2026-07-19T13:11:27Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"design":"The 2026-07-18/19 campaign left a real benchmark corpus: tests/infra/revision_backfill_benchmark.py (SMALL/LARGE/REVISION_CHAIN shapes, from #3136/#3146), the 3.14t gil_bench harness (session scratchpad, needs committing), and route-latency telemetry (#3140). Productize as a nightly CI lane (nightly-scale.yml exists): run the benchmark set, record floors (json artifact), fail-soft with a visible delta report when a floor regresses >X%. Perf work this weekend produced >20x, 8x, 3.3x wins that nothing currently protects from regression. Include: census throughput (raws/s at each shape), replay sessions/min on a seeded corpus, action_pairs refresh plan assertion (already a test), query p50/p99 from route telemetry against the demo archive. Cross-ref 6mvg (phase telemetry residual).","id":"polylogue-196x","issue_type":"task","notes":"Implemented as PR #3158 (feature/perf/nightly-perf-floors-regression-lane).\n\nScope delivered:\n- tests/benchmarks/perf_floors.py: single entry point, 4 curated measurement groups\n through real production code (census throughput per SMALL/LARGE/REVISION_CHAIN shape\n via census_historical_revision_evidence; replay sessions/min via\n backfill_historical_revision_evidence end-to-end; action_pairs refresh ms/session via\n the real refresh_action_pairs -- the exact l3tk regression class; query p50/p95 via\n the real compute_latency_percentiles route-latency surface).\n- tests/benchmarks/floors.json: committed baseline, direction-aware per-metric tolerances\n (50-70%), explicitly measured_under_load=true (concurrent live rebuild + nix build +\n another agent's pytest run on this machine) with a note recommending a quiet-machine\n re-run to tighten.\n- tests/unit/infra/test_perf_floors.py: 8 unit tests (direction-aware compare logic,\n floors round-trip, one --quick end-to-end smoke run of every measurement group).\n- .github/workflows/nightly-scale.yml: new perf-floors job, fail-soft via job+step\n continue-on-error, posts ::warning:: on regression, uploads JSON artifact,\n update-perf-floors workflow_dispatch input to ratchet.\n- docs/plans/test-clock-allowlist.yaml: allowlisted the runner's real report timestamp.\n\nDeferred / not found: the \"3.14t gil_bench harness\" mentioned in the design as living\nin a session scratchpad was not located as a committed artifact in this checkout --\nnot included. If it exists elsewhere, add it as a fifth measurement group in a\nfollow-up. p99 not produced: production compute_latency_percentiles only computes\np50/p95 -- used the real metric rather than fabricate an unbacked p99.\n\nVerification: devtools verify --quick exit 0 (16/16 steps); devtools test\ntests/unit/infra/test_perf_floors.py 8 passed; actionlint clean; manual end-to-end run\n~8s, 0 regressions, delta table in PR body.","owner":"ezo.dev@gmail.com","priority":3,"started_at":"2026-07-19T14:03:56Z","status":"closed","title":"Nightly perf floors: benchmark regression lane from the war-room harnesses","updated_at":"2026-07-19T14:28:36Z"} -{"_type":"issue","acceptance_criteria":"Session-commit stubs and the unused web-construct row are deleted with grep evidence of zero remaining references; the stale fuzz README is deleted or rewritten to match current fuzz targets; topology projection regenerated if a module disappears (render all --check green); devtools verify (mypy + testmon-affected) green. No behavior change intended \u2014 no new tests memorializing the deletion.","close_reason":"Satisfied by PR #2882: persist_session_commits/session_commit_edge_to_row/ArchiveWebConstructRow deleted with rg-confirmed zero remaining references; stale fuzz README reference fixed. devtools verify --quick green.","closed_at":"2026-07-15T00:02:16Z","comment_count":0,"created_at":"2026-07-03T04:32:24Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:49:13Z","created_by":"Sinity","depends_on_id":"polylogue-a7xr","issue_id":"polylogue-1a9","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Single surgical-renewal PR; targets enumerated on the issue. GH issue thread (body + comments) is input, not authority; this bead's scope statement wins where they conflict.","design":"Targets (gh#2477, code-confirmed): insights/session_commit.py persist_session_commits is a no-op ('del edges, repo_id') and session_commit_edge_to_row has no callers \u2014 delete both; storage/sqlite/archive_tiers/write.py ArchiveWebConstructRow is never instantiated (_write_web_constructs inserts inline) \u2014 delete the dataclass; tests/fuzz/README.md references polylogue.lib.timestamps (now polylogue.core.timestamps) \u2014 fix the doc. One surgical-renewal PR; grep each symbol across both sync/async trees before declaring dead.","external_ref":"gh-2477","id":"polylogue-1a9","issue_type":"chore","labels":["area:substrate","delivery:M-substrate-consolidation","delivery:ac-patched","lane:substrate-consolidation","refactor"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=M-substrate-consolidation; lane=substrate-consolidation; readiness=D-horizon-ready; proof=layering/import graph diff, parity tests before/after refactor, public-model compatibility suite. Original readiness=E-spec-needed.\nCompleted 2026-07-14: All dead symbols removed and verified to have zero callers via grep. Changes in PR #2882 (chore: remove dead session-commit stubs and unused web-construct row). devtools verify --quick all gates pass. No behavior change - mechanical cleanup only.","owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"Remove dead session-commit stubs + unused web-construct row + stale fuzz README","updated_at":"2026-07-15T00:02:16Z"} -{"_type":"issue","acceptance_criteria":"A synthetic index rebuild leaves retained embedding rows for deleted/superseded messages and absent sessions; automatic bounded convergence removes only the orphan/superseded rows, updates status counters, survives interruption/retry idempotently, and preserves active vectors. Live inspect-before/after evidence reports the 11,348/6 baseline and resulting exact counts. Mutation checks disabling generation/identity/content-hash guards fail. Focused embedding storage/convergence tests and devtools verify --quick pass.","close_reason":"Implementation is landed and the only remaining work is authoritative generation activation followed by bounded live reconciliation. That proof is now an explicit b5l transition acceptance criterion with the current 22,442/303 census. Identity-present changed-text lifecycle remains 0k6.","closed_at":"2026-07-14T23:45:10Z","comment_count":0,"created_at":"2026-07-10T16:52:54Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T18:52:58Z","created_by":"Sinity","depends_on_id":"polylogue-0k6","issue_id":"polylogue-1dk1","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-10T18:52:58Z","created_by":"Sinity","depends_on_id":"polylogue-b5l","issue_id":"polylogue-1dk1","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-10T18:52:57Z","created_by":"Sinity","depends_on_id":"polylogue-mhx","issue_id":"polylogue-1dk1","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Live 2026-07-10 source-v4 audit found 675,825 message_embeddings_meta rows but only 675,725 status-summed embedded messages, including 11,348 message IDs absent from the rebuilt index and six embedding_status rows for absent sessions. These retained rows inflate counters/storage and made approximate coverage exceed 100%. Status now suppresses false precision, but the stale bytes and lifecycle remain.","design":"Treat index generation replacement as an explicit embeddings reconciliation boundary. Define the authoritative join by stable session/message identity plus content hash; after a blue-green/index rebuild, identify metadata/vector/status rows whose source objects no longer exist or whose content hash is superseded. Reconcile in bounded batches with generation/epoch evidence, preserving active vectors and resumability. Daemon convergence owns automatic cleanup; manual CLI is inspect/break-glass. Coordinate with b5l generation swap and 0k6 changed-text replacement rather than adding a second vector lifecycle.","id":"polylogue-1dk1","issue_type":"bug","labels":["area:embeddings","area:storage","delivery:J-embeddings-retrieval","horizon:frontier","lane:embeddings-retrieval"],"notes":"PR #2749 (branch fix/orphan-embedding-reconcile) implements the identity-scoped reconciler:\n- polylogue/storage/embeddings/reconcile.py: reconcile_embedding_orphans / inspect_embedding_orphans,\n bounded (max_count, default 500), resumable (more_pending), idempotent, three guards (identity NOT EXISTS\n join = sole deletion trigger; content-hash mismatch on an identity-present message is never deleted -\n that's 0k6's re-embed territory; quiet-window skips rows embedded within the last 5 minutes to avoid\n racing an in-flight full-replace write). Recomputes message_count_embedded for touched sessions.\n- Wired into daemon convergence via periodic_embedding_orphan_reconcile_check (embedding_backlog.py,\n 15 min interval, 500-row batches) alongside the existing embed backlog drain loop.\n- Manual break-glass/inspect: `polylogue ops maintenance embedding-orphan-reconcile` (--yes to apply).\n- Focused tests: tests/unit/storage/test_embedding_orphan_reconcile.py (8 cases: identity removal,\n content-hash guard preserved, orphan status removal, quiet-window guard, bounded/resumable batching +\n idempotency, dry-run no-mutation, inspect alias, missing-embeddings.db noop) +\n tests/unit/daemon/test_embedding_orphan_reconcile_daemon.py (config-gating, missing-index noop, real\n removal) + 2 CLI tests in test_archive_maintenance_cli.py. 55 tests pass, mypy --strict clean.\n- Design deviation: did NOT gate on the b5l blue-green generation pointer (not yet landed) - uses direct\n identity comparison against the live index.db instead. Functionally equivalent for the reported bug\n (dangling identities); can be generation-scoped later without changing the public shape.\n- NOT DONE: live inspect-before/after run against the real archive reporting the 11,348/6 baseline and\n resulting exact counts (AC requirement). This worktree has no access to the operator's real archive.\n Follow-up: run `polylogue ops maintenance embedding-orphan-reconcile --yes` against the live archive,\n record before/after counts here, then close.\n- Manual smoke evidence (demo archive, not live): deleted one live embedded message from index.db,\n dry-run reported 1 orphan, --yes removed exactly it + recounted message_count_embedded, follow-up\n dry-run confirmed clean/idempotent.\n[Closure audit / live census 2026-07-12T09:54:52.466Z, code 7fd5b6bb9] PR #2755 landed the bounded identity-orphan reconciler, but this bead remains OPEN. Read-only production-route dry-run against /home/sinity/.local/share/polylogue (embedding-orphan-reconcile --output-format json; dry_run=true, mutates=false) scanned 741,327 message_embeddings_meta rows, 741,327 vector rows, and 17,235 embedding_status rows. Current candidates: 22,442 orphan message identities (22,442 meta + 22,442 vector), 303 orphan status rows, zero quiet-window skips, more_pending=true; removed counts all zero. This supersedes the 2026-07-10 11,348/6 observation as the current pre-apply census while preserving that historical baseline. DO NOT APPLY yet: active index.db is schema v32 while packaged INDEX_SCHEMA_VERSION is v35, so it is not authoritative deletion truth and the merged guard correctly refuses mutation. Remaining closure work: (1) complete/materialize an authoritative v35 index; schema version alone is insufficient\u2014gate cleanup on rebuild/materialization generation/readiness, because raw materialization and orphan reconciliation are sibling daemon loops; (2) rerun dry-run, then bounded apply passes until more_pending=false and record exact before/after meta/vector/status counts plus preserved-active-vector/backlog evidence; (3) complete or explicitly defer the identity-present changed-text/superseded-row lifecycle to open polylogue-0k6, since reconcile.py deliberately preserves content-hash mismatches. Post-merge operator-quality follow-up: wrap apply schema refusal as ClickException (CodeRabbit discussion_r3566069102); this is not the primary open-state reason.\n2026-07-13 embeddings-hygiene resume / PR #2796: read-only live readiness check found the public archive pointer anchor /realm/db/polylogue/index.db resolving to v35 generation gen-v35-fastforward-1783887475997-88c34860. The active index reports schema v35 (packaged v35); exactly one matching generation record has a non-empty source snapshot, but its state is inactive. It is therefore NOT authoritative deletion truth and no reconciliation apply or live census mutation was run. Branch commit 4326d07dc fixes the safe product-path residual: public index.db symlinks now read generation metadata beside the pointer anchor/database tier, while requiring the same active state, source snapshot, schema, and identity guards. Focused verification: test_embedding_orphan_reconcile.py 16 passed; tests/unit/storage -k embedding 89 passed. Next live step belongs to the v35 activation owner: make the matching generation record active according to the recorded cutover protocol, then rerun inspect and only then consider bounded apply.\nSCOPE NARROWED 2026-07-13 (PR #2796 merged as 4177544ce): code side satisfied \u2014 bounded orphan cleanup is idempotent, revalidates generation identity before commit, requires an ACTIVE source-snapshotted generation record beside the pointer anchor (external-tier regression covers the public index.db symlink layout), and mutation-guard tests fail when any authority check is removed. REMAINING (why this stays open): live apply is deliberately blocked \u2014 the live v35 record gen-v35-fastforward-1783887475997-88c34860 is state=inactive, so deletion authority does not exist yet. Sequence: (1) v35 activation owner marks the matching generation active under the recorded cutover protocol; (2) fresh read-only inspect; (3) bounded apply; (4) record before/after counts against the 11,348/6 baseline in this bead. Nothing else remains in code.","owner":"ezo.dev@gmail.com","priority":2,"status":"closed","title":"Reconcile orphan embedding rows across index rebuild generations","updated_at":"2026-07-14T23:45:10Z"} -{"_type":"issue","acceptance_criteria":"bead-cluster.py either has a CommandSpec entry (devtools workspace bead-cluster or similar) or an explicit documented reason for staying unregistered.","close_reason":"Fixed and merged via PR #3312 - recovers functionality lost when PR #3188's over-broad dead-code sweep deleted .agent/tools/bead-cluster.py as 'no live references' without cross-checking this still-open bead. Recovered the pre-deletion version via git show 9e9e33950^:.agent/tools/bead-cluster.py, confirmed the algorithm is genuinely distinct from delivery-gate-status (footprint/overlap/contention clustering of ready beads vs. gate-progress board), and ported it to devtools/bead_cluster.py preserving the algorithm exactly. Fixed two real bugs surfaced while making it work against the current bd CLI: (1) bd ready --json truncates at 100 rows and appends a trailing plain-text pagination notice that broke json.loads - fixed via a JSONDecoder.raw_decode-based tolerant parser; (2) main() returned None instead of the int the CommandSpec dispatch contract requires. Registered as 'workspace bead-cluster' in devtools/command_catalog.py with a use_when explicitly distinguishing it from delivery-gate-status. 32 new tests (footprint extraction, classification, overlap-graph clustering, contention detection, roster validation, the tolerant parser, mocked bd subprocess calls, end-to-end main()). Verified against the live Beads workspace: devtools workspace bead-cluster --max-priority 1/--json/--validate-roster all produced sensible real output. mypy --strict, ruff, devtools render devtools-reference/render all --check, devtools verify --quick all clean. Personally reviewed the full diff (CodeRabbit rate-limited) before merging.","closed_at":"2026-07-27T08:55:44Z","comment_count":0,"created_at":"2026-07-16T10:20:47Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T12:20:46Z","created_by":"Sinity","depends_on_id":"polylogue-2yax","issue_id":"polylogue-1ebm","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-16T12:20:46Z","created_by":"Sinity","depends_on_id":"polylogue-utf","issue_id":"polylogue-1ebm","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"dogfood-2 devtools triage (investigations/devtools-triage.md, F-020): .agent/tools/bead-cluster.py commit 49182a7f2 message says feat(devtools): add bead-cluster.py execution-frontier clustering tool, but the file lives in .agent/tools/, was never registered as a CommandSpec, and is invisible to devtools --help, render devtools-reference, and every completeness mechanism polylogue-utf/polylogue-o21 protect. Confirmed by direct diff NOT redundant with delivery-gate-status.py -- different questions over the same data (footprint/overlap clustering vs gate-progress board). Implements polylogue-2yax (footprint/overlap/contention clustering of ready beads).","design":"Register as a devtools workspace subcommand (closest analog: workspace frontier), or formally document why it is intentionally excluded from the catalog if there is a reason found during implementation.","id":"polylogue-1ebm","issue_type":"task","labels":["area:devtools","discovered-from:dogfood-2"],"notes":"Recovered .agent/tools/bead-cluster.py (deleted by PR #3188) as devtools/bead_cluster.py, registered as `devtools workspace bead-cluster` CommandSpec. Preserved the clustering algorithm exactly; fixed bd-ready pagination-truncation JSON parsing bug + main() int-return contract; added tests/unit/devtools/test_bead_cluster.py (32 tests); regenerated docs/devtools.md. Verified against live repo Beads data. PR: https://github.com/Sinity/polylogue/pull/3312 (open, not merged).","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"devtools: register bead-cluster.py as a workspace subcommand","updated_at":"2026-07-27T08:55:44Z"} -{"_type":"issue","acceptance_criteria":"`polylogue-1fp` includes a before/after ownership map, preserves public behavior through parity tests, and deletes or redirects the old path with compatibility notes where needed. The refactor does not change evidence semantics unless a migration and release note say so. Verification artifact: CLI/daemon/MCP/Python/web query parity suite and content-hash citation drift fixture.","comment_count":0,"created_at":"2026-07-03T13:23:40Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T15:23:39Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.14","issue_id":"polylogue-1fp","metadata":"{}","type":"blocks"},{"created_at":"2026-07-03T15:24:09Z","created_by":"Sinity","depends_on_id":"polylogue-exb","issue_id":"polylogue-1fp","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:31:13Z","created_by":"Sinity","depends_on_id":"polylogue-t46","issue_id":"polylogue-1fp","metadata":"{}","type":"parent-child"}],"dependency_count":2,"dependent_count":0,"description":"api/archive.py is a 5,259-line, 126-method God-facade; every surface (CLI, MCP, daemon, devtools) imports the whole Polylogue object to use its own small slice. Consequences: any facade edit rebuilds every surface's mental model, surfaces cannot declare what they actually need, test doubles are all-or-nothing, and the substrate->api inward imports (see the layering bead) formed precisely because the facade is the only place some primitives live. 9e5.14 produces the evidence (which of the 126 methods each surface calls); this bead executes the split.","design":"Shape: capability protocols (QueryReads, SessionReads, InsightReads, AssertionWrites, MaintenanceOps, EmbeddingOps...) defined next to their implementations; the Polylogue facade becomes a thin composition root that constructs and hands out protocol views \u2014 kept for the public library API (docs promise it), but internal surfaces import their protocol, not the facade. Execution order: (1) land the layering bead first (substrate must stop calling up); (2) cut protocols along the 9e5.14 usage-map clusters, biggest consumer first (MCP tools likely map cleanly to read protocols); (3) each protocol extraction is one PR: define protocol, move/alias methods, re-point one surface, mypy --strict is the net (memory: trust mypy for identifier refactors; testmon for the behavioral slice). Anti-goal: do NOT create a parallel service layer \u2014 the implementations stay where they are; protocols are typing views over existing code. Success metric: api/archive.py under ~1,500 lines of composition + public-API preservation; no surface imports a method it does not call (import-linted via the layering machinery).","id":"polylogue-1fp","issue_type":"task","labels":["area:substrate","delivery:C-read-evidence-contract","delivery:ac-patched","lane:read-contracts","refactor"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=C-read-evidence-contract; lane=read-contracts; readiness=D-horizon-ready; proof=CLI/daemon/MCP/Python/web query parity suite and content-hash citation drift fixture. Original readiness=E-spec-needed.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Facade decomposition: split api/archive.py into per-capability protocols","updated_at":"2026-07-07T12:59:19Z"} -{"_type":"issue","acceptance_criteria":"A representative Codex exec tool-use record with nested arguments and cmd is queryable through command:polylogue. Existing command-shaped tool inputs remain unchanged. A focused real-route regression test passes, the affected query tests pass, and the original live dogfooding query returns actual matches after the archive has the compatible read path or materialization.","assignee":"Sinity","close_reason":"Satisfied on master by PRs #2853/#2855 (219869f66, 13d19ae36): Codex exec command payloads normalize into action queries with legacy evidence preserved; the later verification found no residual code gap.","closed_at":"2026-07-14T23:12:16Z","comment_count":0,"created_at":"2026-07-13T16:40:56Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"## Problem\nDogfooding exposed that actions where command:polylogue returns no matches for Codex shell invocations. Codex exec tool uses nested arguments containing cmd, while the action projection and search index only recognize command.\n\n## Steps to Reproduce\nQuery the live archive with actions where tool:bash AND command:polylogue, then inspect a known Codex exec tool-use record whose nested arguments contain cmd with a Polylogue invocation. The query returns no match even though the action exists.\n\n## Outcome\nNormalize this real capture shape so command predicates and action-text queries can find coding-agent shell activity.","design":"Trace the canonical tool-use normalization path before storage. Extract shell command text from supported provider shapes, including nested arguments encoded as an object or JSON string and the Codex cmd field, into the existing canonical command representation. Keep query semantics provider-neutral. Cover the import-to-query route with a fixture that would fail if nested arguments/cmd extraction is removed.","id":"polylogue-1frn","issue_type":"bug","notes":"[2026-07-14 verification, no new code] Investigated as part of this cluster (paired with polylogue-9e5.8.4, see PR #2870). This bead is already fully resolved on origin/master by two PRs merged before this session started: 219869f66 \"fix(actions): expose Codex exec payloads as commands (#2853)\" (write-time: Codex parser promotes cmd/string-arguments execution payloads into canonical command field, per-tool-name allowlist to avoid promoting unrelated tools' arguments) and 13d19ae36 \"fix(actions): read legacy Codex commands without rewriting evidence (#2855)\" (read-time: bounded SQL _action_command_expression makes already-materialized legacy rows queryable via command: predicates without rewriting stored evidence, since rewriting would break content-hash citation anchors). Both cite \"Ref polylogue-1frn\" in their commit bodies.\nRe-verified locally: devtools test tests/unit/sources/test_parsers_codex.py -k exec (1 passed), full test_parsers_codex.py (59 passed), tests/unit/cli/test_query_expression.py -k \"legacy_codex or codex\" (2 passed, including test_legacy_codex_execution_payloads_are_queryable_without_rewrite which directly proves the AC: \"actions where command:polylogue\" / \"blocks where command:polylogue\" match pre-existing legacy rows with no backfill). AC \"nested arguments encoded as an object or JSON string and the Codex cmd field\" is covered by _tool_input_from_arguments (codex.py) which parses JSON-string arguments, promotes nested \"cmd\" keys, and promotes nested \"arguments\" string keys only for a closed execution-tool-name set. No further code change identified as needed. No new commit made for this bead -- treating as already_done, not closing per repo convention (orchestrator closes after merge-train review).","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-13T17:04:46Z","status":"closed","title":"Normalize Codex exec commands for action queries","updated_at":"2026-07-14T23:12:16Z"} -{"_type":"issue","acceptance_criteria":"1. The matcher excludes tokens inside filesystem paths, filenames with extensions, and code/quoted-output spans. 2. It rejects candidates that do not match the bead-id shape (long hex is not a bead id). 3. Re-run reports the genuine dangling reference and not the five false positives. 4. A fixture covers each of the five false-positive shapes so they cannot regress.","comment_count":0,"created_at":"2026-07-28T20:05:32Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Measured 2026-07-28: the X2 'names nonexistent bead' check reports 9 findings; classified by hand, 5 of the 6 distinct cases are false positives because the matcher does not exclude non-prose contexts.\n\n polylogue-3gd.3 -> 'polylogue-mcp' is a BINARY NAME in /nix/store/.../bin/polylogue-mcp\n polylogue-yyvg.6 -> 'polylogue-all' is a FILENAME, 00-polylogue-all.tar.gz\n polylogue-8jg9.1 -> 'polylogue-all' is the check QUOTING ITS OWN OUTPUT about yyvg.6\n polylogue-yla8 -> 'polylogue-a92969b6e4c8d728b' is an agent SESSION id\n polylogue-1xc.14(.1/.1.1/.1.2/.1.3) -> 'polylogue-a47769bba68869d49' is an agent SESSION id (5 findings, one cause)\n polylogue-yyvg.7 -> 'polylogue-x2q3s' is the ONLY genuine dangling bead reference\n\nA check whose findings are 5/6 noise trains readers to skip it, which is worse than not having it -- the one real dangling reference was invisible inside the noise.\n\nBead ids have a known shape (short base36 suffix, optional dotted child path). Session ids are long hex. Filenames and store paths are recognisable by their surrounding characters.","id":"polylogue-1hal","issue_type":"task","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"backlog-hygiene X2 check reports dangling bead refs for binaries, filenames and its own output","updated_at":"2026-07-28T20:05:32Z"} -{"_type":"issue","acceptance_criteria":"Repo-scoped post appears in the next session's preamble and marks delivered; session-tree scope reaches a spawned subagent live; caps/ttl enforced; CLI+webui board surfaces work; delivery events queryable.","close_reason":"Absorbed by polylogue-s7ae.3: blackboard posts, scoped delivery, unread/read/ack receipts, expiry, context injection, and bounded wakeup are one coordination-message capability.","closed_at":"2026-07-15T19:54:00Z","comment_count":0,"created_at":"2026-07-03T15:16:03Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:31:05Z","created_by":"Sinity","depends_on_id":"polylogue-s7ae","issue_id":"polylogue-1hj","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-04T20:02:00Z","created_by":"Sinity","depends_on_id":"polylogue-s7ae.3","issue_id":"polylogue-1hj","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Raw-log 05-08, uncaptured: a groupchat-ish channel for agents, subagents, and operator. The substrate half exists (blackboard_post/list in user.db) but nothing DELIVERS \u2014 a post is seen only if someone polls. The channel version: posts address scopes (repo, session-tree, broadcast, direct) and ARRIVE via the injection machinery, with operator surfaces in CLI/webui. The restrained hive-mind: a message bus with judgment-shaped delivery, not a chatroom streaming into every context window.","design":"(1) Extend blackboard rows: scope (repo | session-tree | broadcast | direct:session-ref), ttl, per-session delivered_at receipts. (2) Delivery legs in restraint order: SessionStart preamble gains a 'messages for you' section (scope-matched, undelivered, within ttl, cap ~3, refs style); mid-session delivery ONLY for direct-scope urgent via the advisory path (bfv budgets). (3) The concrete payoff: parent posts scope=session-tree constraints; spawned subagents receive them at SessionStart \u2014 cross-agent invariants without stuffing dispatch prompts. (4) Everything archived by construction (posts are user.db rows, deliveries are hook events) \u2014 the channel is queryable evidence. After 37t.4 and d1y.","id":"polylogue-1hj","issue_type":"task","labels":["area:context","area:mcp","delivery:D-agent-context-coordination","lane:agent-coordination"],"notes":"Coherence (2026-07-03): delivery legs register as ContextSources (session-start messages section; direct-scope urgent as the mid-session moment) \u2014 caps/ttl stay here, token arbitration moves to the scheduler.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=D-agent-context-coordination; lane=agent-coordination; readiness=D-horizon-ready; proof=two-agent separate-worktree proof with before/after coordination envelopes. Original readiness=D-horizon-ready.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Blackboard as agent comms: cross-session messages that actually arrive","updated_at":"2026-07-15T19:54:00Z"} -{"_type":"issue","acceptance_criteria":"Test stack documented in the v2 scaffold; component lane runs per-PR within budget; one e2e journey and one visual snapshot demonstrably catch a seeded regression; re-baseline procedure documented; tests/visual retirement mapped surface-by-surface. VERIFY: CI run links + the seeded-regression demonstrations in notes.","comment_count":0,"created_at":"2026-07-08T18:15:42Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:10:15Z","created_by":"Sinity","depends_on_id":"polylogue-ap7","issue_id":"polylogue-1ilk","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T19:13:44Z","created_by":"Sinity","depends_on_id":"polylogue-bby","issue_id":"polylogue-1ilk","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"description":"Web UI test coverage today is DOM-smoke only (tests/visual/test_reader_*.py) plus demo-visual-verify in CI. The webui-v2 stack decision (bby.11: TypeScript+Preact+Vite per its design field) determines the right test stack, so this bead is deliberately blocked on it rather than investing in harnessing JS-in-Python-strings that v2 replaces. Operator direction 2026-07-08: the webui plan must be figured out end-to-end so agents can execute rapidly - testing is part of that plan.\n","design":"Decide-with-the-stack, then implement: (a) component/unit lane - vitest + @testing-library/preact for rendered components against fixture payloads (typed API client from the daemon OpenAPI gives contract-checked mocks); (b) e2e lane - playwright against the daemon serving the demo archive (existing demo seed machinery), smoke journeys: open reader, search, expand tool block, follow lineage link; (c) visual regression - playwright screenshot snapshots of the canonical views, tolerances tuned to the design-token system (9xuk) so token changes re-baseline deliberately, wired like syrupy snapshots (dedicated fix(test) re-baseline PRs); (d) CI placement respecting the per-PR economy: component lane per-PR (fast), e2e+visual on master/nightly like the heavy pytest suite. Existing tests/visual DOM-smoke retires only when the surfaces it covers are re-covered.\n","id":"polylogue-1ilk","issue_type":"task","labels":["area:test","area:web","horizon:mid"],"notes":"2026-07-10 live audit: its stack-decision blocker is stale because bby.11 is ratified. First slice must install Playwright against the current shell, not wait for v2: boot/search/open/back; credentialed first-party flow; deterministic delay/401/409/503/out-of-order requests; keyboard/focus/a11y; responsive screenshots/traces; current known-red journeys retained as evidence. Full packet: .agent/scratch/2026-07-10-webui-verifiability-audit.md.\n[Recovered Web Cockpit no-import ruling, 2026-07-11] The kit's probe_current_web.py and audit_web_surface.py are not a test harness: they infer daemon flags from help text, request route literals with urllib, scan source keywords, and emit manifests without browser DOM, interaction, focus, accessibility, responsive, or assertion coverage. Do not import them or count their green packaging checks as web proof. The kit's complete/partial/unavailable/timeout/forbidden/error inventory is useful fixture input only; implement it through the current-shell Playwright journeys already specified here, retaining known-red traces until repaired.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Webui v2 test stack: vitest component lane + playwright e2e/visual-regression riding the stack decision","updated_at":"2026-07-11T15:52:31Z"} -{"_type":"issue","acceptance_criteria":"Detector produces a correct suggestion from seeded telemetry (dominant flag pattern -> candidate with evidence aggregate); accepting in judge writes the scoped settings row and the new default takes effect; rejecting suppresses re-proposal; suggestions capped; deployment keys never proposed.","comment_count":0,"created_at":"2026-07-03T15:28:39Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T17:28:39Z","created_by":"Sinity","depends_on_id":"polylogue-20d.14","issue_id":"polylogue-1jc","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T22:29:31Z","created_by":"Sinity","depends_on_id":"polylogue-37t.10","issue_id":"polylogue-1jc","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-07T15:02:03Z","created_by":"Sinity","depends_on_id":"polylogue-37t.12","issue_id":"polylogue-1jc","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:34:50Z","created_by":"Sinity","depends_on_id":"polylogue-w8db","issue_id":"polylogue-1jc","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-03T17:28:39Z","created_by":"Sinity","depends_on_id":"polylogue-y4c","issue_id":"polylogue-1jc","metadata":"{}","type":"blocks"}],"dependency_count":3,"dependent_count":0,"description":"The archive records every polylogue invocation (its own dogfood telemetry + affordance usage), which means it can OBSERVE preference: the operator adds --view dialogue to 80% of codex reads; always re-sorts by recency; never opens temporary sessions from lists; always bumps --max-tokens on read. Static defaults leave that signal on the floor; silent auto-adaptation would be drift nobody audited. The middle path is the pattern the product already owns: OBSERVED preference becomes a CANDIDATE settings change in the judgment queue \u2014 'you used --view dialogue in 47/58 codex reads this month; make it the codex-scope default?' \u2014 accepted with one keystroke in polylogue judge, revocable, and recorded with its evidence like every other judged claim.","design":"(1) SIGNAL: invocation spans (20d.14 CLI telemetry) + affordance usage rows give (verb, flags, scope, count) aggregates; a detector runs as a low-frequency insight pass over trailing 30d with minimum support (n>=20) and dominance (>=70%) thresholds \u2014 both themselves y4c prefs. (2) PROPOSAL: emits candidate assertions (kind: setting_suggestion \u2014 reuse setup_improvement machinery from 37t.10 if the shapes align rather than adding a kind; check the every-kind-has-a-surface cost) carrying: the proposed settings row (key, scope, value), the evidence aggregate, and the expected effect ('saves typing --view in ~40 invocations/month'). (3) JUDGMENT: appears in polylogue judge like any candidate; accept writes the settings row via the normal y4c path (attributed to the assertion, so 'why is this my default?' resolves to evidence); reject suppresses re-proposal for that key+scope. (4) RESTRAINT: max N open suggestions at once; never proposes anything in the deployment class (toml/env keys are out of scope by construction); the detector itself is off-by-default until the telemetry lane exists, then default-on with the cap (jgp: ambient, restrained volume). (5) This is deliberately the same loop as agent memory: observation -> candidate -> judgment -> injected default \u2014 configuration as another kind of judged memory.","id":"polylogue-1jc","issue_type":"feature","labels":["area:analytics","area:context","area:surface","delivery:E-variants-preferences","lane:variants-preferences"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=E-variants-preferences; lane=variants-preferences; readiness=D-horizon-ready; proof=mixed-language variant fixture with source/variant/alignment rendering in CLI/web/MCP. Original readiness=D-horizon-ready.\nRECONCILED 2026-07-13: this is a LOOP_REGISTRY instance (rxdo.11) \u2014 watch: config-usage standing query; measure: metric:; propose: config-diff candidates; judge: operator gate; bump: versioned prefs. Register it, do not build bespoke plumbing. Same shape as 37t.10.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Learned defaults: the archive proposes your configuration as judged candidates","updated_at":"2026-07-13T03:59:58Z"} -{"_type":"issue","close_reason":"Fixed in PR #3341: replaced the now-inert '_action_relation_for_query -> actions' rename mutation with a mutation forcing action_relation_select_sql(session_placeholders=None)'s genuinely unbounded windowed-CTE recompute (measured 53500 VM steps vs 400 bounded), restoring the anti-vacuity canary's discriminating power in both affected tests.","closed_at":"2026-07-27T17:37:04Z","comment_count":0,"created_at":"2026-07-20T09:39:21Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Pre-existing failures (confirmed on origin/master, unrelated to any of the z9gh.2/z9gh.3 execution-residual work in fix/query/z9gh-execution-residuals): tests/unit/storage/test_archive_tiers_archive.py::test_exact_session_action_count_bounds_pairing_before_global_ranking and tests/unit/archive/query/test_execution_control.py::test_exact_session_multi_aggregate_work_is_not_amplified_by_irrelevant_growth both monkeypatch _action_relation_for_query to force a fallback to the plain 'actions' compatibility view (simulating pre-z9gh.2 global-first behavior) and assert the resulting query costs >=50000 SQLite VM steps as an anti-vacuity control. Since PR #3018 (z9gh.2) replaced the old windowed-CTE 'actions' view with one backed by the small, indexed, pre-materialized action_pairs table, that fallback is no longer expensive at these tests' data scale (measured: 0 and 400 VM steps respectively) -- the mutation no longer reproduces a meaningfully different/expensive path, so the anti-vacuity check is vacuous. Also noted in the same run: test_api_query_units_routes_through_execution_control and test_api_multi_aggregate_receipt_reports_real_work_selection_and_delivery fail identically on unmodified master with an unrelated 'query_units' vs 'api.query_units' call-log naming mismatch -- separate stale assertion, same file. Fix: either raise the mutation to something still meaningfully expensive at this data scale (e.g. force a full block_type scan directly, or scale up the noise-session count) or lower/remove the now-invalid >=50000 threshold and replace with a plan-shape assertion (EQP-based, as done in the new test_bounded_action_relation_plans_session_index_not_archive_wide_tool_scan). Discovered while implementing the z9gh.2 F-006/F-007 session-alias EQP fix.","id":"polylogue-1ldl","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":2,"status":"closed","title":"Stale 'archive-wide fallback is expensive' mutation assumption in action/multi-aggregate VM-step regression tests","updated_at":"2026-07-27T17:37:04Z"} -{"_type":"issue","acceptance_criteria":"The three raw-log examples work as presets/inline specs on the live archive; compile_context and read share the machinery; presets visible to completions; omission markers always carry resolvable refs.","comment_count":0,"created_at":"2026-07-03T15:15:56Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:12:56Z","created_by":"Sinity","depends_on_id":"polylogue-4p1","issue_id":"polylogue-1lm","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T20:10:15Z","created_by":"Sinity","depends_on_id":"polylogue-ap7","issue_id":"polylogue-1lm","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-04T22:29:25Z","created_by":"Sinity","depends_on_id":"polylogue-jnj.1","issue_id":"polylogue-1lm","metadata":"{}","type":"blocks"}],"dependency_count":1,"dependent_count":0,"description":"'Prose-only' is one point in a space the operator keeps requesting by example: user messages plus directly-adjacent agent replies (raw-log 07-02 \u2014 what the agent intended to report, minus the toil); tool outputs truncated from the middle beyond N lines (raw-log 06-23); decisions-only; tool-skeleton (calls + outcomes, no bodies); failure-slices; reboot-with-refs (37t.3); compact recaps for mass export ('every sinex-related chatlog in compact form for gptpro', 06-18). One algebra: SELECTOR (role, material-origin, block type, adjacency, outcome class, topic) x TRANSFORM per class (verbatim | refify | truncate-middle(n) | fold-to-line | recap) x BUDGET (per-class allowances, tail/head bias). Prose-only itself conflates authored prose, protocol chatter, and generated packs \u2014 material_origin already distinguishes them; the algebra should too.","design":"(1) Extend ProjectionSpec (jnj.1) with typed selector predicates (reuse the DSL block-predicate grammar \u2014 no second filter language) and per-class TransformSpec; compile_context and renderers consume the same spec (4p1's Projection axis, deepened). (2) Adjacency selectors are the novel primitive: adjacent-to(role:user, distance<=1, after) via window functions over position. (3) Transforms compose with ap7 semantic renderers; truncate-middle keeps first/last K lines with an omission marker carrying the block ref (expandable, jgp). (4) Named presets as registry entries: prose, dialogue, skeleton, decisions, forensic, reboot, compact-export \u2014 uniform across read --view, MCP detail levels, export profiles, context compilation. (5) Acceptance driven by the raw-log examples: each expressible as a one-line spec, no code.","id":"polylogue-1lm","issue_type":"task","labels":["area:context","area:query","area:surface","delivery:C-read-evidence-contract","horizon:mid","lane:read-contracts"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=C-read-evidence-contract; lane=read-contracts; readiness=A-implementation-ready; proof=CLI/daemon/MCP/Python/web query parity suite and content-hash citation drift fixture. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/157_polylogue_1lm.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nPriority correction 2026-07-15: promoted P3 to P2 as the transcript/content projection slice of the sole ReadRequest algebra. It remains sequenced behind the shared projection normalizer; priority does not imply a parallel executor.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Composable transcript views: selector x transform x budget algebra","updated_at":"2026-07-15T19:54:01Z"} -{"_type":"issue","acceptance_criteria":"A single recommended in-page placement direction (or an explicit, justified division between F2/F3 and F4) is recorded on polylogue-90y before implementation of the in-page overlay begins.","close_reason":"Resolved by the follow-up Claude Design pass (2026-07-09), grounded in real authenticated ChatGPT/Claude.ai screenshots. F2/F3 and F4 are not competing alternatives -- they're a two-layer split: Layer 1 (F4, ambient/blended) extends the host's existing per-message action row (capture-status dot + save-to-Polylogue action, matched to ~30px ghost icon size/style both hosts already use); Layer 2 (F2/F3, deep-dive/separate) is the corner chip + slide-over for cross-conversation intelligence with no host equivalent (cost, recall, assertions, timeline). Boundary rule recorded on polylogue-90y verbatim: 'Per-message state blends in. Cross-conversation intelligence floats.' Both layers checked against real composer/sidebar proportions, not just a fixed demo canvas.","closed_at":"2026-07-09T12:40:25Z","comment_count":0,"created_at":"2026-07-09T11:49:40Z","created_by":"Sinity","dependency_count":0,"dependent_count":1,"description":"The 2026-07-09 Claude Design pass (docs/design/browser-capture-redesign/) produced two parallel, unreconciled in-page placement strategies for the same capability: F2/F3 (shadow-DOM ambient chip + slide-over, fully separate from host DOM, per polylogue-90y's original taste constraints) and F4 (native-blended, woven into the host's own per-message action row). A follow-up brief requesting a single recommended direction (or an explicit division of labor between the two), grounded in real authenticated ChatGPT/Claude.ai screenshots, has been prepared but not yet run through Claude Design. The reference screenshots are kept local/private (not committed to this public repo -- they contain real chat titles/message content from an authenticated session); delivered directly to the operator. Run that follow-up pass, then update polylogue-90y's design notes with the resolved direction before implementation starts.","id":"polylogue-1nb2","issue_type":"task","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Resolve F2/F3-vs-F4 in-page placement strategy for browser-capture redesign","updated_at":"2026-07-09T12:40:25Z"} -{"_type":"issue","acceptance_criteria":"1. A committed hotspot map identifies each listed control center, its dependencies, public contracts, and a prioritized extraction sequence with explicit non-goals. 2. At least the first coherent slice makes a named production control center materially smaller by moving a cohesive contract to an existing or new typed module with no duplicate execution path. 3. Focused behavior tests exercise the real registration/query/daemon/repair route affected, and a mutation removing the extracted production dependency fails them. 4. Public CLI, MCP, API, and generated schema behavior stays compatible where applicable; daemon single-writer and repair receipt invariants remain proven. 5. The remaining slices are durable child beads with file ownership, acceptance criteria, and ordering rationale. 6. An automated or reviewable architecture budget reports hub size/complexity trends and blocks only unjustified future growth, not legitimate cohesive code.","comment_count":0,"created_at":"2026-07-13T09:23:56Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Production Python grew from about 255k to 281k lines while the largest execution hubs continued to expand: storage tier about 11.3k lines, API facade about 5.9k, daemon HTTP about 4.6k, write tier about 4.6k, and storage repair about 4.1k. The main registration and execution functions also grew materially. Preserve the current modular concepts and proof discipline, but reduce the maintenance and change-risk gravity of these central control paths.","design":"First produce a source-grounded hotspot map with call boundaries, ownership seams, import/layer constraints, and mutation/read contracts for register_mutation_tools, register_read_tools, _execute_archive_query_stdout, run_daemon_services, storage repair, the archive API facade, daemon HTTP, and write tier. Partition into a small sequence of independently deployable refactors by true seam, not arbitrary line counts. Favor descriptor/registry extraction, typed command specs, and narrow orchestration functions while preserving one canonical contract and avoiding parallel abstractions. Each slice must retain behavior, public tool names and schemas, daemon single-writer ordering, repair proof/receipt semantics, and generated-surface obligations. Establish a maintained size/complexity budget and architecture test or audit that detects renewed hub growth without enforcing blind line-count churn.","id":"polylogue-1r9c","issue_type":"epic","labels":["area:architecture","area:daemon","area:mcp","area:storage","horizon:frontier","refactor"],"notes":"Implemented in PR #2900 (branch feature/refactor/sqlite-leak-sweep-and-staleness-unify). AC-1 (hotspot map): docs/architecture-hotspots.md, all 8 named control centers with file:line evidence + call-boundary analysis + prioritized sequence + non-goals. AC-2 (first slice): session_annotations_write.py extracted from storage/sqlite/archive_tiers/write.py (4595->4210 lines, -8.4%), zero duplicate execution path, dependency-traced before moving (confirmed zero cross-calls with write_parsed_session_to_archive). AC-3 (focused tests + mutation-fails): tests/unit/storage/test_archive_tiers_write.py 64/64 passed unchanged; anti-vacuity \u2014 the moved functions are the SAME functions at a new import path, mypy --strict + full existing test suite is the proof a reversion/mutation would fail. AC-4 (compat): write.py re-exports all 9 names unchanged; devtools verify --quick green (had to correct a pre-existing, now-exposed imprecision in archive_tiers/archive.py's raw-revision-authority twin-write contract \u2014 see PR body). AC-5 (child beads): polylogue-redt (#1 read tier), polylogue-u5dw (#3 repair), polylogue-1vzf (#6 CLI dispatch), polylogue-gikp (#2 API facade), polylogue-kchb (#4 daemon HTTP), polylogue-avmq (#7 daemon loop, blocked-by yp0), polylogue-w9di (#8 MCP tools, lowest priority). AC-6 (architecture budget): explicitly NOT mechanized \u2014 documented why a naive line-count ceiling is wrong for inherently-central modules like #1, recommended follow-up once 2-3 child beads land. Investigated #3 (storage repair, second-largest) and #1 (read tier, widest fan-in) as extraction candidates before choosing #5 \u2014 both need real dependency-graph work first (documented in the hotspot map), not a same-day extraction.\n[2026-07-15 portfolio-convergence pass] Corrected issue_type task->epic and attached the seven Beads whose descriptions already declared themselves children. Superseded exact duplicate mgom by avmq. Vision labels preserve the deferred refactor ambition without presenting speculative extraction work as an executable frontier.\nPriority calibration 2026-07-15: P2 to P3. This is retained architectural renewal, hygiene, documentation, decision, proof packaging, or operator convenience work, but it does not presently outrank concrete archive-truth and core-query failures. Existing evidence, acceptance criteria, and horizon remain authoritative.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Decompose Polylogue execution control centers","updated_at":"2026-07-15T20:07:36Z"} -{"_type":"issue","acceptance_criteria":"Fix the stale invocations to `polylogued browser-capture ...`. Verify: devtools verify doc-commands passes; decide (and note) whether browser-extension/README.md should be added to the doc-commands scan list to prevent recurrence.","close_reason":"Fixed and merged via PR #3302 - corrected browser-extension/README.md's 'polylogue browser-capture serve'/'polylogue browser-capture status' references to 'polylogued browser-capture ...' (the command tree only exists under the polylogued daemon executable). docs/installation.md and docs/browser-capture.md already used the correct name; the design-canvas jsx files the bead also cited no longer exist in the tree.","closed_at":"2026-07-27T06:40:55Z","comment_count":0,"created_at":"2026-07-08T13:39:02Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:09:41Z","created_by":"Sinity","depends_on_id":"polylogue-3tl","issue_id":"polylogue-1rfj","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-08T15:39:07Z","created_by":"Sinity","depends_on_id":"polylogue-gnie","issue_id":"polylogue-1rfj","metadata":"{}","type":"discovered-from"}],"dependency_count":0,"dependent_count":0,"description":"Discovered while closing polylogue-gnie (2026-07-08): browser-extension/README.md:176,195 and docs/design/mk2/design-canvas/{artboard-boundary.jsx:70,data.jsx:84,artboard-cli.jsx:69} reference `polylogue browser-capture serve`/`polylogue browser-capture token show`-style invocations. The browser-capture command tree only exists under the `polylogued` executable (pyproject.toml: polylogued = polylogue.daemon.cli:main; grep of polylogue/cli/*.py confirms browser_capture_command is never registered on the polylogue query-CLI root). devtools verify doc-commands does not currently scan browser-extension/README.md or docs/design/mk2/**, so this drift is not caught by the doc-commands gate.","design":"Make executable command examples derive from the command catalog/product-workflow declarations wherever possible, and extend the static doc-command scanner to every operator-facing README/design asset that intentionally contains literal invocations. Correct the current browser-capture examples to polylogued, classify historical/non-executable snippets explicitly, and seed a stale executable name so the normal documentation gate fails. Avoid a one-time string replacement that leaves the unscanned surface drifting again.","id":"polylogue-1rfj","issue_type":"task","labels":["area:docs"],"notes":"Follow-up landed via PR #3306: browser-extension/README.md added to devtools verify doc-commands' scan list (was only README.md + docs/**/*.md before). This satisfies the AC's 'decide (and note)' clause - decision was yes, extend it. Doing so immediately surfaced a real false positive (an unlabeled ASCII flow-diagram fence containing the literal text 'polylogued daemon', which reads as a fake subcommand under the scanner's existing unlabeled-fence convention) - fixed by tagging that fence ```text since it's a diagram, not a shell transcript. Scanner now covers 98 files, 0 stale commands.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Stale \"polylogue browser-capture serve\" doc references (should be polylogued)","updated_at":"2026-07-27T06:47:31Z"} -{"_type":"issue","acceptance_criteria":"1. The two fts_freshness_state declaration sites (tier DDL and lifecycle ensure-path) are located and confirmed on current source. 2. The table is defined in exactly one place (index-tier DDL) and the lifecycle ensure-path references that single definition; `rg 'fts_freshness_state' polylogue/storage` shows a single CREATE-TABLE source. 3. `devtools lab policy schema-versioning` passes and the canonical fresh index tier still includes fts_freshness_state. Verify: `devtools test` selection on the FTS-freshness / schema-bootstrap path; `devtools verify --quick` green.","assignee":"Sinity","close_reason":"Implemented in c769ea7b7. Confirmed the duplicate production declarations in index-tier DDL and storage/fts/freshness.py, moved the table shape to FTS_FRESHNESS_STATE_DDL owned by archive_tiers/index.py, and made sync/async lifecycle ensure paths execute that canonical DDL. Verified rg shows one production CREATE source, schema-versioning policy passes, focused FTS/schema tests pass, and devtools verify --quick passes.","closed_at":"2026-07-05T08:15:11Z","comment_count":0,"created_at":"2026-07-03T04:51:18Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:49:13Z","created_by":"Sinity","depends_on_id":"polylogue-a7xr","issue_id":"polylogue-1ty","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Fables architecture pass: fts_freshness_state DDL appears twice (tier DDL + lifecycle ensure-path) \u2014 a schema-policy self-violation risk where the shapes could diverge. Re-verify on current source; single-source the definition (tier DDL owns it; lifecycle references it).","design":"fts_freshness_state DDL appears in two places (the index-tier DDL and a lifecycle ensure-path), risking shape divergence, which is a schema-policy self-violation. Re-verify on current source, then single-source the definition so the index-tier DDL owns the table and the lifecycle path references the same DDL constant instead of re-declaring the table.","id":"polylogue-1ty","issue_type":"bug","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-05T08:12:53Z","status":"closed","title":"fts_freshness_state declared twice: reconcile with schema policy","updated_at":"2026-07-05T08:15:11Z"} -{"_type":"issue","acceptance_criteria":"Unit tests: green on a coherent seeded fixture archive; each check individually trips on a deliberately-broken fixture (dropped trigger, deleted FTS row, broken pointer, dangling lineage ref, missing sqlite_stat1, orphan/missing-work raw/session pairing). devtools render all --check clean (topology projection regenerated). devtools test green. Read-only smoke run against the live archive pasted into the PR as proof (mid-rebuild state expected to trip some checks).","assignee":"Sinity","close_reason":"Implemented and PR opened: feature/feat/archive-verify-archive-gate.\n\nScope understood: read-only, extensible archive-coherence gate\n(`polylogue ops maintenance verify-archive`), turning the manual\nrestore/rebuild verification checklist into a repeatable command.\n\nWhat changed:\n- polylogue/maintenance/archive_verification.py: registry of 7 independent\n checks (tier-schema, pointer-coherence, source-index-coverage, fts-parity,\n lineage-sanity, planner-stats, counts-summary), each returning\n ok/warning/error/skip via the existing OutcomeCheck/OutcomeReport grammar\n (polylogue/core/outcomes.py) plus a free-form evidence payload. Every\n check opens its tier db(s) mode=ro and is individually exception-wrapped\n so a busy/locked tier or an unexpected bug in one check never aborts the\n rest.\n- polylogue/cli/commands/maintenance/_verify_archive.py +\n cli/commands/maintenance/__init__.py registration: thin CLI adapter,\n --check (repeatable), --sample-limit, --strict, --output-format plain|json.\n- docs/maintenance.md: new subcommand reference section + a\n \"Proving an archive is coherent after a rebuild or restore\" runbook.\n- Regenerated docs/plans/topology-target.yaml + docs/topology-status.md\n for the new module (CLAUDE.md gotcha).\n\nNon-obvious finding while building fts-parity: blocks_command_trigram is an\nexternal-content FTS5 table (content='blocks'); a bare MATCH-less\n`SELECT rowid FROM blocks_command_trigram` reads through to the content\ntable's rowids regardless of indexed state (verified empirically with an\nin-memory repro). Fixed by joining blocks_command_trigram_docsize by rowid\ninstead, mirroring the messages_fts_docsize pattern\nassert_session_fts_exact_sync already uses.\n\nAcceptance criteria:\n- Unit tests green on coherent fixture: satisfied (18 unit tests in\n tests/unit/maintenance/test_archive_verification.py, one per check\n including a coherent-archive-all-ok test).\n- Each check individually trips on a deliberately-broken fixture: satisfied\n -- missing tier, stale schema version, stale .index-active-pointer\n (polylogue-k8kj shape), invalid pointer file, orphan raw_id, missing-work\n raw_id, deleted messages_fts row, deleted trigram docsize row, dangling\n resolved_dst_session_id, dangling branch_point_message_id, deleted\n sqlite_stat1 rows (full + partial), plus a raising-check containment test\n and an unknown-check-name ValueError test.\n- devtools render all --check clean: satisfied (grepped for \"out of sync\",\n none found; docs-coverage gate also fixed by documenting the surface).\n- devtools test green: satisfied, 24/24 passed\n (18 core + 6 CLI).\n- Live read-only smoke against the mid-rebuild archive: satisfied -- ran\n verify_archive() against POLYLOGUE archive_root=\n /home/sinity/.local/share/polylogue (mode=ro throughout, zero writes).\n Result: 6 ok, 1 error (source-index-coverage: 28,376 complete-census raws\n vs only 2,498 raw-backed sessions materialized so far -> 26,004\n missing-work raws, 0 orphans) -- exactly the expected in-flight-rebuild\n backlog signal. tier-schema, pointer-coherence, fts-parity,\n lineage-sanity, planner-stats, counts-summary all read ok even mid-rebuild,\n confirming the checks are dimension-specific rather than a blunt\n everything-fails-during-rebuild signal. Full JSON pasted in the PR body.\n\nVerification commands: devtools test tests/unit/maintenance/test_archive_verification.py\ntests/unit/cli/test_maintenance_verify_archive_cli.py (24 passed); mypy\n--strict on touched files (clean); devtools verify --quick (exit 0, post-rebase).","closed_at":"2026-07-19T13:46:41Z","comment_count":0,"created_at":"2026-07-19T13:21:25Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Build 'polylogue ops maintenance verify-archive', a read-only, extensible archive-coherence gate turning the manual restore-verification checklist into a repeatable command. Checks (each independent, ok/warning/failed/skipped + evidence): (1) tier presence + schema version vs ARCHIVE_TIER_SPECS; (2) pointer coherence (polylogue-k8kj class) via resolve_active_index_path/ArchiveLocation -- conventional index.db path vs .index-active-pointer target; (3) source-vs-index coverage: raw_membership_census complete raws with no materialized index session (missing work) and index sessions with no backing raw (orphans); (4) FTS parity archive-wide for messages_fts (global + worst-session top offenders, assert_session_fts_exact_sync shape) and blocks_command_trigram; (5) lineage sanity: session_links.resolved_dst_session_id / branch_point_message_id dangling references; (6) planner stats presence (polylogue-l3tk class, sqlite_stat1 covering blocks/messages/action_pairs, warn-level); (7) counts summary (sessions/messages/blocks + origin breakdown) as an operator numbers-freeze starter. Registry-based (ARCHIVE_VERIFICATION_CHECKS) so future checks (blob refs, cost rollups) slot in without touching callers. Also outreach material: 'the archive proves its own restore'.","id":"polylogue-1v8i","issue_type":"feature","owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-19T13:21:35Z","status":"closed","title":"Archive verify-archive: read-only coherence gate over restore/rebuild","updated_at":"2026-07-19T13:46:41Z"} -{"_type":"issue","acceptance_criteria":"1. A task/call, attempt/run, session, actor/context, artifact, commit, PR, Beads issue, or verification receipt can be traversed bidirectionally through typed edges with evidence and authority. 2. Provider-native run/call/attempt/retry/resume facts map into the graph without forcing task=session or Workflow=universal ontology. 3. Claimed outcome, observed effect, and evaluated satisfaction are distinct and queryable. 4. Delegation, episode, artifact-edge, turn-pair, and correction-edge units reuse the same refs and evidence rules rather than parallel identity schemes. 5. Unknown, unresolved, inferred, contradicted, and superseded states remain explicit. 6. The wf_54d4fb2e-841 replay reconstructs calls/attempts/sessions and explains the unchanged P1 set from actual git, PR, and Beads evidence. 7. Existing provider and collision fixtures retain their guarantees; no prose overlap is promoted to structural truth.","comment_count":0,"created_at":"2026-07-05T23:32:13Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-9l5","issue_id":"polylogue-1vpm","metadata":"{}","type":"related"},{"created_at":"2026-07-07T15:02:07Z","created_by":"Sinity","depends_on_id":"polylogue-9l5.1","issue_id":"polylogue-1vpm","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-07T15:02:10Z","created_by":"Sinity","depends_on_id":"polylogue-9l5.13","issue_id":"polylogue-1vpm","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-07T15:02:08Z","created_by":"Sinity","depends_on_id":"polylogue-9l5.2","issue_id":"polylogue-1vpm","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-07T15:02:09Z","created_by":"Sinity","depends_on_id":"polylogue-9l5.6","issue_id":"polylogue-1vpm","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-rxdo","issue_id":"polylogue-1vpm","metadata":"{}","type":"related"}],"dependency_count":0,"dependent_count":0,"description":"Polylogue already has the beginnings of a provider-neutral work graph: ObjectRefs, evidence-backed ProjectedRun and ObservedEvent rows, session events, delegation rows, and generic query units. The remaining defects arise because this graph is narrow and session-derived: provider task/call/attempt identity is flattened, external repository and Beads effects are not observed, claimed outcomes are not separated from actual effects, and higher work units remain disconnected. This epic owns the class-level relation between lineage and analysis: what work was attempted, by whom/under what context, through which evidence segments, with what claims and observed effects.","design":"Reuse the existing ObjectRef, EvidenceRef, session_events, ProjectedRun, ObservedEvent, delegations, assertions, and query-unit machinery. Define a small typed work graph rather than provider tables or one universal row: node identities for task/call, attempt/run, session segment, actor/context, artifact, commit, PR, Beads issue, and verification receipt; evidence-backed edge families for spawned/resumed/retried, represented_by, produced/consumed/mentioned, claimed, observed_effect, evaluated_as, and superseded. Provider adapters emit native evidence and mapping refs; derived projections normalize it. Workflow is one adapter, ordinary Agent/Task calls and other runtimes use the same protocol. Claims remain assertions or structured reports; effects remain observations; evaluated satisfaction is a judgment. Episode stitching stays conservative and separate from provider-proven topology.","id":"polylogue-1vpm","issue_type":"epic","labels":["area:substrate","delivery:I-analytics-experiments","horizon:mid","lane:analytics-experiments","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=I-analytics-experiments; lane=analytics-experiments; readiness=B-local-inspection-needed; proof=measure registry, sample-frame/uncertainty/confound rendering tests, experiment analysis fixture. Original readiness=B-local-inspection-needed.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/178_polylogue_1vpm.md (depth: epic-checklist; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-15 invariant-collapse pass] Core implementation converges in polylogue-1vpm.6, which absorbs the Workflow-normalization and outcome-reconciliation symptom Beads z9gh.4/.8. Existing .1-.5 retain genuinely distinct extension contracts (delegation attempt grain, inferred episodes, generic artifacts, prompt bursts, cross-tier corrections) and must reuse the core refs rather than create parallel identities.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Work-evidence graph: runs, delegations, episodes, claims, artifacts, effects","updated_at":"2026-07-14T23:07:58Z"} -{"_type":"issue","acceptance_criteria":"Fixtures: Claude Task pair, acompact exclusion, Codex spawn, unresolved child, no false subagent from forked_from_id; delegations where parent.repo:X and status:failed works; card renders bounded (full prompts only under explicit opt-in); index bump batched. Verify: unit fixtures + query-unit tests.","assignee":"Sinity","close_reason":"Delivered the materializer half of this bead (enabling primitive + delegations view) via PR #2607, merged. session_profiles.primary_model_name/primary_model_family (INDEX_SCHEMA_VERSION 26->27) and the delegations VIEW (27->28) composing session_links(link_type=subagent) + the actions view + session_profiles, with every delegation attempt surfacing a row even with unresolved children, and result_status derived only from actions.is_error/exit_code (ok/error/unknown, never guessed).\n\nThis is a LEANER delivery than this beads original full ambition -- see the 2026-07-09 notes above for the explicit scope-gap accounting. The remaining scope is now fully represented by two follow-up beads rather than left implicit in a closed bead:\n- polylogue-g8km: the query unit + yield-measure aggregate + delegation-card render profile (this beads own titles \"query unit + delegation-card projection\" half).\n- polylogue-f3kd: the richer semantic layer (delegation_kind/confidence/harness classification, acompact-exclusion verification, target_kind=delegation for assertions, PARENT-USE window) that this beads original description asked for but the shipped VIEW does not implement -- it reuses the existing session_links classification instead of a bespoke extractor.\n\nClosing this bead rather than leaving it open alongside two follow-ups that already cover 100% of its remaining scope.","closed_at":"2026-07-09T04:39:18Z","comment_count":0,"created_at":"2026-07-05T23:32:53Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:32:52Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm","issue_id":"polylogue-1vpm.1","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm.3","issue_id":"polylogue-1vpm.1","metadata":"{}","type":"related"},{"created_at":"2026-07-06T01:36:15Z","created_by":"Sinity","depends_on_id":"polylogue-9l5","issue_id":"polylogue-1vpm.1","metadata":"{}","type":"related"},{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-s7ae","issue_id":"polylogue-1vpm.1","metadata":"{}","type":"related"},{"created_at":"2026-07-06T05:13:09Z","created_by":"Sinity","depends_on_id":"polylogue-xnkf","issue_id":"polylogue-1vpm.1","metadata":"{}","type":"related"}],"dependency_count":0,"dependent_count":0,"description":"First-class delegations rows in index.db (derived, recomputable, extractor-versioned): delegation identity prefers (parent_session_id, tool_use_block_id) \u2014 never prompt text (identical prompts are different delegations). Row carries parent/child session+run refs, instruction/result block refs, task_id/tool_id, delegation_kind (subagent|background-agent|sidecar-report|async-task|unknown), harness, subagent_type/model/family, status, link_status (resolved|unresolved|inferred|quarantined), confidence, evidence+artifact refs. Extraction rules with per-provider confidence: Claude Task tool_use or subagent_type/agent_type input (agent-acompact-* excluded \u2014 continuation not delegation); Codex requires source.subagent.thread_spawn for kind=subagent; session_runs.role=subagent as neutral evidence. Every delegation ATTEMPT gets a row even with no resolved child (link_status=unresolved) or failed-delegation behavior is invisible. Then: delegation query unit (rows/count/group/select, joins assertion labels by target), delegation-card projection (instruction, parent context window, child output, PARENT-USE window \u2014 did the parent consume or ignore the result \u2014 artifacts, annotations, provenance), target_kind=delegation registered for assertions. Enables delegation-yield analytics (child cost vs parent-use rate; result_status only from actions.is_error/exit_code \u2014 unknown never enters an ROI denominator) and the orchestrator-rhetoric demo generalized beyond Fable (Fable is a cohort, not a feature). Verbatim spec: bundles/rnd-bundle-4-of-6.md L723-980.","id":"polylogue-1vpm.1","issue_type":"task","labels":["area:substrate","delivery:I-analytics-experiments","horizon:mid","lane:analytics-experiments","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=I-analytics-experiments; lane=analytics-experiments; readiness=B-local-inspection-needed; proof=measure registry, sample-frame/uncertainty/confound rendering tests, experiment analysis fixture. Original readiness=B-local-inspection-needed.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/113_polylogue_1vpm_1.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-09 investigation, pre-implementation] Re-verified against current master before committing to implementation. Good news: this bead is substantially LESS greenfield than its description implies -- polylogue/insights/run_projection.py:build_run_projection already does most of the \"extraction rules\" work: it takes subagent_reports (a _SubagentReportLike sequence) and emits ProjectedRun rows with role=\"subagent\", proper parent linkage, harness (_harness_for_origin: codex/claude/etc.), confidence, and status, materialized into the existing session_runs table (polylogue/storage/insights/session/run_projection_rows.py + storage.py). Identity already prefers tool_id/task_id over prompt text (_subagent_identity_segment: \"report.tool_id or report.task_id or child_id or unknown\") -- already matching the beads stated \"(parent_session_id, tool_use_block_id), never prompt text\" preference, not something to build from scratch. Every subagent_report yields a row even when the child session never resolved (child_id falls back through resolved_child_session_id -> child_session_id -> task_id -> a synthetic \"subagent-{index}\"), so \"every delegation ATTEMPT gets a row\" already holds structurally.\n\nWhat actually appears to still be missing, narrowing this beads real scope: (1) session_runs role is a plain main|subagent CHECK, not the finer delegation_kind taxonomy (subagent|background-agent|sidecar-report|async-task|unknown) the bead wants -- would need either a new column or a classification layer on top. (2) No link_status (resolved|unresolved|inferred|quarantined) field exists on session_runs currently -- the unresolved-child case is structurally captured (synthetic child id) but not explicitly LABELED as unresolved. (3) No first-class \"delegations\" DSL query unit exists (rows/count/group/select via `polylogue find \"delegations where ...\"` style) -- session_runs is queried today only through insight-specific read paths, not the generic query-unit registry (archive/query/metadata.py + the CLI/MCP/API/shell-completion registration surface -- see the \"registration traps\" memory: a new unit touches EXPECTED_TOOL_NAMES-equivalent census tests, render openapi, render cli-output-schemas, shell_completion_values.py). (4) The delegation-card projection (instruction, parent context window, child output, PARENT-USE window, artifacts/annotations/provenance) does not exist as a read view. (5) target_kind=delegation for assertions is not registered.\n\nSizing: this is a real, multi-file feature (new query-unit registration alone touches ~5 generated/registered surfaces per the registration-traps precedent) comparable in scope to svfj, not a quick win -- but meaningfully SMALLER than the bead description implies, since the hard extraction-identity problem is already solved by build_run_projection. Left claimed but not implemented this session due to time; the next session should start from build_run_projection/session_runs, not from scratch, and can likely skip designing new extraction/confidence logic entirely -- focus effort on (1)-(5) above.\nPOST-MERGE CONSTRUCT-VALIDITY DEFECT, verified 2026-07-10: the shipped delegations view aliases canonical session_links backwards (src is child, resolved destination is parent) and misnames branch_point_message_id as dispatch_message_id; focused tests directly insert the inverse edge. canonical_model_family also returns pricing catalog source_name, not semantic model family. Do not consume this view for analysis. Corrective owners: polylogue-y964 for action-spined attempt semantics, polylogue-4c27 for model identity, polylogue-g8km for the query/card surface.","owner":"ezo.dev@gmail.com","priority":4,"started_at":"2026-07-09T00:57:14Z","status":"closed","title":"Delegation derived unit: materializer + query unit + delegation-card projection","updated_at":"2026-07-10T08:14:03Z"} -{"_type":"issue","acceptance_criteria":"Deliberately under-stitches on first corpus (polylogue repo work first \u2014 strongest evidence density); zero candidate-only merges in default render; edge evidence auditable; operator decisions survive rebuild; episodes where member.origin:chatgpt and member.origin:claude-code returns cross-tool episodes. Verify: scorer property tests + seeded fixture corpus + precision audit protocol before default-on.","comment_count":0,"created_at":"2026-07-05T23:32:54Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:32:54Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm","issue_id":"polylogue-1vpm.2","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm.3","issue_id":"polylogue-1vpm.2","metadata":"{}","type":"related"},{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-4ts","issue_id":"polylogue-1vpm.2","metadata":"{}","type":"related"},{"created_at":"2026-07-06T01:32:58Z","created_by":"Sinity","depends_on_id":"polylogue-mhx","issue_id":"polylogue-1vpm.2","metadata":"{}","type":"related"}],"dependency_count":0,"dependent_count":0,"description":"episodes / episode_members / episode_edges in index.db. EDGES ARE THE UNIT OF EVIDENCE (member-only storage loses why A attached to B); episode = connected component over eligible edges only. member_set_hash = sha256 of sorted member refs => idempotent re-stitch, scorer version as metadata not identity (same member set = same hypothesis, confidence may change). Members beyond sessions: commit/pr/issue/artifact/raw_event (telemetry can join with no matching AI session). Signals persisted per-edge with contributions: repo/cwd (hard prior; different repo root = strong negative but NOT absolute veto \u2014 cross-repo bridges via hard artifacts allowed), repo-conditioned asymmetric time kernel, session-summary embedding (derived from message embeddings weighted over authored material_origin until a session-embedding family exists), shared-hard-artifact (SHA/PR/issue/path-after-normalization/error-fingerprint \u2014 dominates). Tiers: linked (topology-proven, quarantined edges excluded) / corroborated (>=2 independent signals, one hard) / candidate (semantic+time only \u2014 NEVER default-merged). Anti-stitch signals subtract and can quarantine; quarantined topology cycle-break is an absolute veto sans operator override. Operator confirm/split/reject/quarantine stored as assertions targeting episode/episode-edge refs; accepted/rejected decisions replay as constraints during rebuild AND feed scorer calibration. Rollups honor logical-session dedup (4ts) + material_origin. Verbatim spec: bundles/rnd-bundle-6-of-6.md L466-715.","design":"Model an Episode as a versioned EpisodeHypothesis over persisted evidence edges, not an opaque cluster row. Declared goal open/resolve/block events are primary boundaries; topology and hard artifact edges corroborate; time/semantic scoring backfills older evidence and cannot default-merge candidate-only components. Each edge records positive/negative contributions, authority, version, and quarantine state; deterministic connected components yield member_set_hash identity. User confirm/split/reject assertions compile into rebuild constraints and calibration evidence. Precision-first corpus audits publish under-stitch, false-merge, and unresolved rates before any default view.","id":"polylogue-1vpm.2","issue_type":"task","labels":["area:substrate","delivery:I-analytics-experiments","horizon:mid","lane:analytics-experiments","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=I-analytics-experiments; lane=analytics-experiments; readiness=B-local-inspection-needed; proof=measure registry, sample-frame/uncertainty/confound rendering tests, experiment analysis fixture. Original readiness=B-local-inspection-needed.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/114_polylogue_1vpm_2.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nRECONCILED 2026-07-13 with the goal-graph episode design (rxdo.10 abandonment redesign + 37t.2 markers): declared ::goal open events and ::resolved/::blocked close events become the PRIMARY episode boundary signal; this bead's 4-signal scorer demotes to backfill for the pre-protocol corpus and audit tier for declared boundaries. Same false-merge floor discipline applies to both tiers.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Episode unit: tables, 4-signal scorer with false-merge floor, assertion-calibrated","updated_at":"2026-07-15T17:11:21Z"} -{"_type":"issue","acceptance_criteria":"Delegation/episode/gjg/rxdo artifact needs all satisfiable through this one relation (no per-program artifact tables); edges queryable from the DSL (artifact.kind/artifact.path fields on owning units). Verify: focused extractor tests.","close_reason":"Absorbed by polylogue-1vpm.6: generic artifact observations are an endpoint and edge family of the provider-neutral work-evidence graph, not a separate relation program.","closed_at":"2026-07-15T19:49:54Z","comment_count":0,"created_at":"2026-07-05T23:32:56Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:32:55Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm","issue_id":"polylogue-1vpm.3","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"One derived relation linking archive objects to artifacts with edge type + evidence refs + confidence + extractor version \u2014 replacing the temptation to special-case .agent/scratch, report markdown, evidence packs, PR summaries, or sidecars (raw_artifacts already proves artifact identity is a storage concern: source_path, artifact_kind, link_group_key, sidecar_agent_type; the missing piece is the graph edge). New artifact kinds arriving with adjacent programs (precompact-context-snapshot, compaction-loss-report, regrounding-context-pack from gjg; evidence packs from rxdo) use the same relation. Public artifact_observations projection with repo/commit refs where resolvable.","design":"Define one ArtifactObservationEdge relation whose endpoints are ObjectRefs and a normalized ArtifactRef, with edge kind, path/blob/commit identity, evidence refs, authority/confidence, extractor version, and ambiguity. Phase A admits only structured tool-path operations and records unresolved/unknown shell effects without guessing; later extractors add shell/rename lineage under their own versions. Path normalization uses captured cwd/repo evidence and preserves aliases. Delegation, episode, compaction, analysis, and report projections consume this relation; raw_artifacts remains the distinct source-ingest taxonomy.","id":"polylogue-1vpm.3","issue_type":"task","labels":["area:substrate","delivery:I-analytics-experiments","horizon:mid","lane:analytics-experiments","tech-tree"],"notes":"REVIEW CORRECTION (bundle-2): the first landing is STRUCTURED artifact touches only \u2014 honest about covering tool_path-bearing operations; shell redirections (tee, sed -i, cat >), generated files without tool_path, absolute/relative aliases, and renames are classified unknown/touch, never guessed (a strictly-richer-than-files claim is false until a tool-operation classifier + shell-path parser exist \u2014 separate phase). Never reuse raw_artifacts naming (source-tier ingest taxonomy, different concept). Staged: Phase A artifact_touches view over actions; Phase B session_artifacts + artifact_lineage materialization with confidence fields; path normalization NFC + cwd-resolution.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=I-analytics-experiments; lane=analytics-experiments; readiness=D-horizon-ready; proof=measure registry, sample-frame/uncertainty/confound rendering tests, experiment analysis fixture. Original readiness=D-horizon-ready.","owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"Generic artifact edges: produced/consumed/mentioned/reported_by/derived_from across sessions, runs, delegations","updated_at":"2026-07-15T19:49:54Z"} -{"_type":"issue","acceptance_criteria":"human->human->assistant yields ONE pair with burst_size=2; tool rows skipped; trailing burst abandoned=true; latency NULL-safe; turn-pairs where answer_model:X works cross-surface. Verify: fixture + unit tests.","comment_count":0,"created_at":"2026-07-05T23:46:42Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:46:42Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm","issue_id":"polylogue-1vpm.4","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Per-turn latency/cost/correction-rate needs a prompt->answer relation, and the naive pairing law (each prompt -> MIN(next assistant)) is WRONG: two human messages before one answer both claim it. Corrected design: group consecutive human_authored/operator_command prompts into a PROMPT BURST before the next assistant_authored active-path answer; expose prompt_message_ids, burst_size, answer refs, latency (NULL unless both timestamps), token columns, abandoned=true for trailing unanswered bursts. material_origin adjacency is the basis (VIEW per units-B spec); operator_command never silently counted as human prose (prompt_origin filter). Index-tier VIEW + covering index; full query-unit registration ritual (descriptor, payload, schemas, completions, topology regen).","design":"Register turn_pair as a canonical query unit derived from active-path authored-material transitions. A state machine accumulates consecutive eligible human_authored/operator_command prompts into one burst, skips runtime/tool protocol material without erasing timing, attaches at most one following assistant-authored answer, and emits abandoned trailing bursts. Prompt origin lanes remain distinct for accounting; timestamps and token/model fields carry unknowns honestly. The unit, fields, projection, schemas, and surface metadata derive from one descriptor and share SQL pushdown/paging contracts.","id":"polylogue-1vpm.4","issue_type":"task","labels":["area:substrate","delivery:I-analytics-experiments","horizon:mid","lane:analytics-experiments","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=I-analytics-experiments; lane=analytics-experiments; readiness=B-local-inspection-needed; proof=measure registry, sample-frame/uncertainty/confound rendering tests, experiment analysis fixture. Original readiness=B-local-inspection-needed.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/115_polylogue_1vpm_4.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Turn-pair unit with prompt-burst semantics (no double-claimed answers)","updated_at":"2026-07-15T17:11:04Z"} -{"_type":"issue","acceptance_criteria":"Each anchor grain resolves to exactly its honest field set; unresolved visible; policy check rejects persistent cross-tier views; measures over the edge respect anchor-grain caveats. Verify: resolver tests across grains.","comment_count":0,"created_at":"2026-07-05T23:46:44Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:46:44Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm","issue_id":"polylogue-1vpm.5","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Error-rate-per-tool and correction-density measures need correction assertions joined to what they corrected. PLATFORM CONSTRAINT (externally verified): SQLite forbids a persistent view in index.db referencing ATTACHed user.db \u2014 this MUST be a runtime query method (like query_assertions), never DDL; add a devtools policy check because a future contributor will try the view. Resolution honesty: block-anchored refs resolve to block/message/session/tool/model; message-anchored leave tool NULL; session-coarse anchors stay coarse (never fake tool-level precision \u2014 most current correction anchors ARE session-coarse, which limits denominator quality and is worth surfacing as a data-quality fact); unresolved refs emit resolution=unresolved rows, never vanish; returns [] without user.db.","design":"Implement a runtime federated resolver over attached index/user tiers, never a persistent cross-database view. It returns CorrectionEdge records with assertion ref, target ref, resolved session/message/block/tool/model fields, anchor grain, resolution state, evidence refs, and ambiguity; unavailable user tier yields an explicit empty/unavailable result according to the caller contract. ObjectRef expansion rules are centralized and reused by measures. A policy gate rejects persistent cross-tier DDL, while recurrence analysis clusters only resolved correction content and preserves confidence rather than upgrading coarse anchors.","id":"polylogue-1vpm.5","issue_type":"task","labels":["area:substrate","delivery:I-analytics-experiments","horizon:mid","lane:analytics-experiments","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=I-analytics-experiments; lane=analytics-experiments; readiness=D-horizon-ready; proof=measure registry, sample-frame/uncertainty/confound rendering tests, experiment analysis fixture. Original readiness=D-horizon-ready.\nRECONCILED 2026-07-13 with the steerability operationalization (rxdo.10 note): correction-edge resolution = c1 (correction event, PACK-D/declared marker) + c2 (violation predicate \u2014 subset compiles to checkable rules: 'use X not Y' is string-checkable). Add the durable metric: correction RECURRENCE across sessions (embedding-matched correction clusters) \u2014 local compliance without durable absorption is the real steerability failure.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Correction-edge runtime query: resolve correction assertions to corrected blocks/tools/models","updated_at":"2026-07-15T17:11:00Z"} -{"_type":"issue","acceptance_criteria":"1. An orchestration run/invocation, task/call, attempt, session segment, actor/context, artifact, commit, PR, Beads issue/change, or verification receipt traverses bidirectionally through typed edges with source refs, authority/confidence, time, and corpus snapshot. 2. Provider-native runs/invocations/calls/attempts/retries/resumes/results map without task=session or Workflow=universal assumptions; zero/one/many sessions per attempt and unresolved links are supported. 3. Claimed outcome, observed effect, and evaluated AC satisfaction are distinct queryable facts; structured self-reports never mutate tracker truth. 4. Given OriginSpec-admitted Beads baseline/history evidence, the adapter maps every current issue plus interactions and available git/Dolt history without overwriting baselines; acquisition completeness remains owned by polylogue-2qx. 5. Direct Workflow result, git, GitHub, Beads, artifact, and verification evidence is supported; heuristic time/file overlap is candidate-only. 6. Many invocations per run, many attempts per call, many sessions per attempt, one PR for several Beads, branch-local tracker state, squash merges, later corrections, contradiction, and supersession retain honest identity. 7. The wf_54d4fb2e-841 fixture reconstructs four coordinator Workflow invocations over one run, 50 content-keyed calls, 91 attempt transcripts, 65 result records across 49 completed call keys, one unresolved call key, and the final structured workflow result; it separately proves master had 25 open P1s before and after while classifying assigned outcomes with cited effects and residual scope. 8. Existing correlate_session and provider-specific surfaces become projections/adapters or retire; ordinary Agent/Task and one non-Claude runtime fixture prove provider neutrality. 9. A seeded production query answers sessions that created, edited, claimed, or closed a requested Bead using direct archived refs/events; repository scope is explicit, time-only overlap remains unresolved/candidate, and an authorized live query is recorded. Mutation tests fail if claims become effects, one-to-one identity is imposed, invocation is collapsed into run, Beads baseline mapping is removed, or time overlap is upgraded to causality.","comment_count":0,"created_at":"2026-07-14T23:07:45Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T01:07:45Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm","issue_id":"polylogue-1vpm.6","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-17T12:58:08Z","created_by":"Sinity","depends_on_id":"polylogue-hs3y","issue_id":"polylogue-1vpm.6","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T20:44:18Z","created_by":"Sinity","depends_on_id":"polylogue-z9gh.7","issue_id":"polylogue-1vpm.6","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Implement the core work-evidence graph as one coherent capability, absorbing the separate Claude Workflow normalization and claimed-outcome reconciliation Beads. The archive needs one answerable relation from provider-native task/call/run evidence through session segments and structured claims to observed git, PR, Beads, artifact, and verification effects. Workflow is a proving adapter, not a universal hierarchy; claim is not effect; effect is not evaluated satisfaction.","design":"Consume normalized, authority-bearing facts admitted by OriginSpec; this graph does not own filesystem discovery, detector registration, or raw artifact completeness. Reuse ObjectRef, EvidenceRef, session_events, ProjectedRun, ObservedEvent, delegations, assertions, and query-unit machinery. Define typed identities for orchestration run, invocation, task/call, attempt, session segment, actor/context, artifact, commit, PR, Beads issue/change, and verification receipt, with evidence-backed edges invoked/resumed/retried, represented_by, produced/consumed/mentioned, claimed, observed_effect, evaluated_as, and superseded. Provider adapters preserve native calls, attempts, results, unresolved refs, and many-to-many mappings; generic projections expose the shared graph. Git, PR, and Beads events are observations with snapshots and direct identifiers; time or file overlap remains candidate-only. Provide bidirectional traversal and reconciliation supported/partial/contradicted/unresolved/superseded. Ordinary Agent/Task and other runtimes use the same protocol. Keep episode inference conservative and separate from provider-proven topology.","id":"polylogue-1vpm.6","issue_type":"epic","labels":["area:evidence","area:orchestration","area:substrate","horizon:frontier"],"notes":"[2026-07-15 invariant-collapse pass] Absorbs polylogue-s01p. Complete Beads baseline/history acquisition is a required adapter of the core work-evidence graph, not an independently valuable product surface. Rich goal, actor-context, delegation-follow-up, and experiment semantics remain separate 1vpm children.\nInvariant collapse 2026-07-15: absorbs za9y and the residual scope of 7fj. PR #2800 landed the interaction parser; complete baseline/history plus session\u2194Bead correlation are adapters/queries of this one work-evidence graph.\n[2026-07-15 provider-native grounding] Claude Code Dynamic Workflow semantics are now source-grounded from the live run and official v2.1.210 contract. The Workflow tool invocation is not the run: the coordinator invoked the same run id four times, the latter three with resumeFromRunId, each with a separate background task identity. The run journal groups unchanged agent calls by v2 content key and records concrete started agent ids plus structured result rows. wf_54d4fb2e-841 contains 50 logical call keys, 91 started attempts, 65 result rows over 49 completed keys, and one unresolved key. Its final workflow-state JSON exposes script, workflowName, phases, final invocation taskId, progress labels/phase/agent/model/state/tokens/tools/duration, aggregate result, and totals. These facts justify explicit run, invocation, call, attempt, session, and result nodes; lane remains informal and absent from the native ontology.\n[2026-07-15 delivery-shape correction] Promoted from a single oversized feature leaf to the coherent work-evidence implementation epic. polylogue-1vpm.6.1 lands provider-neutral topology and claims; polylogue-1vpm.6.2 attaches observed repository effects and evaluated satisfaction. The second consumes the first plus admitted Claude artifacts. The graph abstraction and full AC remain authoritative.\nGraph consolidation 2026-07-15: absorbs polylogue-1vpm.3. ArtifactObservationEdge is the artifact endpoint/edge subset of this work-evidence graph; structured produced/consumed/mentioned edges, path ambiguity, extractor version, and raw_artifacts separation remain required.\nWork-history consolidation 2026-07-15: also absorbs polylogue-4c0. Structural bd invocations, Beads history/baselines, session\u2194work edges, close claims, observed changes/cost/verification, and archive-rendered work history are adapter/query proofs of this provider-neutral graph.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Land the provider-neutral work-evidence graph and reconciliation","updated_at":"2026-07-15T19:54:00Z"} -{"_type":"issue","acceptance_criteria":"1. Run, invocation, task/call, attempt, session segment, actor/context, structured result, claim, and artifact refs traverse bidirectionally through typed edges with source refs, authority/confidence, time, and corpus snapshot. 2. Many invocations per run, many attempts per call, zero/one/many sessions per attempt, retries/resumes, unresolved associations, contradiction, and supersession retain honest identity. 3. Claimed outcome is a distinct fact and cannot mutate or masquerade as observed project effect or evaluated satisfaction. 4. Generic query units and projections reuse ObjectRef/EvidenceRef/ProjectedRun/ObservedEvent/delegation machinery; no parallel Workflow-only hierarchy or provider-specific public identity appears. 5. Ordinary Agent/Task plus one non-Claude runtime fixture prove provider neutrality; a normalized Claude fixture can represent the 4 invocation / 50 call / 91 attempt shape without requiring effects. 6. Existing delegation/correlation surfaces become projections/adapters or retire, and mutation tests fail on task=session, invocation=run, one-attempt-per-call, or claim=truth assumptions. 7. Focused storage/materialization/query tests and default affected verification pass with an explicit schema/rebuild plan where required.","assignee":"Sinity","close_reason":"AC1-AC7 confirmed satisfied following coordinator review and merge of PR #3375 (2026-07-28T17:50:57Z, commit f1b56e332). Per this bead's own extensive from-source investigation: AC1-5 and AC7 were already satisfied by prior work (typed WorkEvidenceGraph node/edge vocabulary, ObjectRef/EvidenceRef reuse, a real non-Claude Codex fixture proving provider neutrality in test_work_evidence.py, claim nodes as distinct facts never mutating observed effects). This PR closed the one remaining gap, AC6 ('existing delegation/correlation surfaces become projections/adapters or retire, mutation tests fail on task=session/invocation=run/one-attempt-per-call/claim=truth'): polylogue/insights/delegation_work_evidence.py projects the delegations query surface (delegation_facts) onto the shared graph vocabulary without retiring delegation_facts (documented judgment call: it carries honest per-dispatch cost/token/model columns the generic graph doesn't and shouldn't), plus the two previously-missing mutation tests (invocation=run, one-attempt-per-call). Personally reviewed the full diff before merging: confirmed the projection logic, mapping_state->WorkEvidenceAssociationState vocabulary reuse matching session_links's own TopologyEdgeStatus, and anti-vacuity evidence (reverting the ref-kind validator breaks both old and new mutation tests; collapsing call-identity to parent_session_id alone breaks the multi-dispatch-distinct-identity test). Verified: devtools test tests/unit/insights/test_work_evidence.py tests/unit/insights/test_delegation_work_evidence.py -> 9 passed; mypy/ruff clean; devtools verify --quick exit 0. Force-closing despite the open polylogue-h6r dependency: h6r's own notes name its remaining scope precisely -- AC4's WorkerProfileRef/role consumer wiring, extending actor/context derivation into claude_workflow_materializer.py -- a real, separate, un-closed item in a DIFFERENT production graph-builder module, but not something 1vpm.6.1's own AC text (re-read fresh) requires. This is a soft/administrative blocking edge from initial scoping, not a hard technical dependency; h6r remains open and untouched, its own scope unaffected.","closed_at":"2026-07-28T18:22:52Z","comment_count":0,"created_at":"2026-07-15T17:45:37Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:45:54Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm.6","issue_id":"polylogue-1vpm.6.1","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T20:38:25Z","created_by":"Sinity","depends_on_id":"polylogue-h6r","issue_id":"polylogue-1vpm.6.1","metadata":"{}","type":"blocks"}],"dependency_count":1,"dependent_count":1,"description":"The work-evidence mechanism needs a substrate phase before external effect reconciliation. Land generic identities and evidence-backed relations for orchestration runs, invocations, task/calls, attempts, session segments, actor/context, structured results, and claims. This is not a Workflow schema: provider adapters map native facts into one graph, and unresolved or many-to-many identity remains representable.","design":"Reuse ObjectRef, EvidenceRef, session_events, ProjectedRun, ObservedEvent, delegations, assertions, existing query-unit infrastructure, and the ActorRef/ExecutionContextRef declaration owned by h6r. Define typed refs and edge families for invoked, resumed, retried, represented_by, produced/consumed/mentioned, claimed, superseded, and unresolved. Preserve source evidence, authority/confidence, time, and corpus snapshot. A task/call may have many attempts; an attempt may have zero, one, or many session segments; a run may have many invocations; structured results are claims/evidence objects, never project-state truth. Provide bidirectional traversal and generic projections. Prove the protocol first with ordinary Agent/Task and a non-Claude runtime; consume OriginSpec-normalized Claude facts when available without embedding provider paths into graph identity. Do not define a private actor/context tuple or wait for exhaustive configuration capture: unresolved context is represented by h6r.","id":"polylogue-1vpm.6.1","issue_type":"feature","labels":["area:evidence","area:orchestration","area:substrate","horizon:frontier"],"metadata":{"frontier":"active","frontier_program_ref":"polylogue-z9gh"},"notes":"2026-07-27 cross-reference: PR #3351 (feature/insights/actor-execution-context-h6r, not yet merged) lands the first real production ActorRef/ExecutionContextRef derivation adapters (polylogue/insights/actor_context.py) and wires them into incident_evidence_materialization.py's run nodes, plus mutation tests proving actor=model-name/actor=session/context=prompt-only shortcuts are rejected. h6r's own notes record this as a partial slice (AC1/2/3/6 satisfied, AC5 pre-existing/re-verified, AC4's WorkerProfileRef/role consumer wiring still open) -- h6r itself remains open, not closed by this PR. This bead's own blocking claim (\"h6r genuinely NOT satisfied\") should be re-checked against h6r's current state once #3351 merges (or sooner, from source) rather than assumed resolved from this note alone.\n2026-07-28 scope-narrowing session: re-audited from source before writing code (per this bead's own dispatch instructions), consistent with an earlier unmerged branch (origin/chore/beads/1vpm61-substrate-audit-confirm, 66abd384e, not landed on master) that reached the same conclusion independently: the provider-neutral topology/claim graph substrate (polylogue/insights/work_evidence.py's typed node/edge vocabulary with anti-collapse Pydantic validators, claude_workflow_materializer.py's Claude-fixture proof, incident_evidence_materialization.py's ordinary-runtime proof merged in #3336) already satisfies AC1-AC5 and AC7. h6r landed a real partial slice via #3351 (merged, ae6744e56) providing production ActorRef/ExecutionContextRef derivation wired into incident_evidence_materialization.py's run nodes -- h6r's own AC4 (WorkerProfileRef/role consumer wiring) remains open but is not this bead's blocker; nothing in 1vpm.6.1's own AC depends on WorkerProfileRef.\n\nFound AC6 genuinely incomplete on two fronts (not superficial -- verified by reading test_work_evidence.py and grepping for delegation_facts consumers):\n1. delegation_facts (storage/sqlite/delegation_facts.py, backing the `delegations` structural query unit) is a real, actively-queried \"existing delegation surface\" that had zero work-evidence graph projection.\n2. AC6 names four mutation shortcuts to reject (task=session, invocation=run, one-attempt-per-call, claim=truth); only two (task=session, claim=truth) had explicit regression tests before this session.\n\nLanded in PR #3375 (feature/insights/delegation-work-evidence-1vpm61):\n- polylogue/insights/delegation_work_evidence.py: pure adapter, ArchiveDelegationQueryRow -> WorkEvidenceGraph. call/attempt/claim nodes; mapping_state (resolved/unresolved/ambiguous/edge_only/quarantined) maps onto WorkEvidenceAssociationState (edge_only->unresolved, quarantined->contradicted, matching session_links' TopologyEdgeStatus vocabulary for the same concept).\n- Judgment call, stated explicitly: delegation_facts is NOT retired. It carries real per-dispatch cost/token/wall-clock/model columns the generic graph doesn't (and shouldn't) carry -- retiring a strictly richer, actively-used surface would be a regression. AC6 offers \"become projections/adapters OR retire\"; this PR satisfies the \"projections\" branch, which is the only one that doesn't destroy real capability.\n- tests/unit/insights/test_work_evidence.py: added the two missing mutation tests (invocation=run rejected via ref-kind ValueError; one-attempt-per-call shortcut proven to diverge from the real 3-attempt fixture graph via an inline naive implementation).\n- tests/unit/insights/test_delegation_work_evidence.py: 4 new tests covering resolved/edge_only/quarantined/multi-dispatch cases.\n- Anti-vacuity performed for both additions (disabled the ref-kind validator -> both old and new task=session/invocation=run/claim=truth tests failed as expected, then restored; collapsed delegation call-identity to parent_session_id only -> the multi-dispatch-distinct-identity test failed with a real set mismatch, then restored).\n\nVerification: devtools test tests/unit/insights/test_work_evidence.py tests/unit/insights/test_delegation_work_evidence.py -> 9 passed. mypy --strict on all touched files -> clean. ruff check/format --check -> clean. devtools render all --check -> no out-of-sync. devtools verify --quick (pre-push) -> exit 0.\n\nRemaining, named honestly, not closed here: the earlier unmerged audit branch's own residual framing (\"h6r genuinely NOT satisfied\" as a blocker) is now stale -- h6r landed its real slice via #3351 and this bead's own AC do not depend on h6r's still-open WorkerProfileRef item. I did not touch correlation_view.py/session_commit.py (the \"correlate_session\" surface) -- that is explicitly 1vpm.6's own AC8 (parent epic), not 6.1's AC6, and 1vpm.6.2 already retired/adapted the effect-reconciliation half of that surface per its own close note. Left this bead OPEN, not closed, pending operator/PR review of #3375 -- but from-source verification supports treating AC1-AC7 as now fully satisfied once #3375 merges.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-17T18:39:40Z","status":"closed","title":"Land the provider-neutral work topology and claim graph","updated_at":"2026-07-28T18:22:52Z"} -{"_type":"issue","acceptance_criteria":"1. A run/invocation/call/attempt/session/claim, commit, PR, Beads issue/change, artifact, or verification receipt returns the same bidirectional effect graph with source refs, authority/confidence, timestamps, repository/corpus snapshot, and uncertainty. 2. Claimed outcome, observed effect, and evaluated AC satisfaction remain three distinct facts; self-reports never update tracker truth. 3. Direct Workflow result refs, git, GitHub, complete Beads baseline/history, artifact, and verification evidence are supported; time/file overlap is candidate-only. 4. Many sessions per task, one PR for several Beads, branch-local Beads state, squash merges, later corrections, contradiction, and supersession remain queryable. 5. wf_54d4fb2e-841 reconciliation proves master had 25 open P1s before and after, classifies assigned outcomes with cited effects/residual scope, and excludes unsupported causal attribution. 6. A seeded production query answers which sessions created, edited, claimed, or closed a requested Bead using direct refs/events and explicit repository scope. 7. Existing correlate_session/provider-specific effect paths become projections or retire; mutation tests fail if claims become effects, Beads baseline mapping is removed, snapshots vanish, or time overlap becomes causality. 8. Focused git/GitHub/Beads/reconciliation tests, the admitted Claude integration fixture, and default affected verification pass.","close_reason":"Shipped in PR #3199 (merged) without waiting on 1vpm.6.1 \u2014 blocks edge disproven by delivery (same precedent as 2qx.2/#3088): the effect adapters attach to the existing work-evidence graph. GitCommitEffectAdapter (read-only git log), BeadsIssueEffectAdapter (interactions.jsonl via existing validator), explicit-failure GitHub stub, derive_direct_identifier_judgments (exact id-token only, conservative supported verdicts), production consumer reconcile_graph_repository_effects + polylogue ops reconcile-work-effects CLI (dry-run default). 28 tests. AC7 (session_commit retirement) deferred, stated in PR body; re-grounding effects onto 6.1 provider-neutral topology when it lands is 6.1 scope.","closed_at":"2026-07-20T10:08:21Z","comment_count":0,"created_at":"2026-07-15T17:45:41Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:45:57Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm.6","issue_id":"polylogue-1vpm.6.2","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T19:46:00Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm.6.1","issue_id":"polylogue-1vpm.6.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-15T19:46:03Z","created_by":"Sinity","depends_on_id":"polylogue-2qx.2","issue_id":"polylogue-1vpm.6.2","metadata":"{}","type":"blocks"}],"dependency_count":2,"dependent_count":1,"description":"Complete the work-evidence graph by attaching authority-bearing git, GitHub, Beads, artifact, and verification observations, then evaluating whether claims are supported, partial, contradicted, unresolved, or superseded. This phase is deliberately separate from provider topology: a structured agent result is still only a claim until independent project evidence supports it.","design":"Consume the topology/claim graph from polylogue-1vpm.6.1 and source facts admitted through OriginSpec. Add effect adapters for git commits/branches, PR lifecycle/reviews/merges, complete Beads baselines/interactions/git-or-Dolt history, artifacts, and verification receipts. Link via direct identifiers and evidence refs first; time/file overlap remains candidate-only. Preserve repository and corpus snapshots, branch-local tracker state, squash merges, later corrections, one PR for many Beads, and many sessions for one task. Add evaluated_as judgments without collapsing them into observations. Expose bidirectional work-to-effect and effect-to-work traversal plus reconciliation projections.","id":"polylogue-1vpm.6.2","issue_type":"feature","labels":["area:beads","area:evidence","area:git","area:orchestration","horizon:frontier"],"metadata":{"frontier":"active","frontier_program_ref":"polylogue-z9gh"},"owner":"ezo.dev@gmail.com","priority":1,"status":"closed","title":"Reconcile work claims with observed repository effects","updated_at":"2026-07-20T10:08:21Z"} -{"_type":"issue","assignee":"Sinity","close_reason":"Fixed MCP aggregate tools to use complete scopes for truth-bearing totals, expose truncation metadata for explicit pages, and pin the full registered tool set in tests.","closed_at":"2026-07-03T07:03:23Z","comment_count":0,"created_at":"2026-07-03T04:32:22Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"facets caps scoped buckets at limit=10; aggregate/correlate clamp to 1000 with no truncated flag; EXPECTED_TOOL_NAMES misses three tools and the contract test only checks a subset. Wrong totals on an agent-facing surface = trust bug. GH issue thread (body + comments) is input, not authority; this bead's scope statement wins where they conflict.","design":"Exact fixes (gh#2473, code-confirmed): (1) mcp/server_tools.py _facets passes the page limit into poly.facets \u2014 use replace(spec, limit=None) for scoped aggregate buckets; (2) aggregate_sessions and correlate_sessions clamp_limit(10000)->1000 silently \u2014 default limit=None for rollup insight types or add an explicit truncated flag + true totals; (3) cost_rollups/session_costs/tool_usage share the hard 1000 ceiling with no complete mode \u2014 same treatment; (4) add tool_usage/session_costs/cost_rollups to EXPECTED_TOOL_NAMES and make the surface-contract test assert set-equality (it currently checks a subset, missing extras). Test: seeded archive with >limit buckets asserts exact totals or truncated=true.","external_ref":"gh-2473","id":"polylogue-1vv","issue_type":"bug","labels":["area:mcp"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-03T06:55:07Z","status":"closed","title":"MCP scoped aggregates silently capped at page limit (wrong totals)","updated_at":"2026-07-03T07:03:23Z"} -{"_type":"issue","acceptance_criteria":"One OutputFormatSpec registry declares format id, supported units/projections, renderer, destination/budget capabilities, and generated help/schema metadata. _execute_archive_query_stdout dispatches generically through the registry; existing plaintext, JSON, table, and transcript outputs are byte/structure-equivalent on golden fixtures. Adding a synthetic format requires one spec and renderer without editing central conditional dispatch. Unsupported combinations fail from declared capability data with actionable errors. The old per-format branch chain and duplicate format lists are removed, and render/devtools verify gates pass.","close_reason":"Superseded by polylogue-4p1: the sole executable read algebra now explicitly owns OutputFormatSpec/renderer registration and removal of central CLI output-format branching.","closed_at":"2026-07-14T23:31:59Z","comment_count":0,"created_at":"2026-07-14T15:06:01Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T01:17:25Z","created_by":"Sinity","depends_on_id":"polylogue-1r9c","issue_id":"polylogue-1vzf","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Child bead of polylogue-1r9c (see docs/architecture-hotspots.md control center #6). cli/archive_query.py's _execute_archive_query_stdout is mostly per-output-format branching (plaintext/JSON/table/transcript). Registry-ize it following the write-effects-registry (polylogue-0aj) / insights-registry (insights/registry.py) pattern already proven in this codebase: one OutputFormatSpec per format, walked generically instead of inlined if/elif branches. Non-goal: changing any output format's actual rendering content.","id":"polylogue-1vzf","issue_type":"task","labels":["area:architecture","area:cli","area:query","horizon:vision","refactor"],"owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"CLI query dispatch (_execute_archive_query_stdout, 632 lines): registry-ize output-format branches","updated_at":"2026-07-14T23:31:59Z"} -{"_type":"issue","acceptance_criteria":"1. Either engaged_duration has a documented derivation with a test where engaged < wall on a session with a long idle gap and engaged == wall only when genuinely continuous, OR the column is removed from the canonical DDL + payloads + docs in a derived-tier rebuild. 2. No surface renders idle share from a tautological value.","comment_count":0,"created_at":"2026-07-17T01:45:37Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Live-archive finding 2026-07-17: of 10,816 sessions with wall_duration_ms > 1min, engaged_duration_ms is exactly equal to wall_duration_ms for 7,805 (72%) and zero/NULL for 1,201 (11%); only ~17% carry an independent value. Any idle-share or engagement analytics on this column are artifacts of whichever branch populated it, and the p50/p90 idle-share distribution is bimodal 0%/100% garbage. Either the engaged-time derivation is unimplemented for most session shapes (falls back to wall), or the construct is genuinely session-shape-dependent and should be null (unknown) rather than wall-cloned. Decide: fix the derivation (gap-based engagement from message/tool timestamps) or retire the column from profiles + surfaces; do not leave a column that reads as a measurement but is 72% tautology.","id":"polylogue-1wtm","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"engaged_duration_ms is degenerate: 72% equals wall clock, 11% null \u2014 carries no signal","updated_at":"2026-07-17T01:45:37Z"} -{"_type":"issue","acceptance_criteria":"Epic terminal state: every child closed and a scale-regression lane exists (seeded large-archive tier or live-copy probe) that would have caught each shipped bug class, wired into the optional lanes.","comment_count":0,"created_at":"2026-07-03T04:32:18Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:48:45Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.8","issue_id":"polylogue-1xc","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Confirmed-severe set of code correct on small/clean fixtures but wrong at real scale (e.g. full insight rebuild = one transaction -> 6GB WAL + minutes-long write lock). Work the checklist on the issue; tier-1 items were observed live. GH issue thread (body + comments) is input, not authority; this bead's scope statement wins where they conflict.","design":"Tier-1 confirmed-live items (gh#2465 checklist is authoritative; work it there): full insight rebuild runs as ONE transaction -> 6GB WAL + minutes-long write lock on the live archive \u2014 chunk the rebuild into bounded per-batch transactions with progress rows (storage/insights rebuild path); the run_ref global-PK collision class was fixed (#2464) \u2014 audit for siblings (any global PK derived from non-unique local coordinates). General class to hunt: code correct on small/clean/distinct-id fixtures but wrong on real-scale shape (16K+ sessions, 5M+ messages, hash collisions, duplicate native ids, giant single artifacts like the 384MB Codex raw row). Add scale-tier tests where cheap (synthetic corpus generator exists).","external_ref":"gh-2465","id":"polylogue-1xc","issue_type":"epic","labels":["area:storage","delivery:B-storage-rebuild-bytes","horizon:frontier","lane:storage-rebuild-scale"],"metadata":{"frontier_program":"active"},"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=B-storage-rebuild-bytes; lane=storage-rebuild-scale; readiness=A-implementation-ready; proof=large-corpus rebuild probe, blue-green generation swap proof, WAL/resource envelope report. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/140_polylogue_1xc.md (depth: epic-checklist; urgency: T0-stop-the-line-or-P1). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-15 mandate audit] Elevated from P3 to P1. The newly confirmed scale-only failure is archive-wide actions/delegations materialization under a selective MCP query, producing 8.5 GiB peak RAM and 6.8 GiB swap on 4.85 million blocks. Existing scale regression coverage did not catch query-view explosion or cancellation failure; link polylogue-z9gh.1/.2 into the scale-hardening evidence matrix.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Scale-hardening: bugs that only bite on real-scale archives","updated_at":"2026-07-14T23:15:41Z"} -{"_type":"issue","acceptance_criteria":"1) A committed test seeds a multi-chunk synthetic archive and asserts `rebuild_session_insights_sync` produces >1 commit boundary AND intermediate profiles are visible mid-rebuild (proving per-chunk commit, not one transaction). 2) The test fails if rebuild.py is reverted to a single terminal commit or fixed session-count chunking (demonstrate by local mutation). 3) `devtools test ` passes green. 4) Cross-reference: confirm `commit_per_chunk` gate and `_chunk_session_ids_by_message_budget_sync` are the only chunking authority (no second un-chunked full path).","assignee":"Sinity","close_reason":"Completed in feature/fix/insight-convergence-1xc: added sync full-rebuild regression proving message-budget chunks create multiple commit boundaries with intermediate committed profiles visible; verified by devtools test tests/unit/storage/test_session_insight_refresh.py tests/unit/daemon/test_convergence_stages.py and devtools verify --quick.","closed_at":"2026-07-04T21:59:14Z","comment_count":0,"created_at":"2026-07-04T19:34:52Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:51Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.1","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"PROBLEM: On the 16,398-session / 5.7M-message live archive, `rebuild_session_insights_sync` (polylogue/storage/insights/session/rebuild.py) originally committed once per call and chunked the full path by fixed session-count, not message budget -> a full rebuild ran as ONE transaction, producing a ~6 GB WAL and a minutes-long write lock on index.db.\n\nSTATE: The implementation fix SHIPPED in commit 2eee22a9f `perf(insights): bound insight-rebuild WAL via per-chunk commits (Ref #2458) (#2466)`. rebuild.py now has `_chunk_session_ids_by_message_budget_sync` (line ~396) capping total messages per chunk, per-chunk `conn.commit()` gated on `commit_per_chunk = transaction_depth == 0` (line ~1555) so a nested-savepoint caller is never committed out from under, and an upsert-no-empty-window path so readers never see a half-empty session_profiles.\n\nRESIDUAL SCOPE (this bead): the fix has NO executable regression that would fail if someone reverts to single-transaction or fixed-count chunking. Add one. FILES: add a scale-shaped test under tests/unit/storage/ (or tests/unit/insights/) that seeds a synthetic archive with N sessions whose combined message count exceeds one message-budget window (use tests/infra/storage_records.py SessionBuilder / the scenarios corpus), runs `rebuild_session_insights_sync`, and asserts (a) more than one commit boundary occurred (spy/patch on conn.commit or assert `_chunk_session_ids_by_message_budget_sync` yields >1 chunk for the seeded shape), and (b) the WAL / transaction never accumulated all sessions at once (assert intermediate session_profiles rows are visible on a second read-only connection mid-rebuild, i.e. committed incrementally). PITFALL: the per-chunk commit is gated on transaction_depth==0 \u2014 the test must call the top-level entrypoint, not a nested savepoint context, or commits are suppressed by design. PITFALL: keep the seed small but structurally > one budget window; do not seed a real 6 GB archive in unit scope.","id":"polylogue-1xc.1","issue_type":"bug","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T21:53:03Z","status":"closed","title":"Regression-guard chunked insight rebuild against single-transaction WAL blowup","updated_at":"2026-07-04T21:59:14Z"} -{"_type":"issue","acceptance_criteria":"1) An ADR under docs/ (or thoughtspace) that inventories every current insight table, classifies per-session vs cross-session scope and its affected-scope function, and proposes (or explicitly rejects) a declared-derived-view registry with a single refresh engine. 2) Includes a migration sketch and a cost/benefit call vs leaving rebuild.py as-is. 3) If accepted, spawns implementation child beads; if rejected, records why so it is not re-litigated. No production code change in this bead.","closed_at":"2026-07-13T04:04:37Z","comment_count":0,"created_at":"2026-07-04T21:22:49Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T23:22:48Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.10","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-13T06:04:36Z","created_by":"Sinity","depends_on_id":"polylogue-5wp","issue_id":"polylogue-1xc.10","metadata":"{}","type":"supersedes"}],"dependency_count":0,"dependent_count":0,"design":"Longer-horizon refactor the operator gestured at ('insights as declared derived views'). Today per-session (profiles, latency, work_events, phases, runs, observed_events, context_snapshots) and cross-session (threads, session_tag_rollups, provider_day aggregates) refresh logic is hand-woven across rebuild.py (~1600 lines), aggregates.py, threads.py, and the convergence stage. Evaluate whether these can be declared as a registry of derived-view specs (source rows -> materialized table, per-session vs grouped scope, materializer version) driven by one incremental refresh engine that automatically computes the affected scope on write and the global scope on version bump. Goal: collapse the bespoke incremental-vs-full branching and make adding an insight a declaration rather than editing five files. This is a spike/ADR, NOT a commitment to rewrite - measure whether the abstraction pays for itself against the current working code. Cross-reference insights/registry.py (already a partial registry).","id":"polylogue-1xc.10","issue_type":"feature","labels":["area:storage","delivery:B-storage-rebuild-bytes","lane:storage-rebuild-scale"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=B-storage-rebuild-bytes; lane=storage-rebuild-scale; readiness=D-horizon-ready; proof=large-corpus rebuild probe, blue-green generation swap proof, WAL/resource envelope report. Original readiness=D-horizon-ready.","owner":"ezo.dev@gmail.com","priority":2,"status":"closed","title":"Design spike: express session insights + aggregates as declared derived views over a single refresh engine","updated_at":"2026-07-13T04:04:37Z"} -{"_type":"issue","acceptance_criteria":"Every freshness-probe exception handler in convergence_stages.py logs (warning, exc_info=True) and returns the 'needs work' value (True / the input paths), not the 'converged' value (False / empty set). A test injecting an exception into a probe asserts the stage does NOT report converged and the error is logged. Repeated probe failure surfaces in convergence debt / daemon status. Verify: unit test with a monkeypatched probe raising, asserting needs-work + log; grep convergence_stages.py shows no bare 'except Exception: return False' in a check/probe without a log.","close_reason":"Closed by da8d2ca73. Existing convergence_stages.py probe handlers now fail toward work on exceptions; added regression tests for file-backed FTS/insights probes and split-archive FTS/embed/insights helpers that inject SQLite failures and assert needs-work returns plus warning logging with exc_info=True. Source audit found no bare probe exception path returning converged without logging. Verified with focused convergence-stage pytest and devtools verify --quick.","closed_at":"2026-07-05T08:22:07Z","comment_count":0,"created_at":"2026-07-04T22:35:46Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-05T00:35:45Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.11","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-05T00:35:47Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.9","issue_id":"polylogue-1xc.11","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-05T00:49:07Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.4","issue_id":"polylogue-1xc.11","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"design":"daemon/convergence_stages.py: the freshness PROBE handlers swallow exceptions and default to 'no work needed', with NO logging \u2014 the opposite of the invariant they enforce. FTS check(path) returns False on exception (105-106) = 'does not need repair'; check_many returns set() on exception (161-162) = 'no paths need work'; insights probes repeat the pattern (342 return False, 412 return set()). Contrast the execute() handlers (136-138, 382-384) which logger.warning(exc_info=True) before return False. Consequence: a transient probe error (SQLite lock, schema hiccup, a single corrupt row in the count query) is read as 'invariant satisfied' -> the stage skips -> FTS/insights stay stale INDEFINITELY with zero signal, until an unrelated trigger forces a rebuild. This is a silent automagic-invariants violation, DISTINCT from 1xc.9/1xc.4 (which harden the false_means_pending EXECUTE path). FIX: probe failures must (1) logger.warning(exc_info=True), and (2) fail toward 'needs work' (return True / include the path) so the executor runs and either repairs or logs its own failure \u2014 never fail-closed to 'converged'. Consider surfacing repeated probe failures as convergence debt (live_convergence_debt) so archive_debt/status shows it.","id":"polylogue-1xc.11","issue_type":"bug","labels":["area:daemon","area:storage"],"owner":"ezo.dev@gmail.com","priority":2,"status":"closed","title":"Convergence freshness probes fail-closed to 'converged' on error, silently suspending auto-convergence","updated_at":"2026-07-05T08:22:07Z"} -{"_type":"issue","acceptance_criteria":"1. The batched index schema contains messages_fts_identity(rowid PRIMARY KEY, block_id UNIQUE, source_hash, recipe_id) and exact freshness fields for missing, excess, identity/source/recipe mismatch, check time, and repair generation. 2. Production triggers and full rebuild maintain FTS, docsize, identity ledger, and O(1) freshness state atomically across empty/text transitions, text change, delete, replacement, rollback, and recipe change. 3. Exact reconciliation compares desired block identity/source/recipe with the ledger and docsize; equal-count rowid reuse, changed text, and changed tokenizer/fold recipe all fail before repair. 4. Periodic convergence detects drift in either FTS or ledger, rebuilds both in one bounded operation, records before/after state, and converges idempotently. 5. Metrics/readiness never scan blocks or FTS; ops history is bounded. 6. A real-trigger Hypothesis state machine covers rowid reuse, full replace, rollback, empty text, source change, and recipe change. 7. Removing any trigger arm, block_id/source/recipe check, or exact audit fails. 8. FTS consumes the shared DerivationKey value semantics without sharing embedding storage, scheduling, or lifecycle.","assignee":"Sinity","close_reason":"Core shipped in PR #3235 (merged 121dabe25): messages_fts_identity rowid\u2192block_id ledger (source_hash=blocks.content_hash, versioned recipe_id), identity writes inside the same trigger bodies, exact reconciliation joins rowid+block_id+source_hash+recipe_id (present-but-wrong scoping \u2014 missing-entry counting would permanently poison ready via write.py fast path), bounded ops.db drift history + polylogue_fts_drift_rows Prometheus gauge, schema v43 with declared clone-safe FTS_REINDEX fast-forward, Hypothesis metamorphic state machine on REAL triggers. AC matrix: 1/3/5/6/7/8 satisfied; AC2 write.py companions + AC4 periodic stage deferred to polylogue-miwv.","closed_at":"2026-07-21T05:55:29Z","comment_count":0,"created_at":"2026-07-05T23:44:29Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:44:28Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.12","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"FTS readiness is too boolean: operators need drift MAGNITUDE and tests need to prove trigger coherence under arbitrary block mutation. Keystone identity: messages_fts.rowid == blocks.rowid == docsize.id \u2014 and SQLite ROWID REUSE means a ghost FTS row can bind to a DIFFERENT block after delete+insert, so count agreement is insufficient: exact checks must join on rowid AND confirm block_id. Add: Prometheus gauges from the fts_freshness_state ledger (O(1), no COUNT on scrape), ops.db fts_drift_samples history with retention, metamorphic property tests (arbitrary insert/update/delete sequences through the REAL triggers => 0 missing / 0 excess, incl. empty-text transitions and repair convergence), and periodic exact reconciliation because the ledger itself can be the thing that drifted.","design":"Implement exact FTS identity in the next batched index-schema window. Consume the storage-neutral DerivationKey value shape from polylogue-wmsc for subject/grain, source identity, recipe identity, and output contract, but keep an FTS-owned rebuildable ledger and lifecycle. Add messages_fts_identity keyed by rowid with UNIQUE block_id plus source_hash and recipe_id, maintained by the same insert/delete/update trigger events as contentless messages_fts and rebuilt atomically by the repair path. Desired state is every non-empty-search_text block represented by rowid, block_id, source hash, and the FTS tokenizer/fold/schema recipe. Observed state is identity ledger plus messages_fts_docsize. Exact reconciliation classifies missing desired rows, excess observed rows, rowid/block mismatches, source mismatches, and recipe mismatches. Extend freshness state with exact counts/check time/repair generation; Prometheus reads only that O(1) state. Periodic convergence recomputes the exact comparison and repairs FTS plus ledger together because trigger-maintained state is not self-authenticating. Persist bounded samples in ops.db. Do not recover identity from contentless rows, infer it from counts, or create a universal derivation table.","id":"polylogue-1xc.12","issue_type":"bug","labels":["area:storage","delivery:B-storage-rebuild-bytes","horizon:frontier","lane:storage-rebuild-scale","tech-tree"],"metadata":{"frontier":"active","frontier_program_ref":"polylogue-1xc"},"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=B-storage-rebuild-bytes; lane=storage-rebuild-scale; readiness=A-implementation-ready; proof=large-corpus rebuild probe, blue-green generation swap proof, WAL/resource envelope report. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/021_polylogue_1xc_12.md (depth: anchored-contract-prework; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nPriority correction 2026-07-15: promoted and admitted because rowid reuse can make FTS appear coherent while binding search results to the wrong block identity.\nTerra-readiness correction 2026-07-15: contentless FTS cannot prove block identity. The packet now settles a shadow rowid-to-block_id ledger, exact three-way reconciliation, O(1) metric projection, periodic self-audit, and real-trigger state-machine proof.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-20T21:47:09Z","status":"closed","title":"FTS drift gauges + metamorphic coherence tests; rowid-reuse requires block_id check","updated_at":"2026-07-21T05:55:29Z"} -{"_type":"issue","acceptance_criteria":"A growing excluded fixture reports excluded plus lag and retained reason, never idle; a healthy quiet source reports every acquisition-to-searchable checkpoint; named miss diagnostics distinguish unseen, acquired-unparsed, parsed-unindexed, indexed-unconverged, and searchable; exact-source execution avoids archive-wide scans; live excluded and healthy receipts exist; excluded and broken-head populations are classified before reset; focused tests and quick gate pass.","comment_count":0,"created_at":"2026-07-15T04:23:46Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T06:23:45Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.13","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T20:17:32Z","created_by":"Sinity","depends_on_id":"polylogue-cuxz","issue_id":"polylogue-1xc.13","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T06:25:34Z","created_by":"Sinity","depends_on_id":"polylogue-lkrc","issue_id":"polylogue-1xc.13","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T06:25:37Z","created_by":"Sinity","depends_on_id":"polylogue-yla8","issue_id":"polylogue-1xc.13","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Dogfood traced one growing Codex JSONL across filesystem, cursor, raw revisions, index, and FTS. Its cursor was excluded after five failures, later revisions remained unparsed, and the index was stale. The bounded sample omitted it and cursor projection classified excluded as idle before byte lag. Archive totals show 3,821 excluded cursors and 1,890 broken heads.","design":"Add a source or session scoped freshness projection joining source stat, cursor offset and observed size, retry or exclusion reason, acquired and accepted raw revision, parse and authority state, index high-water, and FTS or insight convergence. Excluded is degraded before idle. Keep raw authority in polylogue-lkrc and replay prevention in polylogue-yla8.","id":"polylogue-1xc.13","issue_type":"feature","labels":["area:daemon","area:sources","area:storage","delivery:A-trust-floor","delivery:B-storage-rebuild-bytes","horizon:frontier","lane:storage-rebuild-scale"],"notes":"Live evidence 2026-07-15 from MCP readiness_check: raw_artifact_count=41,758, materialized_raw_artifact_count=18,331, archive_session_count=18,434, join_gap_count=23,427, plus 1,890 broken active heads, 40 cursor-ahead rows, and 34 uncomparable authority rows. The named-source projection must expose these excluded/degraded populations with snapshot/freshness and must not let an archive-wide session count imply source completeness.\n2026-07-16 integration scope: implement a bounded exact-source freshness read projection and canonical query/status/MCP surface only. It will classify excluded, cursor-ahead, and broken-head evidence as degraded before idle; distinguish unseen, acquired-unparsed, parsed-unindexed, indexed-unconverged, and searchable; and use exact source predicates with no archive/root scans or live mutation. Authority classification/repair remains polylogue-lkrc; replay prevention/actuation remains polylogue-yla8. Live receipts are read-only and deferred until code safety review.\n2026-07-16 implementation accounting: bounded exact-source projection now joins filesystem stat, cursor/retry/exclusion state, accepted raw authority (observed; polylogue-lkrc), application evidence (observed; polylogue-yla8), index high-water/broken-head, FTS, and insight debt; canonical status --source and MCP named_source_freshness call it. AC: excluded-growing/healthy-quiet fixtures and all five miss stages satisfied; exact-key bounds and scan rejection satisfied; aggregate excluded/cursor-ahead now degraded before idle; focused SQLite/FTS+MCP/status tests and seeded affected verify+quick pass. Remaining AC: operator must capture two read-only exact live receipts (incident excluded path and healthy quiet control) after selecting paths, before any lkrc/yla8 remediation. No archive mutation or receipt run in this integration.\n2026-07-16 review handoff: implementation commit 2242fab26 is published as PR #2924. It remains in progress solely for the two operator-selected, read-only live receipts; no archive repair/replay/reset authority was exercised by this branch.\n2026-07-16 GPT-Pro corpus adjudication: named-source design package 8fa6ec827281 is superseded by implementation package 17d8a28e9c6, merged as PR #2924 (b6c78adfcd666358307daf64ac97e8d695a8b854). Residual exact-source operational receipts remain governed by this bead, not a revived handoff lane.\n2026-07-17 fresh-source evidence: current raw browser capture contains ChatGPT handoff chatgpt:6a580976-03d0-83eb-af6a-eb745db5ac0c (Agent Query Discovery; file mtime 07:45 CEST), but POLYLOGUE_ARCHIVE_ROOT=/home/sinity/.local/share/polylogue polylogue --json --origin chatgpt-export find 'since:8h' returned total=0. This is a direct named-origin freshness/user-visible queryability failure: a newly captured ChatGPT artifact exists yet cannot be discovered through the archive. The eventual source-freshness route must make this distinguishable as acquired/unparsed or otherwise degraded with an exact source/capture reference, rather than a misleading empty search. No archive mutation was performed.\nWarroom sweep It.17: claiming session closed; implementation fully merged (#2924). Bead remains open ONLY for two operator-selected read-only live receipts (one excluded-incident path, one healthy quiet control) -- a ~5-minute OPERATOR action, flagged on the warroom board.\n2026-07-26 portfolio-convergence audit: released stale in_progress claim after >7 days with no recorded activity; scope remains open and must be re-claimed on real work start.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-16T02:30:06Z","status":"open","title":"Expose named-source freshness and excluded cursor degradation","updated_at":"2026-07-26T09:13:00Z"} -{"_type":"issue","acceptance_criteria":"1. One typed WorkloadEnvelopeSpec and WorkloadReceipt represent workload/input identity, phase boundaries, build/archive/frame, process-tree and cgroup scope, wall/CPU, RSS/PSS anon/cache/swap, temp and read/write I/O, response bytes, cancellation/progress/backpressure, quiescence, and missing measurements. 2. Existing query-memory, pipeline-probe, scenario-execution, ingest/source-observation, verify-run, and SLO-catalog paths either emit the shared receipt or have an explicit adapter/exemption; unit conversion and process-scope semantics are tested. 3. The 2026-07-15 MCP query and 2026-07-13 watcher append/cohort incidents run as named canaries with comparable phase receipts that distinguish peak from retained/quiescent memory and anonymous charge from cache. 4. A valid oversized query remains logically answerable through scheduling/page/stream/spool/resume even when a physical budget is exceeded; a mutation that converts a budget into a semantic cap fails. 5. Regression gates compare like workload/input/build scopes, expose measurement unavailable separately from pass, and include anti-vacuity mutations for omitted child RSS, cgroup file cache, cancellation latency, and cleanup. 6. The common collector is bounded and does not perturb measured work by serializing the corpus or running parallel heavy readers.","comment_count":0,"created_at":"2026-07-15T18:45:44Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:45:44Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.14","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T20:45:47Z","created_by":"Sinity","depends_on_id":"polylogue-20d.14","issue_id":"polylogue-1xc.14","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T20:45:45Z","created_by":"Sinity","depends_on_id":"polylogue-o21.1","issue_id":"polylogue-1xc.14","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T20:45:47Z","created_by":"Sinity","depends_on_id":"polylogue-s8gb","issue_id":"polylogue-1xc.14","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T20:45:46Z","created_by":"Sinity","depends_on_id":"polylogue-z9gh.1","issue_id":"polylogue-1xc.14","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":2,"description":"Polylogue measures costly work through incompatible one-off paths: query_memory_budget, pipeline probes, scenario execution, verify-run RSS, ingest throughput, source observations, the SLO catalog, and an append-cohort counter. That fragmentation let an MCP query process reach 8.5 GiB plus swap and a daemon catch-up process retain over 4 GiB anonymous memory without one comparable phase/resource receipt. Define one workload-envelope declaration and observation contract. It governs physical execution and evidence; it never imposes a semantic result cap or turns a valid large operation into permanently unsupported work.","design":"Define WorkloadEnvelopeSpec with stable workload/family identity, input/corpus distribution refs, phase model, process-tree/cgroup measurement scope, concurrency/admission shape, quiescence window, and dimensions for wall/CPU, current/peak RSS/PSS, anonymous/file-cache/swap, temp/storage and read/write I/O, response bytes, cancellation latency, progress, queue/backpressure, and cleanup. A WorkloadReceipt binds spec/version, build/runtime, archive/generation/frame, phase observations, measurement availability, budget verdicts, and evidence refs. Budgets declare measure-only, regression-gate, or containment semantics; exceeding them may schedule, page, stream, spill, pause, or resume but cannot create a semantic query/result limit. Consolidate existing collectors behind adapters rather than deleting domain phase instrumentation. Prove with the mandate query workload and watcher append/cohort catch-up, including peak versus quiescent and anon versus cache.","id":"polylogue-1xc.14","issue_type":"feature","labels":["area:ops","area:perf","area:verification","horizon:frontier"],"metadata":{"frontier":"active","frontier_program_ref":"polylogue-1xc"},"notes":"Active-set expansion 2026-07-15: admitted as a high-leverage operational mechanism under the scale/raw-authority program; execution focus remains readiness- and conflict-aware.\n2026-07-16 schema-workload refinement: child polylogue-1xc.14.1 makes input/corpus distribution refs authoritative and executable. Provider observations produce a bounded privacy-safe WorkloadProfile; deterministic provider-native corpora then traverse production ingest/index/query routes and emit this bead shared receipts. This replaces handwritten realistic-fixture and one-off performance-scenario approaches without reducing scale or semantic ambition.\n2026-07-16 GPT-Pro corpus adjudication: workload/resource receipt package 1d287d6cd7c6 is blocked_but_seeded here. Retain physical measurement and no-semantic-cap rule; provider-network failure in historical ledger is not evidence that a later deliverable did not exist. Current schema-derived workload-profile child 1xc.14.1 is the authoritative next dependency.\n2026-07-16 foundation landed in PR #2934 commit 23e8b2933: deterministic real-pipeline seeded archive artifacts now publish atomically as immutable split-tier snapshots, carry stable archive/profile/build/recipe identity plus planted wire facts, and clone privately for mutating consumers. Legacy seeded_db fixtures were removed; C-03 now exercises generated Codex bytes through acquire\u2192parse\u2192materialize\u2192index\u2192query. This is substrate only: live real-archive regeneration/phase evidence and any resulting memory fix remain open.\n2026-07-27 (polylogue-a47769bba68869d49 session): correcting the \"substrate only\" characterization from the 2026-07-16 note -- this is more implemented than that framing suggested. WorkloadReceipt/WorkloadEnvelopeSpec (polylogue/scenarios/workload.py) are consumed by 6 devtools modules (query_memory_budget.py, verify.py, raw_authority_scale_proof.py, seed_receipt_compare.py, pipeline_probe/result.py, verify_slos.py) plus tests/infra/append_cohort_memory_counter.py. tests/unit/scenarios/test_workload_receipts.py has named canary specs for BOTH AC #3 incidents: exact_session_actions_canary_spec (2026-07-15 MCP query/C-03) and the append-cohort counter consumed by tests/integration/test_append_cohort_memory.py (2026-07-13 watcher catch-up), plus a passing anti-vacuity mutation test (test_physical_budget_cannot_be_expressed_as_a_semantic_result_cap).\n\nNot verified this pass, so NOT closing: AC #2 (every named path -- query-memory, pipeline-probe, scenario-execution, ingest/source-observation, verify-run, SLO-catalog -- either emits the shared receipt or has an explicit adapter/exemption, with unit-conversion/process-scope tests) needs an exhaustive per-path enumeration I did not have budget to complete confidently. AC #5/#6 (anti-vacuity mutations for omitted child RSS/cgroup file cache/cancellation latency/cleanup; bounded collector proven not to perturb measured work) also not independently re-verified. This bead is closer to closeable than \"substrate only\" implies but a confident AC-by-AC call needs a dedicated focused pass over devtools/verify.py + verify_slos.py + their mutation tests, not new implementation.\nREFERENCE CORRECTION 2026-07-28: '(polylogue-a47769bba68869d49 session)' in these notes is an agent SESSION id, not a bead id. Same wording appears on 1xc.14.1, 1xc.14.1.1, 1xc.14.1.2 and 1xc.14.1.3 and is flagged by backlog-hygiene X2 on all five; none is a dangling bead reference.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Declare workload envelopes and resource receipts once","updated_at":"2026-07-28T20:05:30Z"} -{"_type":"issue","acceptance_criteria":"1. Every promoted provider package may carry a versioned, deterministic, privacy-classified WorkloadProfile whose provenance names archive generation, observation window, sample counts, inference version, and privacy policy; schema generation into a staging directory does not mutate committed packages. 2. Inference captures bounded streaming presence/null/type rates, quantiles and tails, joint structural variants, tool-result relationship states, lineage/replay shapes, active-growing and convergence states, provider/package mix, archive unit sizes, and predicate selectivity without retaining the corpus or unbounded per-value lists. Peak inference memory is bounded independently of sample count and full-corpus generation proves that bound. 3. Synthetic generation consumes the profile jointly rather than sampling independent marginals, emits deterministic provider-native wire artifacts, and reaches the production acquire, parse, materialize, index, and query implementations; removing a production parser or query pushdown breaks the test. 4. Named scale tiers preserve tail and selectivity activation conditions while allowing small deterministic CI projections. The C-03 canary includes a mixed archive plus exact-session action query and fails when either ranking leg loses the selective bound. Tool pairing, lineage replay, growing-session, and partial-convergence canaries are generated from the same profile mechanism. 5. Workload runs emit polylogue-1xc.14 receipts with workload/profile/build/archive identity, phase timings, resource peaks, cancellation/progress, and cleanup; no performance test invents a separate corpus identity or measurement envelope. 6. A promotion review reports structural changes, distribution changes, and a privacy-vetting inventory. It automatically rejects raw content, filesystem paths, account identifiers, session/message/tool IDs, rare free text, and secrets while listing potentially identifying structural enum/date/domain values for operator approval. 7. The vague performance/throughput scenario family is superseded by this mechanism, and focused schema inference, generator, real-route canary, privacy, determinism, memory-bound, and receipt tests plus devtools verify --quick pass.","comment_count":0,"created_at":"2026-07-16T09:45:51Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T11:45:51Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.14","issue_id":"polylogue-1xc.14.1","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Current schema inference produces structurally valid provider records but destroys the distributions and relationships that activate production failures. Field marginals are sampled independently, numeric values are uniform over extrema, arrays are capped at five, CorpusSpec uses a uniform message-count range, and cluster collection materializes the full unit stream. Consequently tests can traverse real ingest code while remaining unlike the archive shapes that caused the July 15 exact-session action query to perform archive-global ranking before a selective bound. Provider observations must remain the authority: infer a bounded privacy-safe workload profile beside each schema package, generate deterministic provider wire artifacts from it, and exercise the real acquire, parse, materialize, index, query, cancellation, and cleanup routes. This is a production workload declaration, not a handwritten realistic fixture library and not a semantic cap on archive size.","design":"Add a versioned WorkloadProfile artifact to provider schema packages and reference it from WorkloadEnvelopeSpec. Extend field statistics with bounded streaming counts and deterministic quantile sketches for presence versus null, type mix, numeric/string/array/object sizes, payload tails, and conditional distributions. Add structural joint profiles keyed by provider package/version, artifact kind, and cluster for field co-occurrence, tagged-union variants, nested tool envelopes including functions.exec, tool call/result pairing states (paired, missing, late, duplicate, error), lineage depth/width/replay, growing-session state, and convergence state. Add an archive mix profile for origin/package proportions, session/message/block/action size distributions, selective predicate cardinalities, payload tails, and topology shapes. Store only counts, rates, buckets, structural tokens, and privacy-approved enum values; never persist raw content, paths, IDs, rare strings, or representative payloads in the promoted profile. Replace list(iter_schema_units(...)) and unbounded measurement lists with bounded deterministic streaming aggregation. Extend synthetic generation so one seed chooses correlated profile variants and archive scale/selectivity targets, emits provider-native bytes, and then invokes production ingestion and read composition. Wire scenario/performance/query-law lanes to generated workload IDs and shared receipts. First canary reproduces C-03: an exact-session actions query over a large mixed archive must push the session bound into both ranking legs and remain fast; a mutation restoring global-first composition must fail. Existing hand-authored fixtures remain only for minimal parser edge cases and independent known-answer oracles.","id":"polylogue-1xc.14.1","issue_type":"feature","labels":["area:devtools","area:ops","area:perf","area:sources","area:test","area:verification","horizon:frontier"],"notes":"2026-07-16 operator correction: do not optimize for the smallest profile or a preselected minimum of statistics. Preserve every observation with positive expected downstream utility when it can be represented deterministically, privacy-safely, and with bounded streaming resources. Boundedness constrains inference memory and encoded representation, not semantic ambition. The profile format must be extensible, retain sufficient statistics or mergeable sketches for useful derived views, and emit a loss/novelty inventory for stable observed structure that no current field models so useful signal cannot disappear silently. Compact marginals, joints, sketches, and conditional summaries are encodings of evidence, not permission to discard it.\n2026-07-16 first implementation slice (not closure): provider packages now carry deterministic privacy-classified workload profiles with bounded numeric/string/array/object and categorical sketches, structural joint variants, tool-result/functions.exec and lineage relationships; synthetic scalar/array generation consumes observed histograms; an explicit archive-composition artifact captures origin/package mix, session/message/block/action shapes, payload tails, anonymous predicate selectivity, topology, raw revision/growing-source state, convergence debt/lag, and tier sizes without retaining content, paths, repository/branch/model/tool values, or IDs. Every categorical observation contributes to a fixed-memory hashed distribution and approximate-distinct sketch even when readable values are privacy-suppressed. Focused evidence: 765 affected schema tests passed in 38.93s; strict mypy passed; devtools verify --quick passed every step except pre-existing demo-corpus-construct-audit drift owned by polylogue-b054.1.1.1/browser capture. Remaining parent scope is durable: child polylogue-1xc.14.1.1 owns the replayable ObservationJournal and true full-corpus memory bound; joint synthetic variant selection, named scale tiers, C-03 and other production-route canaries, shared workload receipts, promotion/privacy review, and live regeneration remain open.\n2026-07-16 correction to the first-slice note: demo-corpus drift was not pre-existing. Clean master was stable across three sequential and three 8-worker isolated runs. The workload branch changed RNG consumption and exposed that ChatGPT/browser-capture coalescence depended accidentally on a seeded UUID. The fix makes scenario-declared session_native_ids authoritative at provider wire generation, so schema/profile evolution can change content distributions without changing a fixture identity contract. The existing real ingest/convergence test failed before the fix and passed afterward; demo-corpus-datasheet is again in sync.\n2026-07-26 portfolio-convergence audit: released stale in_progress claim after >7 days with no recorded activity; scope remains open and must be re-claimed on real work start.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-16T11:58:59Z","status":"open","title":"Derive archive-scale workload profiles from provider schemas","updated_at":"2026-07-26T09:13:00Z"} -{"_type":"issue","acceptance_criteria":"1. No full-corpus path constructs a Python list or set proportional to unit, membership, sample, scope, path, tool-ID, or distinct-value count; source inspection and an RSS scaling test cover every former retention site. 2. A replayable ObservationJournal ingests each SchemaUnit once, supports deterministic indexed passes for cluster/package/schema/profile generation, uses a permission-restricted local non-synced scratch root, rejects archive/backup/cloud-sync targets, and removes DB/WAL/SHM files after success, exception, cancellation, and ordinary worker termination; stale-run recovery is tested for abrupt death. 3. Mergeable accumulators preserve all exact additive counts plus bounded distributions, distinctness, heavy hitters, joints, relationships, and explicit loss/approximation metadata. Increasing corpus size cannot silently erase a positive-value observation class. 4. A 1x versus 10x generated corpus keeps peak Python RSS within a fixed overhead plus configured journal/cache buffers while producing counts scaled by 10; the test records journal bytes and cleanup. 5. Small known-answer provider bundles are byte/content equivalent to the reference algorithm except for newly declared profile metadata, and shuffled input order produces the same schemas, package assignments, profiles, and identities. 6. Focused clustering, package, privacy, determinism, memory, cancellation, cleanup, unsafe-root, stale-recovery, and actual full-corpus generation tests plus devtools verify --quick pass.","comment_count":0,"created_at":"2026-07-16T12:31:25Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T14:31:25Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.14.1","issue_id":"polylogue-1xc.14.1.1","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Full-corpus inference currently materializes units, memberships, per-package schema samples, profile summaries, and several evidence maps in Python memory. Replacing only list(iter_schema_units(...)) would move rather than solve the retention problem. Introduce one replayable bounded-observation substrate so every downstream cluster, package, schema, relationship, privacy, and workload-profile pass can consume the same evidence without retaining the corpus. This is a memory-bound implementation constraint, not permission to sample away useful observations.","design":"Add a temporary ObservationJournal owned by one generation run. Create it only under a local permission-restricted runtime/cache root, with its parent and SQLite files inaccessible to other users; reject archive roots, cloud-synced roots, and configured backup/data-lake destinations because the spool contains raw provider payloads. Ingest each SchemaUnit once using canonical serialization. Record typed structural metadata and payload bytes separately, with indexes for artifact kind, scope, profile family, and package assignment. Make cluster/package assembly multi-pass over streaming journal cursors; package membership becomes a query/view, not a Python list. Refactor field, categorical, structural-variant, tool-result, lineage, privacy, and schema-shape inference into mergeable accumulators. Every observation updates sufficient statistics or a documented bounded sketch; privacy-sensitive values remain hashed/suppressed. Spill high-cardinality path/profile state into the journal instead of imposing a semantic cap. Use deterministic ordering and identities so small-corpus outputs match the in-memory reference. A run-lifetime owner must close connections and remove journal, WAL, and SHM files after success, exception, cancellation, and ordinary worker termination; startup stale-run recovery handles abrupt process death.","id":"polylogue-1xc.14.1.1","issue_type":"feature","labels":["area:devtools","area:ops","area:perf","area:schema","area:sources","area:test","area:verification","horizon:frontier"],"notes":"2026-07-16 live full-corpus evidence from the pre-hardening generator: by 31m45s the process retained ~1.83 GiB RSS, had issued ~89.5 GB of physical reads against a ~35 GB index, and only then had emitted five of nine provider directories. The run also attempted to decode a quarantined Hermes SQLite evidence database as JSON, logged the exception, and continued without representing the exclusion in the generated profile. The journal implementation must eliminate repeated archive scans and carry a typed per-artifact terminal ledger (included, intentionally excluded with taxonomy/reason, decode failure, unsupported, quarantined) into provenance/loss inventory so a successful generation cannot silently omit evidence.\n2026-07-16 implementation/evidence update: the old live all-provider run ended nonzero after ~60m, with last-observed ~1.37 GiB RSS and ~213 GB physical reads; five providers emitted, while ChatGPT/Claude Code/Gemini failed from stale pre-merge profile-family identities and Hermes silently omitted a quarantined SQLite artifact. This branch now routes real provider generation through a permission-restricted ObservationJournal, persists profile/package assignment, replays memberships and schema samples instead of retaining/copying payload lists, drops clustering payloads immediately after the one clustering observation, performs simultaneous family normalization, recovers dead-owner journals immediately, and removes DB/WAL/SHM on exit. During focused Codex proof, an initial replay bug repeatedly decoded the full record-stream cluster payload and exceeded 2.7 GiB; after removing that retained payload the same production generation test passed in 8.73s and cleanup left an empty journal directory. Remaining before closure: live 1x/10x RSS proof, eliminate/audit residual high-cardinality accumulator sets, integrate terminal artifact ledger at observation source, cancellation proof, and small-corpus/shuffle equivalence.\n2026-07-16 boundedness proof/update: commits de25cf6c2 and 4ba7918c4 add real generate_provider_schema subprocess receipts for 32\u2192320 ChatGPT artifacts and one 1,024\u219210,240-record Codex JSONL. Counts scale exactly 10x; sampled peak RSS was ~96.5\u219297.3 MiB for artifact scaling and ~97.3\u2192109.4 MiB for the giant-stream scaling; journal/WAL/SHM cleanup was empty after every run. Source audit found the prior full-corpus JSONL path materialized every record, then silently reapplied the provider's ordinary 128-sample cap. The new replayable disk-backed sequence feeds every compact record into the ObservationJournal while classification/fingerprinting use bounded prefixes. Focused 77-test schema/sampling/generation gate and devtools verify --quick pass. This proves cross-artifact and single-stream scaling, but does not yet close the Bead: residual per-scope package assembly lists/high-cardinality output maps, cancellation equivalence, and definitive live full-archive generation/resource receipt remain.\n2026-07-17 live Codex full-corpus evidence: PID 1229268 remained runnable at 2h20m (about 84% one CPU), with +1.48 GiB physical reads over 30s and no current writes; it is not stuck. Its private observation journal has a 41.7 GiB WAL whose size/mtime stopped advancing at 04:23, so post-ingest replay is reading the uncheckpointed journal. Static trace confirms `ObservationJournal.close()` is the first normal commit after ingest and `_iter_joined_memberships()` fixes `samples` as the outer relation via `samples CROSS JOIN units`, then filters membership on `units`. Package schema/workload generation invokes that replay repeatedly. Evidence and repair hypotheses: `.agent/scratch/2026-07-17-codex-live-regeneration.md`. This strengthens the parent's remaining live receipt and residual replay-boundary scope: a successful small scaling proof did not demonstrate production archive-scale replay economics. Required closure proof now includes a committed-representative `EXPLAIN QUERY PLAN`/per-phase receipt showing selective membership avoids global sample scans, and a safe checkpoint/transaction design with cancellation cleanup.\n2026-07-17 repair landed: PR #2968, squash commit 067c87e49f58ceaa1526bc1a28630b74965b2f3f. The ObservationJournal now commits private bounded batches (1,024 units or ~32 MiB serialized payload) and flushes before replay; published schema artifacts remain success-only. Membership replay begins at filtered units and joins samples by unit id instead of forcing samples outermost. A plan contract proves a selective package replay uses `units_package_family_idx` then the samples primary key; a separate reader sees flushed evidence. Verification: focused 46-test schema journal/generation gate; `devtools verify --quick`; pre-push quick baseline. The live old Codex process cannot adopt the change; it remains evidence. Remaining parent scope still needs a representative committed live/production-scale receipt to quantify phase time, WAL peak, and read reduction, plus cancellation equivalence.\n2026-07-17 follow-up repair landed: PR #2971, squash commit 810037b86f0f5ec90cdb3b03d0b28e426ecdf874. Live Codex evidence showed one SchemaUnit can contain 223,710 samples (7,150 units / 23,608,430 samples observed), so per-unit commits alone could leave a multi-GiB transaction. `append_unit` now inserts samples in bounded row/byte batches and charges each completed batch to the existing private journal transaction budget; no evidence class is capped or discarded. Verification: all 15 ObservationJournal tests; `devtools verify --quick`; pre-push quick baseline.\n\n2026-07-17 Hermes terminal-accounting repair landed: PR #2973, squash commit df37b5bc44d900d8886154a335ebf5d07fde16b0. The earlier alleged UTF-8 failures were reclassified from direct archive evidence: both 32,768-byte blobs begin `SQLite format 3` and are Hermes `verification_evidence.db` sidecars, not text payloads. Sampling now applies artifact-path taxonomy before generic payload decode and records `intentionally_excluded` / `metadata_document` / `artifact_taxonomy:Hermes SQLite evidence sidecar`. A live full-archive receipt reports 188 included session documents, exactly two such typed exclusions, two unsupported non-session templates, and one provider mismatch\u2014no decode failures. The same repair also preserves the distinct valid-recovery case: UTF-8-encoded lone surrogate code units in historical JSON/JSONL use surrogatepass; arbitrary malformed bytes still fail. Verification: 42 focused raw-payload/sampling tests; real Hermes full-corpus generation (success, empty stderr); devtools verify --quick; pre-push baseline. This satisfies the terminal-ledger integration gap for this concrete artifact class, but not the parent\u2019s cancellation, residual high-cardinality, shuffle-equivalence, or representative production-scale replay receipt obligations.\n2026-07-26 portfolio-convergence audit: released stale in_progress claim after >7 days with no recorded activity; scope remains open and must be re-claimed on real work start.\n2026-07-27 (polylogue-a47769bba68869d49 session): implemented the two concrete test gaps identified by source audit and shipped PR #3298 (branch feature/test/schema-generation-cancellation-shuffle-equivalence, not yet merged):\n\n- test_generation_cancellation_restarts_from_scratch_and_matches_uninterrupted_run (tests/unit/core/test_schema_observation_journal.py) + tests/infra/schema_generation_cancellation_probe.py: proves the real generate_provider_schema entrypoint's \"restart_from_acquisition\" resume claim empirically -- kill a run mid-observe_and_cluster via SIGTERM (deterministic sync point via a progress_callback PAUSED marker, no sleep-race), confirm the journal directory is empty afterward, rerun to completion, assert the resulting schema/sample_count/default_version equal an uninterrupted reference run on the same synthetic archive. This closes AC #2/#6's \"cancellation\" gap through the production entrypoint, not just the existing raw ObservationJournal.append_unit SIGTERM tests.\n- test_shuffled_sample_order_yields_identical_schema_and_package_assignment: feeds an identical SchemaUnit multiset through the real _build_provider_bundle in two different orders (monkeypatching iter_schema_units, same technique as the existing test_build_provider_bundle_captures_element_windows_and_bundle_scopes), asserts schema content, package identity (anchor_profile_family_id, profile_family_ids, sample_count, bundle_scope_count, first_seen/last_seen), catalog version selection, and cluster-manifest identities are all order-invariant. Closes the shuffle-order half of AC #5.\n\nAlso did the source-level residual-accumulator audit implied by AC #1/#3 (\"no full-corpus path constructs a list/set proportional to... distinct-value count\"): traced every unbounded-set mutation site (_ClusterAccumulator.exact_structure_ids/bundle_scopes/member_profiles/source_family_ids in polylogue/schemas/generation/{models,packages,cluster_collection}.py) and confirmed every one is guarded by `if journal is None:` -- and _build_provider_bundle (the ONE production entrypoint used by generate_provider_schema/generate_all_schemas) always constructs a real ObservationJournal and never passes journal=None. So in production these Python-memory sets are provably never populated; the guard is dead code outside test-only direct calls. AC #1's \"source inspection... covers every former retention site\" is now backed by this trace.\n\nNOT closing this bead: AC #5 also requires \"small known-answer provider bundles are byte/content equivalent to the reference algorithm except for newly declared profile metadata.\" I could not find an unambiguous, non-fabricated interpretation of \"the reference algorithm\" -- generate_schema_from_samples (schema_builder.py) uses genson's SchemaBuilder, a structurally different shape-inference algorithm than _generate_cluster_schema's observed_structure_schema/merge_observed_structure_schemas, so comparing them would prove nothing (two different algorithms disagreeing is not a bug). The bead's own description names list(iter_schema_units(...)) as the naive eager alternative to journal-backed streaming, which would require building a full parallel non-journal reference implementation of cluster/package/catalog assembly purely for this test -- a toy-duplicate risk I did not want to fabricate without operator sign-off on what \"reference algorithm\" is actually supposed to mean. Left open with this precise gap named; see PR #3298 body for the same reasoning.\n2026-07-28 (fresh worktree-isolated session, no code changes): re-verified the two test gaps this bead's 2026-07-27 note describes as already implemented. Found PR #3298 (branch feature/test/schema-generation-cancellation-shuffle-equivalence) merged as commit 45e8d7084 -- both test_generation_cancellation_restarts_from_scratch_and_matches_uninterrupted_run and test_shuffled_sample_order_yields_identical_schema_and_package_assignment already exist on master in tests/unit/core/test_schema_observation_journal.py, plus tests/infra/schema_generation_cancellation_probe.py. Nothing to implement or commit this session -- no new PR opened since there is no diff.\n\nIndependent verification performed:\n- devtools test tests/unit/core/test_schema_observation_journal.py tests/infra/schema_generation_cancellation_probe.py -> 17 passed in 18.98s.\n- mypy --strict and ruff check/format --check on both files: clean.\n- Anti-vacuity (temporary local mutations, reverted via `git checkout --`, never committed):\n - Shuffle test: appended one genuinely new, distinct SchemaUnit (raw_id=\"raw-6\") only to the shuffled list (a same-raw_id duplicate was tried first and got silently coalesced by journal upsert, so it doesn't count as a real anti-vacuity mutation -- noting this for future reference). Test failed with `AssertionError: assert 6 == 7` on `canonical_package.sample_count == shuffled_package.sample_count`, a real assertion, not an error.\n - Cancellation test: after the SIGTERM+restart step, deleted archive_root and reran the probe with --count 9 instead of the original 6. Test failed with `AssertionError` on the schema-equality dict comparison (`x-polylogue-observed-artifact-count: 9 != 6`), confirming the equivalence assertion is live.\n - Reverted both mutations; re-ran the full 17-test file to confirm clean pass afterward (git diff/status empty).\n\nAC completeness re-assessment (full text re-read fresh via `bd show --json`): AC #1 (no full-corpus proportional list/set), #2/#6-cancellation, #3 (accumulators), #4 (1x/10x RSS), and #5's shuffle-order clause are all backed by evidence in this bead's history (source audit, PRs #2968/#2971/#2973/#3003/#3298, 1x/10x receipts). The one concrete, still-open gap is AC #5's separate clause: \"Small known-answer provider bundles are byte/content equivalent to the reference algorithm except for newly declared profile metadata.\" The 2026-07-27 session already investigated this and could not find a non-fabricated interpretation of \"the reference algorithm\" (genson-based generate_schema_from_samples is a structurally different algorithm than the production observed_structure_schema/merge path; building a parallel non-journal reference implementation purely for this test risks a toy-duplicate). I concur with that determination on independent re-review -- did not attempt to resolve it, since it needs an operator ruling on what \"reference algorithm\" means, not more test-writing effort.\n\nNot closing: the AC #5 byte/content-equivalence-vs-reference-algorithm gap remains the sole named open item. Everything else this bead's notes claim as done is now doubly confirmed (implementation evidence + this session's independent re-run and anti-vacuity proof).","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-16T13:35:45Z","status":"open","title":"Make schema inference replayable and memory-bounded","updated_at":"2026-07-28T12:45:06Z"} -{"_type":"issue","acceptance_criteria":"1. Known natural-language question, path/XML-fragment, control-character, and overlength property keys collapse into additionalProperties while normal provider field names, MIME keys, and branch-like structural keys remain explicit. 2. Field statistics, structure fingerprints, generation, and validation use one classifier and cannot disagree about the same key. 3. A scanner over every decompressed staged artifact blocks credential/private-key/token patterns and unsafe content-shaped property names; it separately inventories readable enums, dates, domains, emails/account-like values, paths, IDs, and rare strings with artifact/path context for operator review. Seeded blocker and review-only values prove the distinction. 4. Live Claude Code regeneration contains none of the previously exposed content-shaped keys and reports every remaining potentially objectionable readable value class for operator vetting. 5. Current committed provider schemas are replaced with reviewed artifacts so the default branch no longer encodes observed session content as property names. 6. Focused field-stat/schema-law/audit/generation tests and devtools verify --quick pass.","assignee":"Sinity","comment_count":0,"created_at":"2026-07-16T13:10:07Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T15:10:07Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.14.1","issue_id":"polylogue-1xc.14.1.2","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"The committed Claude Code schema contains harmless natural-language session questions and a source-path/XML fragment as JSON property names. Those particular strings are not sensitive; the defect is schema pollution and a general leak channel because arbitrary observed content can enter committed artifacts. Dynamic-key collapse currently recognizes UUID/hex/prefixed identifiers and only collapses whole maps at high cardinality, so low-cardinality maps keyed by content survive inference.","design":"Strengthen the shared dynamic-key classifier with conservative content-shape rules: sentence-question markers, XML delimiters, control characters/newlines, and excessive length make a key observed map content rather than a stable provider field name. Preserve ordinary provider identifiers and useful structural tokens such as MIME types, branch-like values, model/tool names, dates, domains, and paths when they occur as values. Apply one predicate to field-stat wildcard traversal, structure fingerprints, schema collapse, and validation. Add a promotion audit over decompressed schema/package artifacts that distinguishes hard secret patterns from operator-review metadata: unsafe property names and actual credential material block promotion; readable enums, dates, domains, account-like strings, and paths are enumerated with location and frequency for operator judgment rather than silently erased. Regenerate the affected provider schema from the live archive into staging, prove the content-shaped keys are absent, report all remaining readable value classes, and promote only after review.","id":"polylogue-1xc.14.1.2","issue_type":"bug","labels":["area:devtools","area:ops","area:perf","area:schema","area:security","area:sources","area:test","area:verification","horizon:frontier"],"notes":"2026-07-16 old-run audit (not promotion): 65 emitted artifacts from Claude AI, Gemini CLI, Hermes, Antigravity, and Codex all parsed and their JSON Schemas passed Draft 2020-12 meta-validation. Automated scan found no credential/API-key/JWT/private-key/email/authorization material and no content-shaped property names. Review-only metadata comprised 90 absolute representative source paths, 3,397 bundle/session identifiers, and 274 privacy-approved values; readable examples include Sinity, Europe/Warsaw, Gmail, master, model/tool names, cache/directory names, and runtime vocabulary, all currently judged harmless by operator. Audit is necessarily incomplete because ChatGPT, Claude Code, and Gemini failed generation. A fresh fixed Claude Code run is in progress and must repeat both blocker scan and complete objectionable-value inventory independently before promotion.\n2026-07-16 operator/privacy clarification from live catalog audit: do not create a useful private schema and a weakened sanitized public schema. There is one authoritative semantic schema plus workload profile. Readable source paths/raw bundle-scope witnesses are generation/audit provenance and belong in a local restricted receipt, not in a divergent semantic artifact. Current committed catalogs still contain absolute home paths and raw bundle/session scopes for several providers; this is existing promotion debt even where the observed values are harmless. The workload profile itself correctly retains content-free sufficient statistics and explicit loss inventory. Promotion must structurally prevent raw path/scope evidence from entering committed packages while preserving exact/profile/scope resolution through a non-leaking identity mechanism or an explicitly local evidence mapping; do not simply delete useful resolution semantics or accept two schema meanings.\nWarroom sweep It.17 (2026-07-18): claim orphaned -- the claiming session was closed 2026-07-17 and no matching commits exist on master since 2026-07-14. Reset to open; prior notes/receipts unchanged.\n2026-07-27 (polylogue-a47769bba68869d49 session): confirmed AC #2 (one classifier) is satisfied -- is_dynamic_key (schemas/field_stats/detection.py) is imported and used consistently by field_stats/collection.py, generation/dynamic_keys.py, shape_fingerprint.py, validator.py, and promotion_audit.py; no separate/divergent classifier found. AC #3 (scanner separating credential-blocking from review inventory) is plausibly satisfied by the 3 existing tests in tests/unit/core/test_schema_promotion_audit.py (leak-channel blocking without misclassifying review values; credential redaction + invalid-artifact rejection; grouped review-value inventory).\n\nDid not independently re-verify AC #1's exact shape rules (question/path-XML/control-char/overlength key collapse) against is_dynamic_key's body this pass -- that would need a dedicated read of field_stats/detection.py's implementation against those four shape categories.\n\nNot closing: AC #4 and #5 structurally require an actual fresh Claude-Code regeneration from the live archive proving the previously-exposed content-shaped keys are gone, and replacing the COMMITTED provider schema files with that reviewed regeneration -- real production data plus an operator promotion decision. This cannot be satisfied or simulated with demo/synthetic data without violating the bead's own explicit instruction (\"Regenerate the affected provider schema from the live archive into staging... promote only after review\"). Same demo-vs-live-corpus tension as polylogue-1xc.14.1.3's AC #4. Left open.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-16T13:10:29Z","status":"open","title":"Prevent observed content from becoming schema property names","updated_at":"2026-07-27T04:37:39Z"} -{"_type":"issue","acceptance_criteria":"1. A corpus with one new rare family and one dominant family retains both, but default/recommended cannot select the rare family merely because it was observed later. 2. Latest, recommended, default, evidence-family, and promoted-version semantics are documented and represented without overloading one field. 3. Runtime exact-structure, bundle-scope, and profile resolution still reaches every retained family; no positive-value variant is discarded. 4. Live Claude Code regeneration reports all 55 observed families (or an evidence-equivalent representation) while choosing a defensible default with a machine-readable rationale. 5. Known-answer, shuffled-order, resolution mutation, promotion, and devtools verify --quick checks pass.","assignee":"Sinity","comment_count":0,"created_at":"2026-07-16T14:23:05Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T16:23:05Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.14.1","issue_id":"polylogue-1xc.14.1.3","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Full live Claude Code regeneration produced 55 coexisting profile-family packages and then selected the newest rare family (one scope, 45 samples) as latest, recommended, and default, while dominant families cover hundreds of scopes and up to 111,465 samples. The package registry intentionally retains evidence clusters for exact/profile resolution, but generation currently conflates evidence-family enumeration with release-version/default selection.","design":"Preserve every useful structural family and its exact/profile/scope resolution evidence. Make catalog roles explicit: evidence families may coexist; latest is temporal evidence, recommended is the best-supported compatible family (coverage-first with deterministic tie-breaks), and default resolves to recommended unless an explicit promoted release says otherwise. Do not collapse rare positive-value variants or silently delete evidence. If SchemaVersionPackage is the wrong abstraction, introduce a version containing family variants and migrate runtime resolution/promotion rather than papering over it. Promotion review must show family coverage, novelty, temporal windows, default rationale, and changed resolution outcomes.","id":"polylogue-1xc.14.1.3","issue_type":"bug","labels":["area:devtools","area:ops","area:perf","area:schema","area:sources","area:storage","area:test","area:verification","horizon:frontier"],"notes":"Warroom sweep It.17 (2026-07-18): claim orphaned -- the claiming session was closed 2026-07-17 and no matching commits exist on master since 2026-07-14. Reset to open; prior notes/receipts unchanged.\n2026-07-27 CLI-wiring audit (polylogue-a47769bba68869d49 session): traced the live devtools lab schema generate call chain end-to-end to check the open question of whether the correct _select_catalog_versions selection function is actually wired into the production entrypoint, or whether a stale/wrong latest-fallback path in tooling_registry.py is used instead.\n\nChain: devtools/schema_generate.py:main() -> polylogue/schemas/operator/workflow.py:infer_schema (re-export) -> polylogue/schemas/operator/inference.py:infer_schema() -> polylogue/schemas/generation/workflow.py:generate_provider_schema() -> polylogue/schemas/generation/provider_bundle.py:_build_provider_bundle() -> provider_bundle_packages.py:build_provider_catalog_artifacts() [line 218] -> _select_catalog_versions(catalog_packages) [line 269].\n\n_select_catalog_versions (provider_bundle_packages.py:74-103) does exactly what AC #1 requires: latest = temporally-last package; recommended/default = max(packages, key=_coverage_rank) where _coverage_rank = (bundle_scope_count, sample_count, last_seen, version) -- coverage-first, so a rare-but-newer family cannot win by recency alone. Confirmed by the existing known-answer test tests/unit/core/test_schema_generation.py::test_catalog_selection_preserves_latest_without_defaulting_to_rare_family (dominant v1: 943 scopes/28,602 samples vs rare-newer v2: 1 scope/45 samples -> latest==\"v2\", default==recommended==\"v1\").\n\nThe catalog.default_version or catalog.latest_version or catalog.recommended_version fallback chain at operator/inference.py:197 (inside list_inferred_corpus_specs) is a read-side defensive default for legacy/empty catalogs -- it is NOT on the generation write path and does not compete with _select_catalog_versions.\n\nConclusion: no fixable CLI-wiring bug exists. The mechanism is correctly implemented and unit-tested. This closes the open wiring-bug question definitively; no PR needed. Bead stays open because AC #4 (\"Live Claude Code regeneration reports all 55 observed families... while choosing a defensible default\") structurally requires a real live-archive regeneration + operator promotion review, which cannot be satisfied by demo/synthetic data -- same tension as polylogue-1xc.14.1.2's AC #4/#5.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-16T14:31:31Z","status":"open","title":"Separate schema evidence families from release-version defaults","updated_at":"2026-07-27T04:37:05Z"} -{"_type":"issue","acceptance_criteria":"1) `reset --database` leaves source.db intact by default (verify the tier-deletion set no longer includes source.db, or already excludes it). 2) A re-materialize-from-source path (CLI subcommand or reset flag) reconstructs index.db sessions from source.db raw rows without touching live source files \u2014 proven by a test that deletes the live source file, runs the path, and asserts the session is still present in index.db. 3) Explicit source.db deletion is blocked or double-confirmed when unresolvable raw rows exist, with the at-risk count reported. 4) `devtools test tests/unit/cli/test_reset*.py` (add coverage) passes.","assignee":"Sinity","close_reason":"Completed: reset --database now preserves source.db by default, generated CLI docs say source.db/user.db are preserved, --include-source-db is the explicit destructive opt-in, and the opt-in refuses when raw_sessions rows point at missing source paths. Focused reset/convergence/raw-materialization tests passed; devtools verify --quick passed run 20260704T214831Z-quick-1912311-8ad0c83a.","closed_at":"2026-07-04T21:48:59Z","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-04T20:29:38Z","id":"019f2ed2-8cf6-75d1-9a7e-501d703f362c","issue_id":"polylogue-1xc.2","text":"REALITY PASS (2026-07-04): the rebuild-index-from-source.db path already SHIPPED; residual scope narrowed to (a) source.db is still in the DEFAULT `reset --database` deletion set \u2014 remove it or gate it, and (b) the unresolvable-raw-row guard is missing. Close on those two, not the rebuild path."}],"created_at":"2026-07-04T19:34:53Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:52Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.2","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"PROBLEM (observed live, gh#2465 tier-1): `polylogue reset --database` deletes source.db (the durable acquired copy) alongside index.db, and the only repopulation path is re-acquisition from the live source FILES. There is NO rebuild-index-from-source.db path. Any session whose source file has since rotated, been deleted, or moved is permanently lost on reset. The prior 1690-file-loss incident (memory: project_claude_session_loss_2026_03_21) is the same failure shape.\n\nFILES: polylogue/cli/commands/reset.py \u2014 `_source_db_path()` (line ~55) resolves source.db; `_resolve_tier_files_to_delete` (line ~64) includes source.db in the `reset --database` deletion set (the docstring at lines 34/41 claims `--database` preserves source.db 'unless the operator opts in explicitly', so VERIFY the current deletion set first: if source.db is already preserved by default, this bead narrows to the missing rebuild-from-source path). The daemon/explicit-ingest paths materialize index.db from source.db raw rows already (see polylogue/operations/archive_debt.py raw-materialization surface and the convergence insights/materialization stages) \u2014 this bead exposes that as an operator-invocable recovery.\n\nDESIGN: (1) By default `reset --database` MUST NOT delete source.db (it is the durable acquired evidence; only index.db/embeddings.db are rebuildable-from-source). (2) After deleting index.db, re-materialize from the retained source.db raw rows (re-parse raw_sessions -> index sessions) instead of, or in addition to, re-acquiring from live files, so rows whose source file is gone are still recovered. (3) If the operator explicitly requests source.db deletion, GUARD it: refuse (or require an extra confirm flag) when raw_sessions rows exist whose recorded source path no longer resolves on disk, and print the count that would be unrecoverable. PITFALL: source schema v2 allows multiple raw observations per native id (docs/internals.md 'Source schema version 2') \u2014 the rebuild must coalesce to one canonical indexed session per native id, matching the daemon's own materialization, not naively insert duplicates.","id":"polylogue-1xc.2","issue_type":"bug","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T21:40:31Z","status":"closed","title":"reset --database must rebuild index from retained source.db, never lose rotated-source sessions","updated_at":"2026-07-04T21:48:59Z"} -{"_type":"issue","acceptance_criteria":"1) A new bounded, resumable convergence stage re-materializes orphan source.db raw rows into index.db, wired into `make_default_convergence_stages`. 2) After a daemon run, `polylogue ops diagnostics workload --json` `raw_materialization_readiness` reaches zero on an archive seeded with orphan raw rows (test: write raw_sessions rows with no index session, run drain, assert index sessions appear). 3) Stage is per-batch (paged, not fetchall) and per-session idempotent (re-run is a no-op). 4) Unparseable raw rows are marked/skipped, not retried forever. 5) `devtools test tests/unit/daemon/` covering the stage passes.","assignee":"Sinity","close_reason":"Completed/already satisfied with current code: daemon startup runs periodic raw-materialization convergence via _periodic_raw_materialization_convergence_after, _drain_raw_materialization_once calls repair_raw_materialization in bounded batches, actual repair tests prove raw replay/selection/force-write behavior, and daemon tests prove the loop waits for catch-up and retries on SQLite locks. Focused tests and devtools verify --quick passed.","closed_at":"2026-07-04T21:49:00Z","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-04T21:22:52Z","id":"019f2f03-460f-7372-8ba6-8cd9ab1ea812","issue_id":"polylogue-1xc.3","text":"AUDIT (automagic 2026-07-04): premise appears STALE. The daemon DOES auto-drain raw->index materialization via _periodic_raw_materialization_convergence_after, wired at daemon/cli.py:1038. The residual is only OVERSIZED non-stream-safe raw rows excluded by the blob-size execution cap (already tracked by 1xc.6/1xc.1). VERIFY the periodic drain covers all non-oversized cases; if so, close 1xc.3 as already-satisfied and let 1xc.6 own the oversized residual."}],"created_at":"2026-07-04T19:34:54Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:53Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.3","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"PROBLEM (observed live, gh#2465 tier-1): raw-materialization debt \u2014 a source.db raw_sessions row that is not explicitly skipped and has no matching index.db session \u2014 is SURFACED (polylogue/operations/archive_debt.py; daemon status `component_readiness.raw_materialization`) but never AUTO-DRAINED. The daemon is purely acquisition-driven: convergence stages (polylogue/daemon/convergence_stages.py `make_default_convergence_stages` = fts, embed, insights) run over sessions that ingest already wrote to index; nothing re-parses raw rows that ingest dropped or that predate a schema/index rebuild. So the debt count is a permanently non-zero readiness gap with no self-healing path.\n\nDESIGN: add a convergence stage (e.g. `make_raw_materialization_stage`) to the default set in convergence_stages.py that: (check) queries source.db.raw_sessions LEFT JOIN index.db.sessions for non-skipped raw rows with no index session (reuse the archive_debt query so debt-surface and drain-stage share one definition); (execute) force-reparses each orphan raw payload through the existing parse->write path and writes the index session, bounded per batch (do NOT fetchall all orphans \u2014 page them, mirroring the message-budget chunking discipline in rebuild.py). Set `false_means_pending=True` on the stage (see fts stage line ~248 / embed line ~309) so a partial drain is retried, not marked FAILED. PITFALL: coalesce multiple raw observations per native id to one canonical session (source schema v2). PITFALL: this stage must be idempotent \u2014 re-running on an already-materialized row is a no-op by content hash. PITFALL: guard against a poison raw row (unparseable) looping forever \u2014 record a skip/attempt marker so a permanently-bad row does not block drain progress.","id":"polylogue-1xc.3","issue_type":"bug","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T21:40:37Z","status":"closed","title":"Auto-drain raw-materialization debt: convergence stage re-parses orphan source.db raw rows","updated_at":"2026-07-04T21:49:00Z"} -{"_type":"issue","acceptance_criteria":"1) The insights ConvergenceStage sets `false_means_pending=True`. 2) A test simulates a partial rebuild (crash after K chunks) and asserts the stage is re-driven and eventually reaches full profile coverage across passes (not stuck FAILED). 3) The check predicate targets only sessions missing profiles so a resumed pass builds the tail, not the whole archive. 4) Cross-check parity with fts/embed stages' pending semantics. 5) `devtools test tests/unit/daemon/` covering resumability passes.","assignee":"Sinity","close_reason":"Completed: insights ConvergenceStage now sets false_means_pending=True, matching FTS/embed semantics, so bounded False results stay pending instead of failed. Tests cover the default stage flag, converger pending-state behavior, hot-session deferral, stale-session False returns, and quick verification passed run 20260704T214831Z-quick-1912311-8ad0c83a.","closed_at":"2026-07-04T21:49:00Z","comment_count":0,"created_at":"2026-07-04T19:34:55Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:54Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.4","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"PROBLEM (observed live, gh#2465 tier-1): a crash mid-rebuild left session_profiles at 395/16398. The insights ConvergenceStage (polylogue/daemon/convergence_stages.py `make_insights_stage`, ConvergenceStage constructed at line ~529) does NOT set `false_means_pending=True`, unlike the fts stage (line ~248) and embed stage (line ~309). Consequence: when the insights `execute` returns False / raises on a partial rebuild, the stage attempt is recorded FAILED rather than PENDING-retry, so the daemon does not re-drive it and the archive is stranded with partial profiles.\n\nDESIGN: (1) Add `false_means_pending=True` to the `ConvergenceStage(name=\"insights\", ...)` construction so a partial/failed rebuild is retried on the next convergence pass. (2) Verify the underlying `rebuild_session_insights_sync` is per-session idempotent and already commits per chunk (it is, post-#2466: per-chunk commit means a crash leaves the processed prefix durably fresh and the rest genuinely PENDING) so retry resumes from the unbuilt tail rather than redoing everything. (3) The check() predicate must count sessions MISSING insights (session_profiles absent for an index session) so a resumed pass targets exactly the unbuilt tail. PITFALL: `false_means_pending=True` only helps if execute() distinguishes 'more work remains' (return False -> pending) from 'hard error' \u2014 confirm the three execute variants (execute / execute_many / execute_sessions, lines ~348/418/484) return False for a bounded-partial pass and only raise on genuine corruption; a bare `return False` on any exception (current `logger.warning(... rebuild failed); return False`) will now correctly re-queue instead of dead-ending. PITFALL: ensure retry does not thrash \u2014 the drain should make forward progress each pass (per-chunk commit guarantees this).","id":"polylogue-1xc.4","issue_type":"bug","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T21:40:39Z","status":"closed","title":"Make insights convergence stage resumable and per-session idempotent on crash","updated_at":"2026-07-04T21:49:00Z"} -{"_type":"issue","acceptance_criteria":"1) A written audit note (issue comment or docs) enumerates each ObjectRef/global-PK builder in run_projection.py with a verdict: collision-safe or fixed. 2) run_ref (and any other unsafe builder) is changed to a scoped/composite key or main-preferred merge so two distinct runs never overwrite each other. 3) A regression test seeds a parent with two subagent runs whose stable_id would collapse (shared tool_id / index fallback) AND a subagent whose own session is ingested, then asserts both the main run and each subagent run survive materialization (row count matches distinct runs, no silent drop). 4) Rebuild determinism preserved: same input yields same keys across two rebuilds. 5) `devtools test tests/unit/insights/` covering run projection passes.","assignee":"Sinity","close_reason":"Completed: run-projection subagent run/report refs now include deterministic parent-list indexes, observed-event refs include an event-source namespace, successor-context report refs use the same scoped identity, and regressions prove duplicate shared-tool subagents plus an ingested child main run survive the OR-REPLACE materialization path. Verification: devtools test tests/unit/insights/test_transforms.py tests/unit/insights/test_run_projection_materialization.py -> 31 passed; devtools render all --check -> passed; devtools verify --quick -> passed run 20260704T220805Z-quick-1976132-a5305356; devtools test tests/unit/insights/ -> 302 passed.","closed_at":"2026-07-04T22:11:32Z","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-04T22:07:48Z","id":"019f2f2c-6be4-75e5-b061-019bcf6b566f","issue_id":"polylogue-1xc.5","text":"Audit verdict for run_projection ObjectRef/global-PK builders:\n\n- _run_ref(run_id): collision-safe for materialized session_runs main rows. It uses the canonical archive session_id as the run object_id; main runs are one-to-one with sessions, and session_id is already origin-scoped.\n- _subagent_run_ref(session_id, child_id, report, index): fixed. The old parent-scoped stable_id used report.tool_id or task_id or child_id and could collapse two distinct subagent report rows with a shared tool_id/task_id. It now includes the deterministic parent-list index before the stable id: :subagent::. This keeps rebuilds deterministic while making sibling reports distinct.\n- _agent_ref(harness, role_or_type): collision-safe by intent. This is a grouping identity for an agent role/type, not a session_runs/event/snapshot primary key.\n- _subagent_report_ref(session_id, report, index): fixed. It now uses the same deterministic index-scoped report identity as subagent runs, so context snapshot segment refs cannot collapse sibling reports with shared tool_id/task_id.\n- _context_snapshot_ref(run_id, boundary): collision-safe after run_ref is unique. Snapshot identity is scoped by run object_id plus boundary.\n- _event_ref(session_id, kind, index): fixed. Separate projection loops could previously emit the same :: even for different event sources. It now includes an event-source namespace (session/tool_summary/session_digest/subagent), so materialized session_observed_events do not silently overwrite across loops.\n\nThe sibling presentation ref in transforms._subagent_report_object_ref was updated to the same index-scoped identity so rendered successor-context bundles do not keep advertising the older ambiguous subagent-report id. Regression coverage now asserts deterministic rebuild keys, unique duplicate-subagent refs, unique cross-source observed-event refs, and the sync bulk materialization OR-REPLACE path preserving parent main + both parent subagent runs + the ingested child main run."}],"created_at":"2026-07-04T19:34:56Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:55Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.5","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"PROBLEM (gh#2465 tier-1, sibling of the #2464 fix): #2464 (`fix(insights): upsert run-projection rows on cross-session ref collisions`, commit 15f4f21b6) stopped a PK-collision CRASH by switching run-projection writes to INSERT OR REPLACE (polylogue/storage/insights/session/storage.py `build_insert_sql(..., or_replace=True)`, line ~189). But OR-REPLACE now SILENTLY OVERWRITES: when two distinct real run representations resolve to the same `run:` ObjectRef, last-writer-wins deletes one. Concretely, `_run_ref(session_id)` = ObjectRef(kind=run, object_id=session_id) (run_projection.py line ~382) for a session's main run, while a parent references a subagent via `_subagent_run_ref` = `run::subagent:` (line ~386, stable_id = report.tool_id or task_id or child_id or index). A subagent whose own session is also ingested, or two subagent reports whose stable_id collapses to the same fallback (e.g. both fall through to `str(index)` or a shared tool_id), can share a run_ref and one gets dropped.\n\nSCOPE (audit, not just this one site): hunt EVERY global PK / ObjectRef object_id built from LOCAL coordinates that are not globally unique. Grep the ref builders in run_projection.py: `_run_ref`, `_subagent_run_ref`, `_agent_ref`, `_subagent_report_ref`, `_context_snapshot_ref` (`run::`), `_event_ref` (`::`). For each, ask: can two semantically-distinct rows produce the same object_id at real scale (duplicate native ids, fork/resume replays, index-fallback stable_ids, hash prefixes)? The general class per the epic: 'code correct on small/clean/distinct-id fixtures but wrong on real-scale shape.'\n\nDESIGN: for run_ref specifically \u2014 either (a) make the key composite/scoped so distinct runs never collide (e.g. include the owning session_id in a subagent main-run ref, or key session_runs on (run_ref, session_id)), or (b) a deterministic MAIN-PREFERRED merge on collision instead of blind last-writer-wins (a real main run must never be clobbered by a subagent projection). For each other builder found unsafe, apply the same scope-or-merge fix. PITFALL: whatever key change you make must keep run rows deterministically reproducible across rebuilds (same input -> same key) so idempotent rebuild still holds. PITFALL: the fallback ladder `tool_id or task_id or child_id or str(index)` is the collision source \u2014 `str(index)` is only unique within one parent's report list, so it MUST be scoped by the parent session id.","id":"polylogue-1xc.5","issue_type":"task","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T22:02:26Z","status":"closed","title":"Audit global PKs derived from non-unique local coordinates; fix run_ref OR-REPLACE that drops a real run","updated_at":"2026-07-04T22:11:32Z"} -{"_type":"issue","acceptance_criteria":"1) A per-session size ceiling exists; sessions above it build in bounded/streamed/degraded mode with a peak-memory and wall-time cap, not one unbounded load. 2) A benchmark or test with one synthetic giant session (>= the ceiling) asserts build time / peak RSS stays under a bound (reuse devtools/ingest_throughput_probe.py or a bench synthetic fixture). 3) Degraded profiles are marked partial/incomplete honestly. 4) The existing `heavy_session_ids`/degraded path is confirmed to actually bound work (not a load-everything no-op). 5) `devtools bench` or `devtools test` evidence recorded.","assignee":"Sinity","close_reason":"Completed: sync and async session-insight rebuilds now route sessions over the per-session degraded thresholds through bounded counter-only profile builders instead of hydrating full message/block payloads. Tests guard both paths by monkeypatching load_sync_batch/load_async_batch to fail for over-threshold synthetic sessions, assert bounded_large_session/degraded markers, assert no work events/phases, and assert the bounded path completes under 2s. Verification: devtools test tests/unit/storage/test_session_insight_refresh.py (24 passed); devtools verify --quick (run 20260704T222514Z-quick-2013564-b3f22b40).","closed_at":"2026-07-04T22:25:42Z","comment_count":0,"created_at":"2026-07-04T19:34:57Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:56Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.6","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"PROBLEM (gh#2465 tier-2, but OBSERVED live): a 500-session insight batch took 9 minutes because a few sessions had enormous message counts; per-session insight build is unbounded in session size. The #2466 message-budget chunker bounds CROSS-session WAL/RSS by capping total messages per commit window, but it does not bound the cost of a SINGLE pathologically large session \u2014 one 100k-message session (or the 384MB Codex raw row noted in the epic) is still built as one unbounded unit.\n\nFILES: polylogue/storage/insights/session/rebuild.py \u2014 the per-session build path (`load_sync_batch` / the per-session insight compilation around lines ~484-586 and the heavy-session handling that already splits `heavy_session_ids` into degraded vs full ids at lines ~1340-1370). There is already a `heavy_session_ids` / degraded-mode concept \u2014 extend/verify it: the degraded path must actually CAP or STREAM per-session work (e.g. build insights over a bounded message window, or emit a degraded profile marked incomplete) rather than loading the whole giant session into memory. DESIGN: (1) define a per-session message/byte ceiling above which the session is built in degraded/streamed mode; (2) ensure the degraded profile is honestly marked (partial) so downstream reads know it is bounded, not silently truncated; (3) chunk within a session where the insight is decomposable (per-message/per-block accumulation) instead of materializing the full message list. PITFALL: verify the existing degraded path is not already a no-op that still loads everything \u2014 read `chunk_degraded_ids` handling before adding a second mechanism. PITFALL: a bounded profile must remain deterministic and idempotent across rebuilds.","id":"polylogue-1xc.6","issue_type":"bug","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-04T22:14:41Z","status":"closed","title":"Bound per-session insight build cost for giant sessions (9-min-batch pathology)","updated_at":"2026-07-04T22:25:42Z"} -{"_type":"issue","acceptance_criteria":"1) A `scale-regression` LaneEntry exists in the validation-lane catalog, appears in `devtools lab lanes --list`, and runs via `devtools lab lanes --lane scale-regression`. 2) The lane seeds a scale-shaped synthetic archive and asserts each tier-1 invariant (chunked rebuild / resumable insights / raw-debt drain / reset source.db preservation / run_ref no-drop / bounded giant-session build) \u2014 each assertion would FAIL against the pre-fix code for its bug class. 3) The lane is in the optional/scale tier, not the default per-PR gate, and completes under its declared timeout_s. 4) `devtools render quality-reference` (and `render all --check`) reflect the new lane with no drift. 5) Epic terminal check: with all sibling scale-hardening beads closed, this lane is green.","close_reason":"Completed: added the optional scale-regression validation lane and devtools workspace scale-regression probe. The lane seeds deterministic scale-shaped archives and asserts the shipped real-scale bug classes: chunked insight rebuild visibility, bounded giant-session insight build, reset preserving source/user durable tiers while deleting rebuildable tiers, run-ref no-drop materialization, raw-materialization debt detection, and resumable insights stage registration. Verification: focused devtools tests passed (3 selected); devtools workspace scale-regression passed with 6 checks; devtools lab lanes --lane scale-regression passed; devtools render all --check passed after regenerating agents/docs; devtools verify --quick passed run 20260704T224600Z-quick-2088171-b0da2b95.","closed_at":"2026-07-04T22:47:11Z","comment_count":0,"created_at":"2026-07-04T19:34:58Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T21:34:57Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.7","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-04T21:34:58Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.1","issue_id":"polylogue-1xc.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:34:59Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.2","issue_id":"polylogue-1xc.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:34:59Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.3","issue_id":"polylogue-1xc.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:35:00Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.4","issue_id":"polylogue-1xc.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:35:01Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.5","issue_id":"polylogue-1xc.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:35:02Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.6","issue_id":"polylogue-1xc.7","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":0,"design":"PROBLEM (this epic's terminal AC): the epic requires a scale-regression lane 'that would have caught each shipped bug class, wired into the optional lanes.' Today the synthetic corpus and benchmark fixtures are small/clean/distinct-id \u2014 exactly the shape that HID all five tier-1 bugs. The validation-lane registry (devtools/lane_models.py `LaneEntry`; catalogs in devtools/validation_lane_catalog_contracts.py CONTRACT_LANES and devtools/validation_lane_catalog_live.py LIVE_LANES; aggregated in devtools/validation_catalog.py ALL_VALIDATION_LANES; surfaced via `devtools lab lanes --lane `) has no scale/large-archive lane.\n\nDESIGN: (1) Build a seeded large-archive fixture generator that produces a REAL-SCALE-SHAPED archive cheaply: many sessions, at least one giant single session, fork/resume prefix-sharing lineages, duplicate native ids, and colliding-fallback subagent stable_ids. Reuse the synthetic corpus generator (polylogue/scenarios/corpus.py, `build_default_corpus_specs`, polylogue/schemas/synthetic.py `SyntheticCorpus.write_spec_artifacts`) and the existing scale-shaping in devtools/ingest_throughput_probe.py (`_build_fixture_files`, `_build_lineage_sessions`). Parameterize session count / message budget so the lane runs in CI-bounded time but is structurally > one rebuild message-budget window. (2) Add a `LaneEntry` (e.g. name='scale-regression' or 'large-archive-scale-probe', category matching existing optional lanes, appropriate timeout_s) to CONTRACT_LANES that executes a devtools probe asserting the invariants each tier-1 bug violated: rebuild commits per chunk (WAL bounded, no single-transaction), insights stage is resumable after a simulated partial, raw-materialization debt drains to zero, reset --database preserves source.db and recovers rotated-source sessions, run_ref/global-PK builders produce no silent drops (distinct-run count preserved), and per-session build stays under a cost bound for the giant session. (3) Wire it so it appears in `devtools lab lanes --list` and is runnable via `devtools lab lanes --lane `; keep it in the OPTIONAL/scale tier, not the default per-PR gate. FILES: devtools/validation_lane_catalog_contracts.py (add LaneEntry), the probe implementation under devtools/ (new module or extend an existing scale probe), and regenerate docs via `devtools render quality-reference`. PITFALL: `LaneEntry.__post_init__` validates assertion/lane consistency \u2014 supply a valid AssertionSpec or a composite delegation. PITFALL: keep the fixture deterministic and under the lane timeout; do NOT seed a literal 28GB archive \u2014 use the smallest shape that still triggers each bug class (multi-chunk message budget, one over-ceiling session, one id collision).","id":"polylogue-1xc.7","issue_type":"task","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":2,"status":"closed","title":"Add seeded large-archive scale-regression lane wired into the optional validation lanes","updated_at":"2026-07-04T22:47:11Z"} -{"_type":"issue","acceptance_criteria":"A rebuild-safety scenario resets a derived tier and rebuilds from source, asserting byte/row parity + no user.db loss; a durable additive migration round-trips behind the backup gate. Verify: the scenario under devtools lab lanes.","comment_count":0,"created_at":"2026-07-04T21:17:28Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:48:45Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.8","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T19:19:12Z","created_by":"Sinity","depends_on_id":"polylogue-b5l","issue_id":"polylogue-1xc.8","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"design":"scenario-coverage.yaml gap 'schema-rebuild-safety' orphaned on gh#590. A scenario proving derived-tier rebuild (index/embeddings) from durable source/user evidence is lossless and idempotent, and durable-tier additive migration preserves user.db assertions. Ties 1xc.7 scale-regression lane + z7rv migration framework.","id":"polylogue-1xc.8","issue_type":"task","labels":["area:audit","area:storage","delivery:B-storage-rebuild-bytes","horizon:frontier","lane:storage-rebuild-scale"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=B-storage-rebuild-bytes; lane=storage-rebuild-scale; readiness=B-local-inspection-needed; proof=large-corpus rebuild probe, blue-green generation swap proof, WAL/resource envelope report. Original readiness=B-local-inspection-needed.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/089_polylogue_1xc_8.md (depth: anchored-contract-prework; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n2026-07-15 hierarchy repair: rebuild-safety is the proof slice of the derived-tier transition protocol b5l. Scale-hardening 1xc remains related and supplies corpus/resource conditions, but no longer counts the same scenario as a second child.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Schema rebuild-safety scenario","updated_at":"2026-07-15T18:48:46Z"} -{"_type":"issue","acceptance_criteria":"1) make_insights_stage sets false_means_pending=True and passes the 1xc.4 resumability test. 2) docs/internals.md documents insights as a convergence invariant peer to fts/embed with identical resumability/idempotency guarantees and states the three reasons it is NOT inlined into the write transaction (WAL/lock isolation, hot-churn batching, materializer-version rebuild). 3) No new manual-only insight maintenance CLI surface is introduced. Verify: devtools test tests/unit/daemon (insights stage tests) + devtools render all --check.","assignee":"Sinity","close_reason":"Completed in feature/fix/insight-convergence-1xc: make_insights_stage already has false_means_pending=True with daemon regression coverage, docs/internals.md now frames insights as an automatic FTS/embed peer invariant and explains why rebuild stays outside ingest transactions; no manual-only maintenance surface added. Verified by two-file focused test, render all --check, and devtools verify --quick.","closed_at":"2026-07-04T21:59:15Z","comment_count":0,"created_at":"2026-07-04T21:22:48Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-04T23:22:48Z","created_by":"Sinity","depends_on_id":"polylogue-1xc","issue_id":"polylogue-1xc.9","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"design":"The operator's audit conclusion: the insights ConvergenceStage should read as one of three automatic derived-model invariants (fts, embed, insights) that the daemon enforces, never a manual/optional step. Today make_insights_stage lacks false_means_pending=True (unlike fts@248/embed@309), so a partial rebuild is stranded FAILED (observed 395/16398 live). This bead is the umbrella that sequences 1xc.4 (resumability), 1xc.1 (regression proof), 1xc.6 (giant-session bound), and a docs pass: docs/internals.md should describe insights refresh as an automagic convergence invariant with the same guarantees as FTS coherence, and remove any framing that suggests it is optional operator maintenance. Do NOT fold per-session build into commit_archive_write_effects - preserve WAL-chunked, hot-quiet-window, materializer-version-rebuildable behavior. Files: polylogue/daemon/convergence_stages.py (make_insights_stage), docs/internals.md.","id":"polylogue-1xc.9","issue_type":"task","labels":["area:storage"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T21:53:04Z","status":"closed","title":"Reframe insights as a first-class convergence invariant (peer of fts/embed), not a bolt-on stage","updated_at":"2026-07-04T21:59:15Z"} -{"_type":"issue","acceptance_criteria":"The xfail test (test_hermes_state_db_single_session_full_ingest_crashes)\npasses without xfail: a state.db (or verification_evidence.db) with exactly\none session ingests successfully through the real live watcher, reaching at\nleast INDEXED_UNCONVERGED in project_named_source_freshness. No regression in\nthe existing multi-session test in the same file. Historical repair's use of\nparse_retained_raw_sessions for a single-session SQLite raw revision is\ncovered by a focused test, not just the live-ingestion path.","close_reason":"Fixed and merged to master as c2d3f94f9 (PR #3113): magic-bytes SQLite detection in _parse_one + real blob path threading, bounded temp-file spill fallback. xfail removed, regression test passes for real.","closed_at":"2026-07-18T17:20:32Z","comment_count":0,"created_at":"2026-07-18T15:48:02Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Distinct from polylogue-flxh (which is about ATOF's shared multi-session\nJSONL file). This one affects state.db and verification_evidence.db: any\nsuch file with EXACTLY ONE session at ingest time crashes the live daemon\nwatcher's full-ingest path with UnicodeDecodeError.\n\nRoot cause: revision_backfill.py's _parse_one (shared by \"historical repair\nand the live full and append routes\" per its own docstring) has zero SQLite\nawareness -- it unconditionally calls _iter_json_stream/json.loads on the raw\npayload bytes. This is reached via live/batch.py's\n_ingest_full_records_archive -> the single-session branch (`if len(sessions)\n== 1:` at ~line 1755) -> when this logical_source_key has never been seen\nbefore and is not a browser-capture snapshot, it falls to the \"else\" branch\n(~line 1794) which calls classify_raw_revision_cohort then\n_parse_raw_revision_chain(archive, plan) -> _parse_retained_raw_sessions ->\nparse_retained_raw_sessions -> _parse_one, which crashes trying to\njson-decode raw SQLite bytes (confirmed: \"UnicodeDecodeError: 'utf-8' codec\ncan't decode byte 0x8d in position 98: invalid start byte\").\n\nTwo OTHER call sites in the SAME file (live/batch.py lines ~1697-1711, and\nthe equivalent branch in live/append_ingest.py) correctly check\nhermes_state.looks_like_state_db_path /\nhermes_verification.looks_like_verification_evidence_db_path before falling\nback to generic JSON parsing -- _parse_one in revision_backfill.py is the one\ncall site that never got this treatment.\n\nCONFIRMED empirically via the real LiveBatchProcessor\n(tests/unit/sources/test_hermes_source_freshness_integration.py::\ntest_hermes_state_db_single_session_full_ingest_crashes, xfail(strict=True)\npending this bead's fix). A state.db with TWO OR MORE sessions does NOT hit\nthis bug (routes through the working membership-census branch instead,\nproven by the adjacent\ntest_hermes_state_db_multi_session_source_reaches_indexed_through_named_freshness\ntest in the same file, which passes cleanly) -- this is presumably why\nPhase 0 review (PR #3084, merged) did not catch it: real Hermes installs\nalmost always have many sessions by the time they're tested. A brand-new\nHermes install (first-ever session), or any minimal single-session test\nfixture, hits this every time.","design":"Fix belongs in revision_backfill.py's _parse_one (or its caller\nparse_retained_raw_sessions), which currently only receives\n(provider, payload: bytes, source_path: str) -- no access to a real\nfilesystem path the SQLite parsers need (hermes_state.parse_state_db /\nhermes_verification.parse_verification_evidence_db both open via\nsqlite3.connect on a real file path, not in-memory bytes).\n\nTwo candidate approaches:\n1. Detect the SQLite case (payload magic bytes \"SQLite format 3\\0\", or\n reuse hermes_state.looks_like_state_db_payload-equivalent bytes sniffing)\n and write the payload to a bounded temp file before calling the SQLite\n parsers, mirroring what live/batch.py's working branches do via\n blob_store.blob_path(blob_hash) (a real file already on disk -- prefer\n threading that path through instead of a redundant temp-file copy where\n the caller already has blob store access).\n2. Give parse_retained_raw_sessions/_parse_one blob-store access so they can\n resolve to the same blob_store.blob_path(blob_hash) real file path the\n two working call sites already use, rather than reading payload bytes\n eagerly -- more invasive (this function's docstring explicitly says it\n deliberately avoids eager loads for stream providers to prevent\n accidental read_all()), but likely the more correct fix long-term since\n it also removes a second, currently-benign asymmetry (SQLite sources are\n always eager-loaded here even though they're never small).\n\nMust not regress historical repair, which shares this same function per its\nown docstring -- whatever fix lands needs a repair-path test too, not only\nthe live-watcher path.","id":"polylogue-1zex","issue_type":"bug","labels":["area:daemon","area:ingest","area:substrate","lane:origin-interop-export"],"notes":"2026-07-18 IMPLEMENTED (Claude Sonnet, branch feature/fix/hermes-atof-remaining-gaps, commit 6baccdd8d, pushed): hybrid fix per the Fable-adjudicated design. sqlite_snapshot.looks_like_sqlite_bytes (new, shared magic-byte sniffer) + ArchiveStore.blob_path_for_hash (new public method, checks file existence before trusting the path) + _parse_one now detects SQLite payloads and routes to hermes_state.parse_state_db/hermes_verification.parse_verification_evidence_db using the real blob path when materialized, falling back to a bounded temp-file spill (archive_root-scoped, matching the existing _ParsedSessionSpill precedent) only when no real path exists. xfail removed from the live-watcher regression test (now passes for real); added a verification_evidence.db single-session sibling; added two new revision_backfill-level tests proving both the temp-spill fallback (_parse_one called directly with no payload_path) and the real historical-repair entry point (backfill_historical_revision_evidence end-to-end). 14/14 test_revision_backfill.py, 125 total across the affected file sweep (124 passed + 1 unrelated xfail for the still-open flxh bug). devtools verify --quick green. Not yet merged -- PR not opened yet, more Hermes fixes landing on the same branch first per the follow-up mission (flxh next).\n2026-07-18: MERGED to master as c2d3f94f9 (PR #3113).","owner":"ezo.dev@gmail.com","priority":1,"status":"closed","title":"Hermes single-session state.db/verification_evidence.db crashes live-watcher full ingest","updated_at":"2026-07-18T17:20:32Z"} -{"_type":"issue","acceptance_criteria":"- The 20d.14 interactive SLO tier is defined in docs/plans/slo-catalog.yaml and runs green in `devtools bench slo` against the seeded corpus with a live daemon.\n- On the operator machine, live measurement meets the daemon-served query, completion round-trip, cold-CLI, and ingest-to-searchable budgets named in 20d.14.\n- No interactive read verb pays the old cold-import or FTS-gate penalties: the 20d.2 help-latency budget check and the 20d.4 structured-routing regression gate are in place and green.\n- The evidence the epic cites (2s imports, 5-9s helps, 43s regen, 0.2 files/s ingest) is retired \u2014 each has an owning child whose acceptance names its budget.","comment_count":0,"created_at":"2026-07-03T04:31:59Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:48:47Z","created_by":"Sinity","depends_on_id":"polylogue-d22s","issue_id":"polylogue-20d","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T20:48:41Z","created_by":"Sinity","depends_on_id":"polylogue-ovme","issue_id":"polylogue-20d","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Cold CLI invocations pay ~2s of Python imports; some helps took 5-9s; find-then-select cold spikes; claim-vs-evidence regen 43s; ingest catch-up crawled at 0.2 files/s. WAL checkpoint + ANALYZE done (2026-07-03: index.db WAL=0, sqlite_stat1 present, v23). The CLI->daemon fast path is the structural attack; import deferral is the fallback for daemonless cold starts.","design":"Front-door interactive-latency spine. Mechanism ordering: 20d.14 states the named budgets first (evidence-tuned starting points); 20d.2 removes the ~2s import tax for the daemonless cold path; 20d.1 routes the hot path through the daemon over UDS; 20d.12 makes the daemon worth reaching (cursor-keyed result cache); 20d.13 replaces polling with SSE push; 20d.6/20d.15 own the live vs bulk ingest lanes; 20d.4/20d.5/20d.7/20d.8/20d.10/20d.11 are the direct-path and storage-profile fixes that keep the degraded mode fast. The epic's done-state ties to the 20d.14 budgets so 'interactive time' is a measured claim, not a vibe.","id":"polylogue-20d","issue_type":"epic","labels":["area:perf","delivery:G-live-performance","horizon:frontier","lane:interactive-performance"],"metadata":{"frontier_program":"active"},"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/142_polylogue_20d.md (depth: epic-checklist; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-15 mandate audit] Elevated from P4 to P1. Interactive performance is a correctness boundary for an agent archive: correct model-facing queries hung for 60-120 seconds and one incident consumed 8.5 GiB RAM plus 6.8 GiB swap. The epic must cover server responsiveness, cancellation, and resource ceilings as well as nominal latency; polylogue-z9gh.1/.2 carry the stop-the-line incident work.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Interactive performance: the front door answers in interactive time","updated_at":"2026-07-15T19:23:14Z"} -{"_type":"issue","acceptance_criteria":"- Fast-path read surface: `--verbose` prints `served-by: daemon (uds, )` and a warm daemon serves find/read/messages/facets within the 20d.14 interactive-tier budget (target 3.6-17s -> 0.3-0.5s wall). Verify: timed CLI run against a warm daemon; `devtools bench slo` interactive tier green.\n- Golden parity: `--format json` output is byte-identical between direct and daemon-proxied execution for every read surface on the demo corpus. Verify: pytest golden-parity test.\n- Config-mismatch safety (NON-NEGOTIABLE): with the daemon pointed at a different archive_root/index_schema_version/daemon_version than the client's resolved config, the client silently falls back to the in-process path. Verify: regression test seeding the POLYLOGUE_ARCHIVE_ROOT=/tmp mismatch trap.\n- Escape hatches: `--no-daemon` and `POLYLOGUE_DAEMON=off` force the direct path; a daemon-down probe fails in microseconds (test).\n- Writes never proxy: user.db operations always take the direct path (test/assertion).","comment_count":0,"created_at":"2026-07-03T04:31:59Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:31:59Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.1","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":2,"description":"Route CLI queries through the already-hot daemon when available: skips import cost, warm SQLite page cache, shared readiness state. Silent in-process fallback.","design":"Precedent: fast-status path (commands/status.py:950, click_app.py:214-221) already prefers the daemon \u2014 extend the pattern to the whole read surface. Transport: UDS at $XDG_RUNTIME_DIR/polylogue/daemon.sock (TCP stays for the browser); AF_UNIX HTTPServer subclass ~20 lines; instant-fail when down. Probe: socket exists -> connect (fails in microseconds) -> GET /api/health with 100ms budget; health payload carries {archive_root, index_schema_version, daemon_version, commit, started_at}; client compares against its own resolved config and silently falls back on mismatch \u2014 NON-NEGOTIABLE (live trap: POLYLOGUE_ARCHIVE_ROOT from .claude/settings.json pointed at /tmp while the real archive sat elsewhere). Thin client: new cli/daemon_client.py over stdlib http.client \u2014 no httpx, no payload models, no storage imports; send the RAW query string + flags (daemon owns compilation, which also delivers the #1860 structured-routing behavior the CLI lacks \u2014 the fast path fixes that bug for free); --format json renders via sys.stdout.write; table/plain imports only formatting helpers that render from payload dicts. Target: 3.6-17s -> 0.3-0.5s. Endpoints: REUSE /api/sessions, /api/query-units, /api/facets, /api/sessions/:id/read?view=, :id/messages; one new POST /api/cli/query accepting the root-request param dict (cli/root_request.py output) for the gaps so CLI flags never drift from the HTTP surface. Writes stay direct (user.db is a separate WAL, no contention); proxy reads only. Load isolation exists (the client-disconnect probe http.py:118-190 cancels server-side SQLite work on Ctrl-C); add a modest concurrent-read semaphore only if agent fan-out appears. Correctness: golden parity tests \u2014 byte-identical --format json between direct and proxied execution per read surface on the demo corpus. Escape hatches: --no-daemon, POLYLOGUE_DAEMON=off, --verbose prints 'served-by: daemon (uds, 41ms)'. Sequencing: subsumes the ~2s import tax, the cold-I/O tail, and the routing-parity bug; the direct path still needs the routing-parity + cached-stale-verdict fixes, but they shrink from 'the UX' to 'the degraded mode'.","id":"polylogue-20d.1","issue_type":"feature","labels":["area:daemon","area:perf","delivery:G-live-performance","horizon:frontier","lane:interactive-performance","spine","wave:2"],"notes":"PROTOCOL PRIOR-ART (2026-07-06 DR corpus): JSON-RPC 2.0 as the frame (transport-agnostic, id correlation, notifications, batch); gopls -remote=auto pattern (auto-start daemon on connect, Unix socket, idle listen timeout); watchman/emacs deterministic per-user socket discovery + autostart-on-connect; bazel idle-shutdown knobs + per-workspace daemon identity; LSP-style CANCELLATION by request id for keystroke-driven complete/preview (superseded requests cancellable, not merely ignored client-side). Method families converged across three independent designs: hello (protocol version + archive fingerprint + capabilities + state), query.create/get/run/preview/complete/explain, cohort.save_dynamic/snapshot, assertions.import, evidence.pack, analysis.start/finish, context.compile.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/097_polylogue_20d_1.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nLANE STATUS 2026-07-13 (missing from prior durable state): the hot-daemon lane landed UDS groundwork commits on feature/fanout/hot-daemon, including cb77b9de9 session-page proxying; 37t.8 resume routing had already merged. Still outstanding: POST /api/cli/query, full read/facet/unit proxying, --no-daemon and environment escape, golden parity and config-mismatch regression coverage, jnj.13 bare-TTY triage, adversarial pass, and PR. Branch is pushed; resume the preserved lane to finish this list.\nSLICE 1 MERGED 2026-07-13: PR #2827 squashed as 3082c72f0 (+ review fix 1fbf0c439: daemon unit fast path now defers session-only flag validation to the local UsageError path \u2014 Codex P2, regression-tested). Landed: UDS transport at XDG_RUNTIME_DIR/polylogue/daemon.sock with health identity + auth forwarding + archive/schema/version mismatch fallback; --no-daemon / POLYLOGUE_NO_DAEMON=1 / POLYLOGUE_DAEMON=off escapes; daemon-backed session pages, facets, terminal query units; bare-TTY triage (jnj.13); resume routing (37t.8). REMAINING for this bead: direct read/message VIEW proxying (read --view transcript|messages), seeded direct-vs-proxied golden JSON parity suite (non-negotiable AC), timing/SLO evidence on the live archive post-deploy, POST /api/cli/query envelope for complex expressions.\n[2026-07-14] PR #2874 (branch feature/perf/interactive-slo-fast-path): added the real end-to-end golden-parity test the prior landing (#2827) deferred \u2014 tests/unit/cli/test_daemon_golden_parity.py starts a production UDS daemon server against a seeded archive and diffs direct-vs-proxied JSON. This found and fixed two genuine parity bugs in the already-merged fast path: (1) daemon/http.py::_archive_summary_payload hardcoded repo/cwd_display to None regardless of the session's real fields; (2) archive_query.py passed the daemon's /api/sessions wire shape straight through instead of normalizing to the CLI's native SessionListRowPayload shape (word_count vs words, extra session_id/date/flags fields) \u2014 added _normalize_daemon_list_item. Golden parity now holds for find (list mode) + facets. NOT done: read/messages/other views still direct-only (query_verbs.py::read_verb has no daemon proxy at all) \u2014 tracked as polylogue-fko9, which also carries a triage item for a DSL-token-vs-root-option rendering-shape divergence found but not chased. Bead stays open pending that follow-up + merge.\nPriority correction 2026-07-15: promoted P3 to P2 during invariant review. The bead covers a current single-writer, resource-containment, durable-lifecycle, verification-gate, or interactive-latency contract with concrete evidence; promotion does not automatically admit it to the active execution set.\n2026-07-16 GPT-Pro corpus adjudication: session snapshot 6a4ac7f7-f0b4-83eb-941d-7428e03f4834 is research input for daemon/fast-client paths. Retain daemon-owned query, complete, preview and status separation with provenance; no special scratchpad domain. The snapshot is now explicitly routed rather than stranded.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"CLI->daemon fast path over UDS (persistent hot process)","updated_at":"2026-07-16T12:57:38Z"} -{"_type":"issue","acceptance_criteria":"1. Minimal fix: semantic facts are memoized per session within a single filter pass (no more than one build_session_semantic_facts per session per pass), eliminating the up-to-3x construction across matches_action_sequence / matches_referenced_path / category matching (runtime_matching.py, runtime_filters.py). 2. Real fix: the three matchers' predicates (action category, affected path, sequence) are answered from actions-view rows fetched once per candidate set with a single `WHERE session_id IN (...)` query, grouped in Python; candidates failing cheap predicates are dropped before hydration, and cheap structured clauses are pushed into SQL before hydration. 3. The keystone columns (index v16) and idx_blocks_type_tool (v20) are used for these predicates. Verify: instrumentation on a broad SEQ or referenced_path query shows fact builds reduced to <=1 per candidate and hydration limited to predicate-surviving candidates (before/after in the PR); `devtools test` selection on runtime_matching/runtime_filters asserts memoization and that filter results match the pre-change path.","close_reason":"Superseded by polylogue-z9gh.2, which owns selective action/path/sequence lowering and rejects memoization-only preservation of post-hydration filtering.","closed_at":"2026-07-15T19:43:10Z","comment_count":0,"created_at":"2026-07-03T05:06:50Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T07:06:50Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.10","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"description":"matches_action_sequence, matches_referenced_path, and category matching each call _actions_for(session) -> build_session_semantic_facts (runtime_matching.py:20-25) \u2014 full semantic-fact construction over a hydrated session, no memoization across the three matchers, applied as list-comprehension post-filter (runtime_filters.py:188-189). A broad query with SEQ or referenced_path hydrates every SQL-surviving candidate and builds facts up to 3x.","design":"Minimal fix: memoize facts per session within a filter pass (functools cache keyed per pass, or attach _semantic_facts to the Session object). Real fix: all three matchers' predicates (action category, affected path, sequence) are answerable from actions-view rows \u2014 fetch once per candidate set with a single WHERE session_id IN (...) query, group in Python, drop hydration entirely for candidates failing cheap predicates. The keystone columns (v16) and idx_blocks_type_tool (v20) exist for exactly this shape. Also push cheap structured clauses into SQL before hydration. SEQ span capture (DSL bead) builds on the same relation \u2014 coordinate.","id":"polylogue-20d.10","issue_type":"task","labels":["area:perf","area:query","delivery:G-live-performance","lane:live-substrate"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=live-substrate; readiness=A-implementation-ready; proof=live-ingest fixture, event materialization proof, status/liveness report. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/098_polylogue_20d_10.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Runtime post-filter efficiency: memoize semantic facts; lower matchers onto the actions view","updated_at":"2026-07-15T19:43:10Z"} -{"_type":"issue","acceptance_criteria":"`polylogue-20d.11` declares a before/after measurement, an acceptable resource envelope, and a regression guard. The implementation fails loudly on stale/partial state and records phase timing where relevant. Verification artifact: named SLO report, daemon hot-path benchmark, push/cache invalidation tests.","comment_count":0,"created_at":"2026-07-03T05:06:51Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T07:06:50Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.11","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Readers get 32MiB cache / 128MiB mmap (connection_profile.py:84-87) against a 23GB index \u2014 mmap covers 0.5%. mmap'd pages are file-backed and shared across processes; RSS accounting stays honest and the OS page cache does eviction.","design":"Raise READ_MMAP_SIZE_BYTES to 2-4GiB; simultaneously LOWER cache_size on the read profile (SQLite's page cache double-buffers what mmap already maps). Verify with devtools bench memory before/after \u2014 expect wins concentrated in index-heavy scans (group-bys, facets). Measured change, not a blind bump; keep the daemon write profiles untouched.","id":"polylogue-20d.11","issue_type":"task","labels":["area:perf","area:storage","delivery:G-live-performance","delivery:ac-patched","lane:interactive-performance"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=D-horizon-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=E-spec-needed.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Read-profile mmap tuning: raise READ_MMAP, lower double-buffering cache","updated_at":"2026-07-07T12:59:35Z"} -{"_type":"issue","acceptance_criteria":"bench slo (interactive tier): cached facets/status p50 <30ms on the seeded corpus with warm daemon. Cache entries invalidate within one ingest batch of a cursor move (test: ingest a session, facets reflect it next request). /metrics exposes cache hit/miss/size; memory stays under the configured cap under a 10k-query soak.","comment_count":0,"created_at":"2026-07-03T13:27:08Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T15:27:08Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.12","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-04T21:31:24Z","created_by":"Sinity","depends_on_id":"polylogue-20d.1","issue_id":"polylogue-20d.12","metadata":"{}","type":"blocks"}],"dependency_count":1,"dependent_count":2,"description":"The fast path (20d.1) makes the daemon reachable in milliseconds; this bead makes the daemon WORTH reaching: today every facets/status/aggregate request recomputes from SQLite (live evidence: /api/facets defers repos+action_types by default, was stuck 'loading... stale' for minutes during convergence; bare status re-probes the DB per invocation). A hot daemon should answer the common 80% from memory: facets, status snapshot, recent-session lists, saved-view results, common aggregates \u2014 computed once per archive change, not once per request.","design":"(1) CACHE KEY: the archive ingest cursor (ops.db already tracks it) + query fingerprint. A cached entry is valid until the cursor moves \u2014 no TTL guessing, no staleness lies; the convergence snapshot (4bu) rides the same key. (2) WRITE-TRIGGERED RECOMPUTE: after each ingest batch commits, the daemon refreshes the hot set in its idle loop (facets complete families INCLUDING the deferred ones, status snapshot, newest-sessions page, saved views marked hot) \u2014 the webui then never waits on facets; it reads the precomputed payload. (3) COLD-START WARMING: after startup/rebuild/reset, a warming pass touches hot indexes and precomputes the hot set before first request (measured: first-query-after-rebuild pays cold page cache today); mmap profile (20d.11) compounds. (4) MEMORY BUDGET: hard cap (config, default ~64MB) with LRU eviction; /metrics exposes cache hit/miss/size so effectiveness is measurable, and the SLO lane asserts hit-rate on the seeded corpus. (5) SCOPE HONESTY: this is an in-daemon memo layer over the same SQL, NOT a second materialization tier \u2014 rows still come from index.db; eviction or restart costs latency, never correctness. Serve stale-while-revalidating only with the stale flag the payload already carries. Sequence: lands with/after 20d.1 so CLI + webui + MCP all hit the same cache.","id":"polylogue-20d.12","issue_type":"feature","labels":["area:daemon","area:perf","delivery:G-live-performance","lane:interactive-performance","spine"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/092_polylogue_20d_12.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nDESIGN FALLS OUT 2026-07-13: rxdo.3 (merged #2813 lineage) gives the cache key for free \u2014 result-relation identity = (query_hash, archive_epoch, fingerprint). A daemon result cache keyed on (query_hash, archive_epoch) with fingerprint validation IS the provenance design; invalidation = epoch advance. Do not invent a second key scheme.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Daemon result cache + post-ingest warming: precomputed answers, cursor-keyed invalidation","updated_at":"2026-07-13T04:01:30Z"} -{"_type":"issue","acceptance_criteria":"1. Every advertised SSE topic has a declared EventSpec and production emitter, or is removed; tests-only producers cannot satisfy completeness. 2. Session/message events carry exact session/message/source/archive refs and post-commit cursor/frame; opening session A is unaffected by an event for session B. 3. session.updated and retained insight/progress topics fire from real mutation/convergence routes with evidence-backed identity. 4. At-least-once duplicate and Last-Event-ID replay are idempotent; a ring gap yields an explicit resync cursor/ref rather than silent loss. 5. Subscriber cap, loopback/auth/privacy policy, bounded payloads, and slow-consumer isolation remain enforced. 6. A real ingest-to-browser fixture fails if producer identity is removed, an event is emitted before commit, or a tests-only emitter substitutes for production wiring.","comment_count":0,"created_at":"2026-07-03T13:27:10Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T15:27:09Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.13","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-04T21:31:47Z","created_by":"Sinity","depends_on_id":"polylogue-bby.11","issue_id":"polylogue-20d.13","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":3,"description":"SSE transport and browser consumers already exist, but producer semantics are incomplete. Live ingest emits aggregate, unscoped session.appended/message.appended events; session.updated has no production emitter; insight/progress producers are tests-only. An unscoped message event currently refreshes whichever session a browser has open, so the live channel can imply change to the wrong object. This is an evidence-identity defect, not a missing UI feature.","design":"Keep the existing SSE transport, bounded replay ring, reconnect, and subscriber controls. Define EventSpec entries for each public topic with stable event id, object/source/archive refs, cursor/frame, producer transaction phase, payload projection, authorization/privacy, and real producer inventory. Publish only post-commit through the phased write-effect/event path; events carry refs/deltas, not full archive payloads. Browser and CLI consumers invalidate/fetch only matching objects/scopes. Remove topics with no production semantics or wire their actual insight/progress producers. Delivery remains at-least-once; consumers deduplicate by event id/cursor and recover gaps through bounded query/ref continuation.","id":"polylogue-20d.13","issue_type":"feature","labels":["area:daemon","area:perf","area:web","delivery:G-live-performance","horizon:frontier","lane:interactive-performance","spine"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/093_polylogue_20d_13.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n2026-07-15 wiring-closure audit (polylogue-9e5.31): SSE transport and browser consumers now exist, so the description is stale at the transport layer. Producer closure remains partial: live ingest emits aggregate, unscoped session.appended + message.appended; session.updated has no emitter; emit_insight_updated, emit_progress_update, and emit_progress_complete are tests-only. The browser subscribes to all six topics, and an unscoped message.appended refreshes whichever session is open for every successful ingest. Remaining implementation should prove per-session/per-source identity and real insight/progress producers with an ingest-to-browser anti-vacuity route.\nPriority correction 2026-07-15: promoted P3 to P2. The transport is shipped; the residual can refresh the wrong open session and advertises events without real producers, so this is current identity/correctness work rather than later push polish.\n[2026-07-27 PR #3361] feature/daemon/sse-session-identity implements the core identity-scoping fix this bead's description calls out, but does not close the full bead scope. AC matrix:\n\n1. \"Every topic has EventSpec + emitter, or is removed\" \u2014 PARTIAL. session.appended/session.updated/message.appended now have real production emitters with real session_id/source_name (previously session.appended/message.appended were aggregate-only with session_id=None; session.updated had no emitter at all). insight.updated/progress.update/progress.complete removed outright: grepped the whole repo, zero production callers existed for emit_insight_updated/emit_progress_update/emit_progress_complete (only their own unit tests), and the docstring's claimed CLI consumer (`status --convergence --watch`) does not exist in code. NOT done: no formal per-topic EventSpec registry (ids, refs, cursor/frame, phase, authorization contract) -- structural addition beyond this PR.\n2. \"Session/message events carry exact refs; session A unaffected by session B event\" \u2014 SATISFIED for the identity defect literally named in the description: message.appended/session.appended/session.updated now carry the real session_id, and the browser's existing (previously dead) `if (convId && convId !== selectedId) return;` guard in web_shell_realtime.py now actually fires. Verified via unit tests (test_daemon_events_endpoint.py::TestLiveBatchEventFanOut, test_live_watcher.py::test_live_ingest_metrics_carry_real_session_identity) with anti-vacuity (reverted the session_ids_by_path wiring, confirmed the test fails, restored it).\n3. \"session.updated + retained insight/progress fire from real routes\" \u2014 session.updated: SATISFIED (new emit_session_updated, fired from the append-ingest route, which only ever grows an already-tracked file). insight/progress: topics REMOVED rather than wired (the AC's own alternative clause), since wiring a real producer would mean wiring an entirely separate, currently-unwired subsystem (storage/embeddings/progress.py's embed-catchup-run tracker has zero callers anywhere either) -- out of scope for this pass.\n4. \"At-least-once dedup + Last-Event-ID replay idempotent; ring gap -> explicit resync\" \u2014 UNTOUCHED. Pre-existing transport behavior (bounded replay ring, Last-Event-ID, query_events_since) from earlier 20d.13 wiring-closure work; not re-verified or extended by this PR.\n5. \"Subscriber cap, privacy/auth, bounded payloads, slow-consumer isolation\" \u2014 UNTOUCHED, pre-existing (events_http.py).\n6. \"Real ingest-to-browser fixture fails if identity removed / event before commit / tests-only substitutes\" \u2014 PARTIAL. Unit-level anti-vacuity fixtures exist (see #2) proving the identity threading is real production wiring, not a mock. No full ingest-to-browser (actual SSE-over-HTTP + JS client) integration fixture was added.\n\nKnown documented limitation (not silently claimed solved): new-vs-updated session classification uses the ingestion ROUTE (full-parse vs append) as a proxy for new-vs-existing session identity -- correct for the common case, but a full reparse of an ALREADY-EXISTING session id (e.g. a rewritten/replaced file) would still surface as session.appended rather than session.updated. Multi-session bundle raws (browser-capture, ChatGPT exports) get correct per-session identity but no per-session message-count split.\n\nLeaving open rather than closing: AC #1 (formal EventSpec), #4 (ring-gap resync fixture), and #6 (full ingest-to-browser fixture) are real, non-trivial remaining scope this PR does not cover.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Complete identity-scoped SSE producer semantics","updated_at":"2026-07-27T21:11:26Z"} -{"_type":"issue","acceptance_criteria":"1. One checked interactive SLO catalog names daemon query, health/completion, cached status/facets, web first-paint, cold CLI, and ingest-to-searchable budgets with workload/build scope. 2. Seeded live-daemon benchmarks enforce portable required rows and cannot pass when the measured production route is bypassed. 3. polylogue-jtwu emits bounded per-route histogram and CLI-span WorkloadReceipts into the disposable telemetry tier and provides p50/p95 analysis with missing-data honesty. 4. Every performance sibling cites a named row and no hidden timeout/row cap substitutes for meeting it. 5. Live operator-machine observations distinguish warm/cold, daemon/direct, peak/quiescent, and unavailable measurements; focused benchmarks, telemetry tests, catalog validation, and quick verification pass.","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-15T04:27:04Z","id":"019f6407-3c25-7012-8a1b-fe3ceeab21a7","issue_id":"polylogue-20d.14","text":"[Dogfood 2026-07-15 / F-002] polylogued status emitted no result inside 15 seconds. Decomposition measured storage 11 ms, FTS 4 ms, insight freshness 4 ms, raw materialization 1.1 s, raw frontier 1.45 s, cursor lag 2.75 s, and detailed replay or embedding debt beyond 4 s. New child polylogue-20d.17 owns component snapshots, deadlines, and status semantics; this SLO bead remains the shared measurement contract."}],"created_at":"2026-07-03T13:27:13Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T20:45:47Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.14","issue_id":"polylogue-20d.14","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-03T15:27:12Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.14","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T06:25:27Z","created_by":"Sinity","depends_on_id":"polylogue-20d.17","issue_id":"polylogue-20d.14","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":2,"description":"Interactive latency is a correctness boundary for an agent-facing archive. The named SLO catalog and seeded live-daemon benchmarks are now present, but continuous live telemetry and self-analysis are still incomplete. This epic owns one latency contract from declared budgets through benchmark enforcement and production observation; individual performance mechanisms consume it rather than inventing targets.","design":"Keep docs/plans/slo-catalog.yaml as the single budget declaration and 1xc.14 WorkloadReceipts as the common physical measurement envelope. Seeded live-daemon benchmarks gate portable regression budgets. The remaining child polylogue-jtwu instruments bounded per-route histograms, CLI invocation spans, and an honest latency projection over ops-tier telemetry. Sibling fast-path/cache/push/ingest beads cite named SLO rows and emit comparable receipts. Host-dependent live values are observations with build/archive/workload scope, never unconditional CI truth. Exceeding a physical budget triggers diagnosis, paging/queueing/streaming or mechanism repair, never a semantic result cap.","id":"polylogue-20d.14","issue_type":"epic","labels":["area:audit","area:perf","delivery:G-live-performance","horizon:frontier","lane:interactive-performance","spine"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/091_polylogue_20d_14.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-14] PR #2874 (branch feature/perf/interactive-slo-fast-path): interactive tier added to docs/plans/slo-catalog.yaml (daemon_cli_query p50<100/p95<400ms, daemon_health_probe p50<30/p95<100ms, both required+backed by new tests/benchmarks/test_daemon_uds.py against a live UDS daemon; daemon_cached_facets + ingest_to_searchable informational placeholders citing 20d.12/20d.6/20d.13). `devtools bench slo` runs green. NOT done: live telemetry leg (/metrics per-route histograms, CLI spans in ops.db, polylogue analyze latency projection) \u2014 tracked as polylogue-jtwu. Bead stays open pending that follow-up + merge.\nPriority correction 2026-07-15: promoted P3 to P2 and admitted. After multi-minute queries and multi-GiB growth, named interactive budgets and continuous regression evidence are current product requirements, not later polish.\nTractability correction 2026-07-15: the SLO catalog and seeded daemon benchmark core are already present on master. Converted this into the contract epic and transferred active execution to the sole remaining live-telemetry child jtwu.","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Enforce interactive latency as a measured product contract","updated_at":"2026-07-15T19:27:25Z"} -{"_type":"issue","acceptance_criteria":"Full replay of a live-archive copy sustains >=100 raw rows/s whole-run on the operator machine and finishes <5 min; rebuild prints live rows/s and ETA. Ingest RSS stays under the stated cap; bench ingest-amplification shows no per-tier regression; desktop remains responsive during a rebuild (idle IO class verified).","comment_count":0,"created_at":"2026-07-03T13:50:06Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T15:50:05Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.15","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-04T21:31:25Z","created_by":"Sinity","depends_on_id":"polylogue-20d.14","issue_id":"polylogue-20d.15","metadata":"{}","type":"blocks"},{"created_at":"2026-07-04T21:31:26Z","created_by":"Sinity","depends_on_id":"polylogue-20d.6","issue_id":"polylogue-20d.15","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T19:19:19Z","created_by":"Sinity","depends_on_id":"polylogue-b5l","issue_id":"polylogue-20d.15","metadata":"{}","type":"relates-to"}],"dependency_count":1,"dependent_count":1,"description":"Live evidence 2026-07-03: the full index rebuild replayed 16,725 raw rows at 12-15 rows/s whole-run (5/s when it hit big sessions) \u2014 20-40 minutes of archive downtime for an operation the fresh-first doctrine treats as routine. Nobody has stated the machine impact budget either: daemon RSS during bulk ingest, write amplification per tier, page-cache pressure, and IO contention with the live desktop are unmeasured-in-anger even though the instruments exist (live_ingest_attempt RSS fields, bench ingest-amplification, bench ingest-throughput). 20d.6 owns the LIVE catch-up lane (single-session ingest-to-searchable); this bead owns the BULK lane: replays, resets, backfills.","design":"(1) MEASURE first on a live-archive copy: where do the 12-15 rows/s go (parse vs store vs FTS vs insights \u2014 the attempt rows record stage timings); bench ingest-throughput gives the synthetic baseline. (2) PARALLEL PARSE: parsing is CPU-bound JSON; pipeline/services/process_pool.py already provides the safe pool (spawn-context) \u2014 fan out parse across N workers, keep the store single-writer (SQLite reality); the parallel-parse dogfood branch from 2026-06-29 is prior art to consult. Expect the write leg to become the bottleneck: batch multi-session transactions (amortize fsync; measure against WAL autocheckpoint interplay per 20d.6), suspend per-row FTS in favor of the existing bulk trigger-drop path, defer insight materialization to a second pass (the daemon already stages fts/embed/insights separately \u2014 make bulk replay exploit it). Target: >=100 rows/s whole-run on the operator machine, rebuild <5 min \u2014 stated in the SLO catalog as a maintenance-tier budget (20d.14). (3) RESOURCE ENVELOPE: cap ingest RSS (bounded batch size + streaming lowering already exists for multi-GiB files \u2014 verify it holds in bulk mode); write amplification per tier via bench ingest-amplification before/after; IO: run bulk lanes with ionice-idle/self-throttle so a rebuild never makes the desktop stutter (the daemon can set its own IO class; do not rely on the operator remembering systemd slices). (4) REPORT: rebuild prints rows/s + ETA continuously (the devloop agent hand-computed ETA from logs today \u2014 the daemon should just say it; feeds the 4bu convergence snapshot).","id":"polylogue-20d.15","issue_type":"task","labels":["area:daemon","area:ops","area:perf","delivery:G-live-performance","lane:interactive-performance","size:M","spine"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/090_polylogue_20d_15.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Bulk ingest throughput + resource envelope: parallel parse, batched writes, bounded RSS/IO","updated_at":"2026-07-08T20:15:13Z"} -{"_type":"issue","acceptance_criteria":"polylogue lab perf (or devtools equivalent) runs the family and diffs against baseline; one seeded regression (sleep injection) is caught; baselines refreshed with rationale in the same PR that changes them. Verify: two consecutive runs stable within noise band.","closed_at":"2026-07-16T09:46:05Z","comment_count":0,"created_at":"2026-07-04T21:17:26Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-16T11:46:05Z","created_by":"Sinity","depends_on_id":"polylogue-1xc.14.1","issue_id":"polylogue-20d.16","metadata":"{}","type":"supersedes"},{"created_at":"2026-07-04T23:17:26Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.16","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"design":"Scenario family for perf/throughput regression: seed archives at three scales (demo-size, 10%-of-live sample shape, live-shape synthetic) via scenarios/ + corpus_seeded_db infra; measured flows = ingest batch, rebuild-index, hot find query set, read --all of largest session, convergence catch-up. Emit per-flow wall/RSS to a committed baseline file; regression = >X% over baseline on same machine class. Ties: 20d.8 (claim-vs-evidence 43s regen) and 20d.11 (mmap tuning) become measured flows instead of anecdotes.","id":"polylogue-20d.16","issue_type":"task","labels":["area:audit","area:perf","delivery:G-live-performance","horizon:mid","lane:interactive-performance"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=D-horizon-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=D-horizon-ready.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Performance/throughput scenario family","updated_at":"2026-07-16T09:46:05Z"} -{"_type":"issue","acceptance_criteria":"1. Daemon/archive and coordination status both consume the same component-snapshot protocol; no request path synchronously rebuilds the rich whole. 2. A stalled raw/debt/embedding/Beads/archive/handoff component cannot delay healthy components and returns its explicit state, age, last-good evidence, deadline, and detail ref. 3. polylogued status returns within the interactive live-scale budget; warm compact coordination MCP p95 improves at least 3x from the measured baseline and cold compact CLI materially improves while preserving the 8 KiB projection bound and omission counts. 4. Randomized cold CLI and warm in-process MCP sampling records per-component timing, p50/p95, archive state, git head, fingerprints, cache decisions, and raw artifact refs; product budgets are set from those distributions. 5. Refresh invalidation follows declared source fingerprints or events; a changed Beads/archive/process source cannot be hidden by an unexpired TTL, while unavailable sources remain explicit. 6. Exact expensive diagnostics are opt-in, bounded, cancellable, and resumable; limit constrains collection work rather than only rendered rows. 7. Compact/detail payload semantics, process collapse, resource exclusions, archive readiness, and handoff evidence remain correct. Production stall and stale-source mutations fail the tests; live dogfood artifacts cover daemon and coordination consumers; focused status tests, SLO benchmark, and quick gate pass.","assignee":"Sinity","comment_count":0,"created_at":"2026-07-15T04:23:42Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T06:23:42Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.17","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T06:25:27Z","created_by":"Sinity","depends_on_id":"polylogue-20d.14","issue_id":"polylogue-20d.17","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T20:27:07Z","created_by":"Sinity","depends_on_id":"polylogue-703","issue_id":"polylogue-20d.17","metadata":"{}","type":"supersedes"},{"created_at":"2026-07-15T20:17:32Z","created_by":"Sinity","depends_on_id":"polylogue-cuxz","issue_id":"polylogue-20d.17","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-15T06:25:30Z","created_by":"Sinity","depends_on_id":"polylogue-s7ae.8","issue_id":"polylogue-20d.17","metadata":"{}","type":"relates-to"}],"dependency_count":0,"dependent_count":0,"description":"Live dogfood found polylogued status produced no result within 15 seconds although daemon heartbeat and database descriptors were healthy. Coordination status independently measured 2.6 to 16.6 second compact/detail reads. Both synchronously combine millisecond facts with multi-second raw, debt, embedding, Beads, process, archive, and handoff probes, so output byte bounds do not make status interactive. A cached snapshot exists in places, but whole-payload refresh, TTL-only reuse, and missing source fingerprints allow one expensive or stale component to dominate every answer.","design":"Define one StatusComponentSpec and StatusSnapshot protocol reused by daemon/archive and agent-coordination status. Each component declares collector, dependencies, cost/detail class, deadline, refresh trigger or source fingerprint, staleness policy, privacy, and projection fields. An off-request scheduler refreshes components independently, retains last-good evidence, and records fresh, stale, refreshing, timed_out, unavailable, and degraded with observed/start/finish timestamps and evidence refs. CLI, MCP, HTTP, and coordination envelopes select compact or detail projections from snapshots and never run expensive collectors inline. Exact replay, embedding, debt, Beads, archive-family, or handoff expansion is an explicit resumable detail query. Stage timing and request telemetry measure the protocol itself; cache reuse is keyed by declared evidence changes, not TTL alone.","id":"polylogue-20d.17","issue_type":"bug","labels":["area:daemon","area:ops","area:perf","delivery:G-live-performance","horizon:frontier","lane:interactive-performance"],"notes":"Invariant collapse 2026-07-15: absorbs s7ae.8. Its shipped stage harness/cache groundwork and remaining randomized sampling, source-keyed invalidation, p95 budget, and live dogfood become a second consumer proof of the same component snapshot mechanism.\n2026-07-15 portfolio convergence: absorbs polylogue-703. Its one-assembly requirement is the shared StatusComponentSpec/StatusSnapshot substrate here; daemon/status, CLI status, workload diagnostics, MCP, HTTP, and coordination are consumers. The stronger contract retains 703's cross-surface fact parity and adds per-component cost, freshness, deadline, last-good, invalidation, and resumable-detail semantics.\n[2026-07-15 installed-skill dogfood reproduction] MCP readiness_check synchronously assembled 23 checks into 27,673 bytes, then lost the payload at the 25 KiB boundary. The envelope said ok=true while its summary contained one error, raw materialization_ready=false with join_gap_count=23,427, and raw_frontier_integrity state=blocked. Status snapshots must make overall/degraded semantics consistent, keep the compact projection below budget before serialization, and expose exact component/detail refs instead of a whole-report retry.\n[2026-07-18 Lane F PR 1/2-3] PR #3107 (branch feature/perf/snappy-surfaces): shared\nStatusComponentSpec/StatusComponentRegistry protocol (polylogue/operations/status_protocol.py)\n+ daemon/archive status cutover. build_daemon_status() collects its ~14 facts\nthrough a fresh per-call registry (independent deadline per component, explicit\nfresh/stale/refreshing/timed_out/unavailable/degraded states, last-good evidence\nretained). daemon_status_payload()'s previously-unbounded archive_debt call is now\nbounded the same way. polylogued status asks the running daemon's /api/status first\n(honouring POLYLOGUE_DAEMON_URL, matching the archive CLI's existing #1325 pattern),\nfalling back to the now-bounded direct path only when no daemon answers.\n\nLive-archive read-only measurement (provisional, archive mid-restore from the\n2026-07-18 incident): polylogued status + live daemon >60s timeout -> 2.2-2.4s\n(daemon's fresh cached snapshot, age_s<1); polylogued status + no daemon (direct\npath) >90s timeout -> ~8.5s bounded/deterministic with raw_materialization/\nembeddings correctly timing out while search/archive_storage stay fresh. Anti-\nvacuity test added (stalled collector times out without delaying a healthy sibling\n-- fails on the pre-PR synchronous chain).\n\nAC status: #1 (shared protocol, daemon consumer) satisfied for daemon/archive status;\ncoordination status consumer is the next PR. #2 (stalled component isolation) satisfied\nand proven by the anti-vacuity test + live measurement above. #3 (polylogued status\nreturns within budget) satisfied for the daemon-reachable case (2.2-2.4s, mostly cold-\nimport tax); the no-daemon direct path is bounded but not yet \"interactive\" (~8.5s) --\ntightening deadlines from measured distributions is explicitly 20d.14's job, not\ninvented here. #4 (randomized sampling + p50/p95 product budgets), #5 (coordination\nconsumer + full fingerprint-driven invalidation across all sources), #6 (resumable\ndetail-query semantics for embedding/Beads/handoff expansion) remain open, deferred to\nthe coordination-status PR and 20d.14 per the lane's PR1/PR2/PR3 cadence. #7 (payload\ncorrectness preserved) verified via the full existing test_daemon_status.py suite (55\ntests unchanged in assertions, all green) plus mypy --strict and devtools verify --quick.\n\nDeferred, named explicitly (not silently dropped): persistent daemon-lifetime registry\nwith real cross-tick staleness reuse (this PR uses a fresh ephemeral per-call registry,\ncorrect for build_daemon_status()'s existing pure-recompute contract used by ~50\nparameterized tests, but doesn't give the daemon's own periodic refresh loop cross-tick\ncaching beyond what it already had); explicit dependency-graph declarations between\ncomponents (a few facts still combine via cheap pure post-processing after independent\ncollection).\n[2026-07-18 Lane F PR 2/3] PR #3116 (branch feature/perf/coordination-status-cache):\nbounds build_coordination_envelope's archive_evidence stage (session trees, activity\nepisodes, subagent exchanges, proof refs, context-flow refs -- one unbounded SQLite\nread) to a 3s deadline via the shared StatusComponentRegistry protocol from PR #3107,\nwith an explicit degraded fallback surfaced in advisories. Live measurement: ~10s\nunbounded -> capped at 3s; polylogue agents status CLI ~11s+ -> ~5.1s.\n\nAlso adds CoordinationEnvelopeCache (StatusComponentRegistry-backed, fingerprint-\ninvalidated on git HEAD/logs, .beads/issues.jsonl, active index db/WAL mtimes) as\nready substrate for a warm-cached coordination-status consumer -- NOT wired to any\nlive surface in this PR.\n\nMajor scope-narrowing discovery mid-implementation: the MCP agent_coordination tool\n(polylogue/mcp/server_tools.py, register_read_tools) is dead code -- register_tools()\n(live server wiring) only calls the six-tool cutover surface\n(server_cutover.py:register_cutover_read_tools/register_cutover_privileged_tools),\nconfirmed by tracing the call graph. Its dedicated test file was already deleted by\nthe six-tool cutover (#3095) with no replacement coverage. The live, reachable path\nis status(scope=\"coordination\") in server_cutover.py, which has its OWN pre-existing\nbug: every scope value except \"operation\" falls through to archive.stats(), so\nscope=\"coordination\" silently returns archive stats, never coordination data. Filed\npolylogue-qink for wiring CoordinationEnvelopeCache into that handler + deciding\nregister_read_tools/agent_coordination's fate -- deliberately NOT attempted in PR2\nsince it's deep in another lane's actively in-flight six-tool cutover\n(feature/mcp/retire-legacy-registrars) and risks collision.\n\nAC status update: #5 (fingerprint invalidation) substrate exists (CoordinationEnvelopeCache)\nbut is unwired pending qink. #2/#7 for coordination's dominant real cost (archive_evidence)\nsatisfied and measured. Remaining coordination AC gaps (randomized sampling, full stage\nDAG atomization beyond archive_evidence, live dogfood artifact, MCP p95 budget) still\nopen, same as before -- now additionally blocked on qink for the MCP consumer specifically.\n[2026-07-18 evening, Lane F PR 3/N] PR #3128 (branch feature/perf/snappy-surfaces, same branch as PR #3107/#3116): wires status(scope=\"coordination\") on the live six-tool MCP surface to CoordinationEnvelopeCache/build_coordination_envelope (was silently falling through to archive.stats() -- filed + tracked as polylogue-qink, closing that bead on merge). This is the first LIVE MCP consumer of PR #3116's CoordinationEnvelopeCache substrate -- AC #5 (fingerprint invalidation) now has a real consumer to validate against, though full source-fingerprint coverage beyond archive_evidence/git-HEAD/beads/index-WAL is still unaudited.\n\nAlso investigated the CLI cold-start slice (polylogue-8s70) as a possible cheap PR 3: re-attempted readiness/__init__.py + readiness/capability.py TYPE_CHECKING-only deferral of storage.repair's ArchiveDebtStatus import. Measured zero wall-clock change (before/after: ~1.7s both, 3 runs each) via python -X importtime -- root cause is that polylogue/insights/archive.py ALSO imports storage.repair at module level, reached independently via cli/shared/helper_summary.py, so closing one edge does not remove the redundant one. Reverted (no benefit), evidence recorded on 8s70 for a future dedicated pass; NOT attempted as part of this lane per the lane prompt's own guidance not to sweep lazy-imports across the package for an unmeasured win.\n\nRemaining AC gaps unchanged from PR #3116's note: #4 (randomized sampling + p50/p95 product budgets), #6 (resumable detail-query semantics for embedding/Beads/handoff expansion), live dogfood artifact. These are substantial standalone increments -- recommend a fresh session/PR per item rather than folding into this branch further.\n[2026-07-18/19 evening, Lane F PR 5/N] PR #3140 (86ca3287, same branch as PRs #3128/#3131): closes AC #4 substantively for the surfaces that matter to this bead (CLI status + MCP status(scope=coordination)), via polylogue-jtwu's new route_observation substrate (see jtwu's own note for full design/scope-decision detail -- not duplicated here).\n\nConcretely: status(scope=\"coordination\") MCP calls and `polylogue status`/`polylogue agents ` CLI invocations now record real timing + component-level detail (archive_evidence_degraded flag from the coordination envelope's own advisories; daemon-reachable vs direct-fallback for CLI status) into a new bounded route_observations ops-tier table. `polylogue analyze latency` reads it back with real p50/p95, low-confidence-flagged under 5 samples. A new pytest-benchmark (tests/benchmarks/test_cli_cold_start.py) backs a real informational cli_status_cold SLO row in docs/plans/slo-catalog.yaml with a MEASURED number (p50 ~1.80s cold subprocess, 5 rounds) -- this is the \"product budgets are set from those distributions\" clause of AC #4, satisfied with a real runnable benchmark rather than a hand-typed guess.\n\nAC #4 status: \"randomized... sampling records per-component timing\" -- satisfied via real production call sites (not a synthetic sampler) for the two surfaces this bead cares about (status CLI/MCP); \"p50/p95... archive state, git head, fingerprints, cache decisions, raw artifact refs\" -- timing/status/attributes/git_head columns exist and are populated (git_head only wired for the coordination CLI path currently, not yet MCP -- small residual gap); \"product budgets are set from those distributions\" -- satisfied for cli_status_cold specifically. NOT extended to daemon-internal/HTTP status paths (jtwu's note explains why: Lane E's daemon/http.py territory this cycle).\n\nThis closes out this lane's planned work on polylogue-20d.17 for this session. Remaining AC gaps (per PR #3116/#3131's earlier notes, still open): full fingerprint-driven invalidation audit beyond coordination/archive_evidence, resumable detail-query semantics for embedding/Beads/handoff specifically (only archive_evidence got this in PR #3131), live dogfood artifact. Recommend a fresh session for those, or folding embedding/Beads resumability into jtwu's own remaining-scope list since it's the same underlying pattern (persistent StatusComponentRegistry per expensive sub-stage) proven out on archive_evidence.\n\n2026-07-26 portfolio-convergence audit: released stale in_progress claim after >7 days with no recorded activity; scope remains open and must be re-claimed on real work start.\n[2026-07-28 fingerprint-invalidation audit + embedding resumability] PR #3377\n(branch feature/perf/daemon-status-embedding-resumability) closes the\n\"embedding\" leg of the remaining resumable-detail-query scope, plus a full\nfingerprint audit of every status component beyond coordination/archive_evidence.\n\nLive measurement against the real archive (/realm/db/polylogue): embedding_readiness_info\ntakes ~5.06s standalone while build_daemon_status's declared deadline_s for it\nis 2.0s. The daemon's periodic status-snapshot refresh\n(_periodic_status_snapshot_refresh, daemon/cli.py, 10s cadence for the process\nlifetime) called daemon_status_payload -> build_daemon_status, which built a\nbrand-new EPHEMERAL StatusComponentRegistry every tick -- the exact\npre-#3131 archive_evidence pathology, on the daemon status side: a component\nslower than its own deadline timed out and was discarded every single tick,\nforever, never converging, plus leaking one orphaned collector thread per\ntick (a timed-out attempt cannot be cancelled). None of build_daemon_status's\n~14 components had a fingerprint either -- AC #5 gap confirmed real here too.\n\nFix: extracted the inline StatusComponentSpec list into\n_daemon_status_component_specs() shared by the existing ephemeral per-call\npath (build_daemon_status(registry=None), unchanged, all pre-existing tests\npass) and a new periodic_status_component_registry() -- one process-wide\npersistent registry, lazily built, with a real fingerprint\n(_daemon_status_fingerprint: index db + ops db + their -wal mtimes) so a\nchanged archive/ops source forces a refresh inside the ttl_s window.\nrefresh_status_snapshot's periodic call now threads this registry through\ndaemon_status_payload(registry=...).\n\nAnti-vacuity: new test\ntest_periodic_status_component_registry_resumes_slow_embedding_readiness_across_ticks\nproves the collector runs exactly once across 3 ticks (timed_out ->\nrefreshing -> fresh); confirmed it fails both when the registry-reuse check\nis reverted (duplicated attempt) and when refresh_status_snapshot stops\nthreading registry= through. New test\ntest_periodic_status_component_registry_fingerprint_forces_refresh proves a\nchanged index db forces a refresh inside ttl_s. Live dogfood (read-only,\n/realm/db/polylogue): tick 0 times out at 2.0s, ticks 1-2 (0.2s apart)\nobserve refreshing without re-invoking the collector, tick after ~8s total\nreturns fresh with real embedding_coverage_percent=44.1. Artifact:\n.local/coordination/20d17-embedding-resumability-dogfood.json (untracked).\ndevtools test tests/unit/daemon/test_daemon_status.py -- 63 passed. mypy\n--strict clean. devtools verify --quick exit 0.\n\nInvestigated and found NOT to need this treatment (false alarm, same\nmethodology as polylogue-dhjz's investigation): coordination/envelope.py's\n\"beads\" and \"handoff\" sub-stages, and daemon/status.py's archive_debt/\nassertion_candidate_queue ephemeral registries.\n- beads: 3 subprocess bd probes already bounded via REAL subprocess-timeout\n cancellation (0.35s each, run concurrently via ThreadPoolExecutor) -- a\n fundamentally different (and better) contract than archive_evidence's\n unbounded blocking-SQL problem, which is WHY archive_evidence specifically\n needed a background-thread StatusComponentRegistry in the first place.\n Applying that same pattern to beads would add complexity without fixing a\n measured problem.\n- handoff: a cheap filesystem glob (.agent/scratch/*handoff*.md) + a\n LIMIT-bounded SQLite query with a 0.2s connect timeout -- not expensive.\n- archive_debt / assertion_candidate_queue (daemon/status.py): both build a\n fresh ephemeral StatusComponentRegistry per call too, same shape as the\n embedding_readiness bug -- BUT verified by grepping every call site\n (daemon_status_payload(include_archive_debt=True) only from\n daemon/cli.py's status_command no-daemon CLI fallback and\n cli/shared/check_workflow.py's `polylogue check` command) that both are\n ONLY ever reached from one-shot CLI processes, never a persistent loop\n (the live daemon's /api/status route reads the cached _SNAPSHOT via\n get_status_snapshot_payload(), never calling these with\n include_archive_debt=True per-request). No cross-call state exists for a\n persistent registry to preserve there -- the ephemeral pattern is correct,\n matching build_daemon_status's own documented pure-recompute contract.\n\nRemaining AC gaps after this PR: #4's git_head column for the MCP\ncoordination path (jtwu's small residual gap, unrelated to this PR); any\nfurther daemon-side \"expensive\"/\"moderate\" component beyond embedding_readiness\nthat might independently exceed its deadline on a still-larger archive (not\nmeasured to be a live problem for the others at this archive's current scale\n-- fts_readiness/insight_freshness/raw_materialization/raw_failures/\nblob_publication_reservations/health all now share the SAME persistent\nregistry + fingerprint mechanism via periodic_status_component_registry(),\nso they get the resumability fix \"for free\" even though only\nembedding_readiness was independently confirmed to exceed its deadline via\nlive measurement this session).","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-18T14:26:44Z","status":"in_progress","title":"Serve every status surface from budgeted component snapshots","updated_at":"2026-07-28T17:57:00Z"} -{"_type":"issue","acceptance_criteria":"- `python -X importtime -c 'from polylogue.cli.click_app import main'` shows surfaces/payloads and api/archive no longer imported on the `polylogue --help` path. Verify: importtime diff before/after.\n- A new devtools help-latency budget check runs targeted `polylogue --help` invocations under a fixed budget (e.g. <700ms cold, citing the 20d.14 cold-CLI budget) and fails loudly on drift.\n- Nested helps (import / reset / maintenance archive-read / analyze tools) drop from the observed 5-9s to under the budget. Verify: measured before/after under the new budget check.","close_reason":"AC fully satisfied as of PR #2902 (merged dfe52af4f): all 13 required devtools bench help-latency targets green, including ops-maintenance and ops-maintenance-archive-read (the AC's own named nested-help targets), both now ~288ms (down from the original 5-9s evidence this bead cited). importtime diff artifact exists and is reproducible (python -X importtime -m polylogue.cli ops maintenance archive-read --help shows zero occurrences of the heavy storage/insights stack). The devtools bench help-latency regression gate (added in PR #2874) is fixed and enforced. One documented exception outside this AC's named scope: ops maintenance migrate-tier stays informational/over-budget for a separate, deeper architectural reason (archive_tiers package __init__.py eager DDL imports) -- tracked separately, not part of this bead's closure.","closed_at":"2026-07-14T17:04:57Z","comment_count":0,"created_at":"2026-07-03T04:32:00Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:00Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.2","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"description":"~2s import tax per invocation; also the residual cold cost when the daemon path is absent. Candidates: surfaces/payloads (~2,915 lines of Pydantic model construction), api/archive. Measure first: python -X importtime -c 'from polylogue.cli.click_app import main'. Covers the old help-latency and find-select-cold items; add the help-latency devtools budget check as the regression gate.","design":"Measure first: python -X importtime -c 'from polylogue.cli.click_app import main' 2>&1 | sort -t'|' -k2 -rn | head -30. Known heavy candidates: surfaces/payloads (~2,915 lines of Pydantic model construction), api/archive, storage imports pulled at command-module import time. Mechanics: the repo already uses lazy Click commands (see bd memory: lazy cmds hide flags \u2014 use cmd.get_params(ctx) in tests); push heavy imports inside command bodies / module __getattr__; keep a leaf path-resolution module import-light for the daemon fast-path handshake. Regression gate: a devtools help-latency budget check (targeted `polylogue --help` under a fixed budget) so drift fails loudly. Prior evidence: nested help 5-9s (import/reset/maintenance archive-read/analyze tools); warm find-select ~1.7s vs cold spikes.","id":"polylogue-20d.2","issue_type":"task","labels":["area:cli","area:perf","delivery:G-live-performance","lane:interactive-performance","wave:2"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/096_polylogue_20d_2.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nPR #2809 (live-performance-2) merged: additional partial progress \u2014 reset help import deferral measured, warm nested help ~1.18s -> ~0.30s. DEFERRED (not closing): importtime diff artifact, fixed help-latency gate, and maintenance/archive-read nested-help work remain incomplete.\nPR #2816 merged: coordination archive-state probe groundwork landed. Remaining AC gaps still open per lane report: importtime diff artifact, fixed help-latency gate, maintenance/archive-read nested-help sweep.\n[2026-07-14] PR #2874 (branch feature/perf/interactive-slo-fast-path): re-measured current state \u2014 most nested helps already fast (~0.28-0.35s) thanks to prior PR #2809/#2827 work; found and fixed one remaining outlier, `polylogue config --help` (1.16s -> 0.29s), caused by config.py eagerly importing completions.py (pulls insights/storage stack, ~650ms) just to register 3 subcommands \u2014 fixed via _LazyCommand proxies. Added `devtools bench help-latency` regression gate (11 required targets, all green). Remaining known outlier: `ops maintenance` command group (~1.6-1.9s, 2789-line module, ~30 heavy top-level imports) \u2014 kept informational in the gate, tracked as polylogue-sod7 rather than risking a rushed refactor. Bead stays open pending that follow-up + merge.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Defer heavy imports off the CLI startup path","updated_at":"2026-07-14T17:04:57Z"} -{"_type":"issue","assignee":"Sinity","close_reason":"Completed: search readiness now returns trusted recorded FTS readiness verdicts, including cached stale verdicts, before any exact recount. Added sync/async trace regressions proving stale rows do not query blocks or messages_fts_docsize; py_compile/ruff focused checks passed; focused FTS tests passed; live archive v23 ledger shows messages_fts ready at 5,705,798/5,705,798 and POLYLOGUE_ARCHIVE_ROOT=/home/sinity/.local/share/polylogue polylogue --plain find hermes --limit 3 completed in ~3.05s with 1,184 bytes of bounded output.","closed_at":"2026-07-03T06:39:31Z","comment_count":0,"created_at":"2026-07-03T04:32:01Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:00Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.3","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"v23 added fts_freshness_state + the text-populated partial index after `find hermes` refused with 'Search index is incomplete' despite healthy FTS. Verify on the live archive: (a) find works; (b) readiness hot path reads the ledger row, no recount scan; (c) triggers maintain source_rows/indexed_rows +-1 and the bulk trigger-suspension path recomputes exact counts once post-rebuild; (d) recount lives only in ops doctor. Fix whatever of a-d is missing; regression so status cannot report healthy while find refuses. Contentless-FTS delete markers do not change the +-1 arithmetic.","design":"v23 added fts_freshness_state + the text-populated partial index; verify and finish the O(1) design: (a) polylogue find works on the live archive; (b) readiness hot path reads ONE ledger row \u2014 the three FTS sync triggers (messages_fts_a{i,d,u}) increment/decrement source_rows/indexed_rows as a single-row UPDATE inside the existing write transaction (negligible); bulk trigger-suspension path recomputes exact counts once post-rebuild; (c) STALE verdicts are CACHED: when freshness cannot be trusted, record STALE with counts in the ledger (the write exists at fts_lifecycle.py:804-812) and trust it for a bounded TTL instead of recounting ~15s of cold I/O per attempt \u2014 measured: 17s-then-fail, three times, for the same answer; (d) the expensive verify-scan is demoted to ops doctor. Second-order win: with readiness O(1) the gate can run on every query for free. Regression: status cannot report healthy while find refuses; stale archive answers instantly with an actionable error. Contentless-FTS delete markers do not change the +-1 arithmetic.","id":"polylogue-20d.3","issue_type":"task","labels":["area:perf","area:storage","enabler"],"owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-03T06:33:58Z","status":"closed","title":"Verify v23 FTS readiness end-to-end: find works; readiness is an O(1) ledger read","updated_at":"2026-07-03T06:39:31Z"} -{"_type":"issue","acceptance_criteria":"- The CLI search-vs-list site branches on structured-only vs FTS (spec.query_terms/contains_terms), mirroring the daemon http.py discriminator; structured-only queries no longer pass through the FTS readiness gate.\n- Regression test: a structured-only query (filter by origin/date, no query terms) against an archive with deliberately-stale/absent FTS returns results and does not raise or deny on FTS readiness; `devtools test ` green.\n- The current (post-v23) routing shape is verified and documented in the PR before the change.","close_reason":"PR #2784 merged: absent/stale-FTS structured-query regression (drops messages_fts+triggers, filtered row returned). Original defect misframed post-v23; CLI discriminator already parity-correct per PR AC matrix.","closed_at":"2026-07-12T22:56:19Z","comment_count":0,"created_at":"2026-07-03T04:32:02Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:01Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.4","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"The daemon discriminates structured-only queries from FTS queries (http.py ~:1789-1793); the CLI calls the search path unconditionally, so structured filters pay the FTS readiness gate. Port the discriminator at the single CLI search-vs-list site (branch on spec.query_terms/contains_terms). Regression: structured-only query on an archive with deliberately-stale FTS must succeed. Verify current state first \u2014 v23 + recent work may have changed the shape.","design":"The daemon discriminates structured-only queries from FTS queries (polylogue/daemon/http.py ~:1789-1793); the CLI calls the search path unconditionally so structured filters pay the FTS readiness gate. Port the discriminator to the single CLI search-vs-list site, branching on spec.query_terms/contains_terms so structured-only queries skip the FTS gate. Verify current shape first \u2014 v23 freshness work may have changed it.","id":"polylogue-20d.4","issue_type":"bug","labels":["area:cli","area:perf","delivery:G-live-performance","lane:interactive-performance"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/020_polylogue_20d_4.md (depth: anchored-contract-prework; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"CLI structured-query routing parity with daemon (#1860): no FTS gate for non-FTS queries","updated_at":"2026-07-12T22:56:19Z"} -{"_type":"issue","acceptance_criteria":"- Lineage-composed transcript streaming uses the streaming writer (extend the a9dc3f274 pattern) for composed (parent-prefix + tail) reads \u2014 no eager full-materialization fallback remains (grep the composed read path).\n- `read --view messages --full --to ` uses a true iterator/writer renderer rather than eager buffering.\n- Material-origin-filtered message pagination pushes `material_origin` into the repository pagination SQL (pattern a17e3af95); hydration no longer filters in Python.\n- Each of the three is verified with a live-archive file export showing bounded peak RSS (flat vs message count) with export timing recorded, plus focused unit tests on the streaming/pagination modules (`devtools test ` green).","close_reason":"Superseded by polylogue-z9gh.9.1, whose shared bounded query transaction now explicitly owns all three eager streaming/pagination residues.","closed_at":"2026-07-15T19:34:36Z","comment_count":0,"created_at":"2026-07-03T04:32:02Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:02Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.5","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Residue of the streaming-export slice: lineage-composed transcript streaming falls back to the eager path; read --view messages --full --to file lacks a true writer/iterator renderer; material-origin-filtered pagination is eager until SQL owns the predicate.","design":"Three eager fallbacks to close (prior-audit evidence, re-locate): (1) lineage-composed transcript streaming falls back to the eager path \u2014 extend the streaming writer landed in a9dc3f274 to composed (parent-prefix + tail) reads; (2) read --view messages --full --to file lacks a true writer/iterator renderer \u2014 same pattern; (3) material-origin-filtered message pagination hydrates eagerly until SQL owns the predicate \u2014 push material_origin into the repository pagination SQL (pattern: a17e3af95 routed ordinary paginated reads through repository pagination). Verify each with a live-archive file export timing + RSS bound, plus focused unit tests on the streaming/pagination modules.","id":"polylogue-20d.5","issue_type":"task","labels":["area:perf","area:storage","delivery:G-live-performance","lane:interactive-performance"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/095_polylogue_20d_5.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Finish streaming reads: composed transcripts, messages --full writer, origin-filtered pagination SQL","updated_at":"2026-07-15T19:34:36Z"} -{"_type":"issue","acceptance_criteria":"- RE-MEASURE first (recent daemon backoff commits changed the shape): bounded catch-up run + stage timings + `polylogue ops diagnostics workload` before/after are captured and the baseline recorded.\n- The idempotency invariant is kept verified \u2014 full-replace re-ingest rewrites all messages in one transaction \u2014 while for live-tailed long sessions the append path (sources/live/append_ingest.py) stays the hot route; `devtools bench ingest-amplification` on real tails is wired as a scheduled check to catch append-vs-full-replace regressions.\n- End-to-end ingest-to-searchable latency is measured with a synthetic session write on the seeded corpus (chain: hook/watcher debounce -> parse -> store -> FTS -> cache invalidation (20d.12) -> SSE announce (20d.13)); a session appears in find/webui within the ~10s interactive SLO budget (20d.14).\n- If still slow after re-measure, the named suspects (per-file parse overhead, per-file commit cadence, prepare-cache misses) are investigated with evidence; the fix is verified by re-running the timing matrix and `devtools bench ingest-throughput`.","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-17T08:45:38Z","id":"019f6f40-afd7-7442-a8a2-e1fd9dfe1f4f","issue_id":"polylogue-20d.6","text":"Live evidence 2026-07-17: the deployed daemon scanned 16,070 paths every 15s; each prefilter took ~110-125s, so full scans overlapped and the archive was continuously busy. Two old but live-held Codex JSONL tails were selected every sweep (about 88MiB and 100MiB); fuser confirms their writers are active Codex processes, so this is not a static-byte replay. PR #2987 (a09c462) removes repeated bounded probes when the stat state is unchanged, but the global 15s missed-event census still needs a cadence/backpressure redesign. Treat this as direct evidence for this bead's re-measure / interactive responsiveness scope."}],"created_at":"2026-07-03T04:32:03Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:03Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.6","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"0.2 files/s full-ingest chunks; parse_s ~274s for 50 small files. Recent daemon backoff commits (no-op retry/catch-up chunks, filtered retry paths) address parts \u2014 re-measure before working. GH issue thread (body + comments) is input, not authority; this bead's scope statement wins where they conflict.","design":"Live evidence (gh#2391): full-ingest chunks ~0.2 files/s; 50 small files -> parse_s ~274s while convergence <2s; WAL ballooned during a 50-file chunk. Recent daemon backoff commits changed the shape \u2014 RE-MEASURE first (bounded catch-up + stage timings + ops diagnostics workload before/after). Related invariant to keep verified: full-replace re-ingest rewrites all messages in one transaction (correct for idempotency) \u2014 for live-tailed long sessions the append path (sources/live/append_ingest.py) must stay the hot route; run devtools bench ingest-amplification on real tails as a scheduled check, since append-vs-full-replace regressions multiply WAL churn. Suspects if still slow after re-measure: per-file parse overhead, per-file commit cadence, prepare-cache misses.","external_ref":"gh-2391","id":"polylogue-20d.6","issue_type":"task","labels":["area:daemon","area:perf","delivery:G-live-performance","horizon:frontier","lane:interactive-performance"],"notes":"SLO framing (2026-07-03): the user-facing contract for this work is ingest-to-searchable latency \u2014 a session appears in find/webui within ~10s of the JSONL write (budget owned by the interactive SLO tier, 20d.14). That chain is hook/watcher debounce -> parse -> store -> FTS -> cache invalidation (20d.12) -> SSE announce (20d.13); measure end-to-end with a synthetic session write on the seeded corpus, not just parse_s in isolation. The 0.2 files/s figure is the batch-catchup lane; the live single-session lane is the one that must feel instant.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=A-implementation-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/094_polylogue_20d_6.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nPriority correction 2026-07-15: promoted P3 to P2 during invariant review. The bead covers a current single-writer, resource-containment, durable-lifecycle, verification-gate, or interactive-latency contract with concrete evidence; promotion does not automatically admit it to the active execution set.\n2026-07-17 live deployment evidence: service restart sent SIGTERM at 11:21:12 while watcher catch-up prefilter was inside `sha256_range_from_path` via `_needs_work_from_state` / `_plan_catch_up`. The process remained at ~2 GiB RSS and did not complete graceful shutdown; systemd killed it at TimeoutStopSec=90s, then the new daemon started normally at 11:22:42. This is a lifecycle contract failure coupled to oversized full-census planning: shutdown must be observed at bounded hash/scan checkpoints and prevent a restart from waiting for the stop timeout.\n2026-07-17 live closure evidence: PR #2999 removed raw replay cohort expansion from the periodic/default-executor status snapshot while preserving it for explicit rich diagnostic reads. Deployment package updated through sinnix commit 147ee2f. The deployment necessarily waited out the already-running old binary (SIGKILL after its 90s stop timeout), but the new daemon started at 12:10:43 CEST. After allowing its periodic snapshot loop to run, a controlled `systemctl --user restart polylogued.service` at 12:12:01 completed in 1,124 ms: old PID 2095628 received SIGTERM, exited status 143 at 12:12:02, and replacement PID 2097361 was active immediately. No stop timeout or SIGKILL. This proves the original live shutdown blocker is removed under the same service path.\n\n2026-07-17 bounded-status closure evidence: PRs #2999, #3001, and #3002 preserve exact raw-replay, readiness classification, and archive-debt diagnostics for explicit reads, but exclude their archive-wide scans from the 10-second periodic snapshot with explicit unavailable/not_run markers. Sinnix deployment commits: 147ee2f, fc60654, 48655b3. After #3002 deployment, three consecutive /api/status snapshots were fresh and advanced at 12:28:43, 12:28:57, and 12:29:10 UTC; HTTP latency was 3.4\u20134.5 ms and py-spy showed all daemon workers idle. A controlled restart at 12:29:35 CEST completed in 1,075 ms (PID 2161494 -> 2164096), with status 143 but no stop timeout or SIGKILL; the post-restart snapshot was fresh, 5.3 ms, and carried bounded raw-replay/readiness/archive-debt markers. This retires the known periodic-status shutdown blockers; the broader ingest-to-searchable SLO and remaining full-ingest/WAL scope stay open.\n2026-07-26 portfolio-convergence audit: released stale in_progress claim after >7 days with no recorded activity; scope remains open and must be re-claimed on real work start.","owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-17T09:02:07Z","status":"open","title":"Live full-ingest catch-up latency + WAL shape","updated_at":"2026-07-26T09:13:00Z"} -{"_type":"issue","acceptance_criteria":"1. Produce a serialized EQP and size census from one reflink archive copy with one reader; fail loudly on stale/partial state. 2. Include the known coordinator-scoped actions/delegations and tool:Workflow queries, recording rows visited, scans, temp B-trees, elapsed time, peak RSS, swap, and temp I/O. 3. Classify each full scan/materialization as expected or attach it to a concrete fix bead; polylogue-z9gh.2 owns the confirmed global-view defect. 4. State an acceptable resource envelope and add regression queries that fail when selective predicates are applied only after global windows/groups. 5. Never run parallel full dbstat/EQP walks or mutate the live archive.","close_reason":"Superseded by two durable owners: yeq.3 owns repeatable workload/EQP/resource differentials; fie owns the full derived-table/index byte census and scaling decision evidence. All live-safety constraints and known incident queries are retained.","closed_at":"2026-07-15T18:28:31Z","comment_count":0,"created_at":"2026-07-03T04:32:04Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:03Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.7","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"description":"Systematic plan audit: monkeypatch sqlite3 execute in a pytest session against a reflink copy (cp --reflink index.db /realm/tmp/eqp-copy.db), log EXPLAIN QUERY PLAN during a scripted tour of every CLI verb + MCP insight tool; grep for SCAN and USE TEMP B-TREE. dbstat census for sizes (VERIFY dbstat compiled into nixpkgs sqlite, else sqlite3_analyzer). Never against the live DB.","design":"Method: monkeypatch sqlite3 execute in a pytest session against a reflink copy (cp --reflink index.db /realm/tmp/eqp-copy.db) logging EXPLAIN QUERY PLAN during a scripted tour of every CLI verb + MCP insight tool; grep SCAN and USE TEMP B-TREE. dbstat census on the copy (VERIFY dbstat module compiled into nixpkgs sqlite, else sqlite3_analyzer): per-table/per-index bytes for the 33 index tables. Prime suspects (fables audit): text stored in BOTH messages and blocks rows plus the search_text generated column feeding FTS; ~70-column session_profiles; 9+ indexes on messages alone (index.py:128-180). Frame results as projection-overhead-vs-source (index.db 23GB vs 36GB blob truth): which derived structures earn their share. Join with the audit-lane read/write matrix to find expensive-AND-unread material. Never run against the live DB.","id":"polylogue-20d.7","issue_type":"task","labels":["area:perf","delivery:G-live-performance","delivery:ac-patched","horizon:frontier","lane:live-substrate"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=live-substrate; readiness=D-horizon-ready; proof=live-ingest fixture, event materialization proof, status/liveness report. Original readiness=E-spec-needed.\n2026-07-12 incident: a fanout lane ran ~8 parallel dbstat/EQP full scans against the live 32GB index, starving concurrent v35 rebuild validation I/O; lane was interrupted. Constraint for execution: SERIAL queries only, one connection, ionice/nice, and never run dbstat full-walks while a rebuild/validation is active. Better: run against a btrfs reflink clone, not the live file.\nATTEMPT RECORD 2026-07-13: the second EQP/dbstat census attempt was interrupted with exit 143 during the fanout for I/O safety and produced no report. The execution constraint remains: one serialized scan against a reflink clone, never parallel dbstat walks against the live archive. With v35 now live, the next attempt should capture the post-fast-forward shape for comparison.\n[2026-07-15 mandate audit] Direct live read-only EQP evidence now exists for the critical path: a one-coordinator LIMIT 10 delegation query materializes global ranked action/result CTEs, resolved children, counts, and multiple temp B-trees before the outer predicate. This implicated plan coincided with an MCP scope peak of 8.5 GiB RAM, 6.8 GiB swap, 39 GiB read, and 16.1 GiB written. The broad census remains useful but must not delay the targeted fix in polylogue-z9gh.2.","owner":"ezo.dev@gmail.com","priority":1,"status":"closed","title":"EQP sweep + dbstat census on a live-archive copy","updated_at":"2026-07-15T18:28:31Z"} -{"_type":"issue","acceptance_criteria":"`polylogue-20d.8` declares a before/after measurement, an acceptable resource envelope, and a regression guard. The implementation fails loudly on stale/partial state and records phase timing where relevant. Verification artifact: named SLO report, daemon hot-path benchmark, push/cache invalidation tests.","close_reason":"Absorbed by polylogue-5wp: claim-vs-evidence is the measured proof case for one declared derived-view materialization, freshness, incremental-refresh, and frozen-sample re-score policy.","closed_at":"2026-07-15T19:48:03Z","comment_count":0,"created_at":"2026-07-03T04:32:04Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:32:04Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.8","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-04T21:31:28Z","created_by":"Sinity","depends_on_id":"polylogue-20d.10","issue_id":"polylogue-20d.8","metadata":"{}","type":"blocks"}],"dependency_count":1,"dependent_count":0,"description":"Likely falls out of the action-unit outcome fields work (SQL-side pairing instead of Python row inspection). Re-measure after that lands.","design":"Hinge: the pairing cost is Python-side row inspection; 1vpm action-unit outcome fields move it into SQL. Sequence: (1) after the action-unit fields land, re-measure with the staged timings the devloop memory prescribes (per-origin counts, unpaired counts, per-origin sampling \u2014 no whole-regen reruns while diagnosing); (2) if still >10s, the residual is the failure-predicate legs \u2014 apply the indexed disjoint-leg pattern that fixed the earlier OR/COALESCE scan. Budget: full live regen <10s or the demo documents why not.","id":"polylogue-20d.8","issue_type":"task","labels":["area:perf","delivery:G-live-performance","delivery:ac-patched","lane:interactive-performance"],"notes":"Observed during polylogue-sru.5: claim-vs-evidence live regeneration took repeated full archive passes of ~1:25-1:39 for 5,000 inspected failures even when only marker predicates/labels changed. Add a cheap re-score/relabel path over an existing frozen sample/report so calibration and marker tuning do not require rescanning the active archive or rewriting all demo artifacts.\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=G-live-performance; lane=interactive-performance; readiness=D-horizon-ready; proof=named SLO report, daemon hot-path benchmark, push/cache invalidation tests. Original readiness=E-spec-needed.","owner":"ezo.dev@gmail.com","priority":4,"status":"closed","title":"Bound claim-vs-evidence regen latency (43s on live archive)","updated_at":"2026-07-15T19:48:03Z"} -{"_type":"issue","acceptance_criteria":"A deliberately degraded archive copy (stale ANALYZE, oversized WAL, stale FTS ledger) self-heals within one daemon periodic cycle without operator action; bare status and find never claim ready-while-degraded during the window (4bu contract); the enforcement paths have regression tests on the seeded corpus.","assignee":"Sinity","close_reason":"Completed. Degraded archive self-healing is now enforced and proven across the relevant always-running paths: deterministic seeded degraded-copy proof covers stale messages_fts freshness, split-tier WAL, and split-tier sqlite_stat1; daemon tests prove the periodic WAL/optimize loops and FTS surface debt drain call the same primitives; direct archive ingest runs bounded post-commit WAL/optimize upkeep; status/search readiness guards refuse ready-while-degraded for real stale/degraded/blocking components. Final proof run: devtools workspace degraded-archive-proof --out-dir .agent/demos/degraded-archive-proof/current --json reported ok=true with FTS clean->degraded->ready, WAL degraded->truncated, optimize_ran=5, no repair/checkpoint/optimize errors. Verification: degraded proof tests 2 passed, daemon wiring tests 4 passed, demo-shelf ok, devtools verify --quick run 20260704T112022Z-quick-4135735-75b7345f passed. This close does not claim a literal 24-hour wall-clock wait; it claims the daemon-owned upkeep primitives and their always-running trigger paths are covered.","closed_at":"2026-07-04T11:21:29Z","comment_count":0,"created_at":"2026-07-03T05:06:49Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T07:06:48Z","created_by":"Sinity","depends_on_id":"polylogue-20d","issue_id":"polylogue-20d.9","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Meta-finding of the live perf audit: the safeguards (WAL cap, TRUNCATE checkpoints, PRAGMA optimize, freshness) live in a daemon that is not always running, and nothing else claims them \u2014 the archive rotted silently to a 2.7GB WAL and zero planner statistics during daemon-off weeks. Move enforcement into paths that always run: CLI open, ops doctor, ingest commit. Worth more than any new index.","design":"WAL discipline without the daemon: any CLI write-capable open (ops doctor, ingest, user-tier writes) checks wal_size > 2x journal_size_limit and issues wal_checkpoint(PASSIVE) \u2014 never TRUNCATE from the CLI (don't stall on a blocked reader); the daemon keeps TRUNCATE duty; a systemd timer via the HM module (units already ship) as belt-and-braces for daemon-off weeks. Planner stats as ingest side-effect: PRAGMA analysis_limit=1000; PRAGMA optimize; on the ingest connection after each bulk commit (bounded sampling, targets touched tables); one-time full ANALYZE already done 2026-07-03. Observability: /metrics gauges for WAL size + sqlite_stat1 presence; one line in ops status; assert stat1 in the workload probe so regression is visible; time one /metrics scrape under load while at it (1,770-line collector reads both DBs per scrape \u2014 unmeasured). The 2.7GB WAL survived because nothing reported it.","id":"polylogue-20d.9","issue_type":"task","labels":["area:daemon","area:perf","area:storage","size:M"],"notes":"2026-07-04 raw-artifact construct-validity slice: live archive had one index session (claude-code-session:315bcba7-700a-4c0e-b318-ab86d8636376) pointing at missing raw_id 86a21..., while source.db had a newer same-native raw row c2ca... with 62 messages vs the indexed 72-message fuller session. Conclusions: not safe to relink to the shorter raw row; diagnostics should keep exact raw artifact readiness false. Fixed future convergence: unchanged accepted parses now refresh sessions.raw_id and count raw_links; raw-materialization candidate selection no longer hides same-native rows when the indexed raw link is dangling; raw readiness alias classification requires the current indexed raw link to resolve; superseded raw cleanup now protects split archive index.db referenced raw ids instead of config.db_path. Focused proof: py_compile; devtools test tests/unit/pipeline/test_ingest_batch.py tests/unit/storage/test_repair.py tests/unit/storage/test_archive_readiness.py -k raw_link/same_native/protects_split/native_alias/source_path_aliases/dom_fallback/skips_shorter -> 10 passed; devtools verify --quick run 20260704T081605Z-quick-3835476-a6047b92 passed. Remaining real archive debt: the old exact raw artifact is already absent from source.db/blob, so active raw_artifacts stays blocked until recovered from backup or explicitly represented as lost evidence.\n\n2026-07-04 status UX slice: the dev daemon was running, but `polylogue --plain ops status` crashed with `TypeError: float(None)` because `_show_daemon_status` converted `fts_readiness.coverage_pct` directly. Fixed the operator-facing status path to coerce null FTS coverage through a safe float fallback; added `test_daemon_status_treats_null_fts_coverage_as_unknown_progress`. Proof: focused `devtools test tests/unit/cli/test_status.py -k 'fts_coverage or archive_fts'` passed; live `POLYLOGUE_ARCHIVE_ROOT=/home/sinity/.local/share/polylogue polylogue --plain ops status` now exits cleanly and prints daemon/FTS status; devtools verify --quick run 20260704T082425Z-quick-3850532-3b0e9ceb passed. Remaining broader 20d.9 work: exact lost raw artifact is still honest debt; full self-healing WAL/ANALYZE/freshness AC is not closed by this slice.\n\n2026-07-04 split-tier WAL invariant slice: daemon periodic WAL convergence no longer targets only index.db. Added maybe_checkpoint_archive_wals(root, ...) over existing source/index/embeddings/user/ops tier files and rewired _periodic_wal_checkpoint to use the archive root helper. Focused proof: devtools test tests/unit/daemon/test_daemon_cli.py -k periodic_wal_checkpoint -> 1 passed; devtools test tests/unit/pipeline/test_ingest_batch_wal_checkpoint.py -k 'archive_wals or checkpoint_wal or optimize' -> 3 passed; devtools verify --quick run 20260704T091618Z-quick-3927966-b3525723 passed. Live probe: dev daemon /metrics 200 in 3173.5 ms and /api/status 200 in 2.9 ms; metrics exposed WAL size/stat1 gauges. Remaining 20d.9 scope: stale FTS/readiness self-healing proof and deliberately degraded archive-copy acceptance are not closed by this slice.\n\n2026-07-04 optional FTS self-healing slice: startup now attempts derived FTS surface repair only after messages_fts freshness is trusted ready; if optional surface repair fails or is incomplete, it records fts_surface debt for session_work_events_fts and threads_fts. Daemon convergence now dispatches all supported FTS surface debt through repair_fts_surface instead of only handling messages_fts. Live proof against /home/sinity/.local/share/polylogue: deliberately marked session_work_events_fts and threads_fts freshness stale, enqueued fts_surface debt, ran the daemon debt-drain primitive, and both surfaces returned ready with exact counts (22,843 work events; 8,720 threads) and no remaining FTS debt. Focused proof: devtools test tests/unit/daemon/test_daemon_cli.py -k 'fts_surface or fts_startup_readiness or startup_failure or startup_large_drift' -> 11 passed; devtools test tests/unit/daemon/test_convergence_stages.py -k 'fts_global_repair or optional_surface_repair or archive_fts' -> 6 passed. Broad quick gate: devtools verify --quick run 20260704T093430Z-quick-3957389-34534596 passed. Remaining 20d.9 scope: deliberate degraded archive-copy acceptance and broader self-healing matrix are still open; this slice closes the optional FTS freshness gap.\n\n2026-07-04 split-tier planner-stat upkeep slice: daemon periodic PRAGMA optimize no longer targets only index.db. Added maybe_optimize_archive_tiers(root, ...) over existing source/index/embeddings/user/ops tier files and rewired _periodic_db_optimize to dispatch that helper through asyncio.to_thread after the 24h sleep. Focused proof: devtools test tests/unit/pipeline/test_ingest_batch_wal_checkpoint.py -k 'optimize_archive_tiers or optimize_sqlite or archive_wals' -> 3 passed; devtools test tests/unit/daemon/test_daemon_cli.py -k 'periodic_db_optimize or periodic_wal_checkpoint' -> 3 passed. Live proof against /home/sinity/.local/share/polylogue: maybe_optimize_archive_tiers(reason=live-proof) touched 5 tiers, ran 5, errors 0; index tier took about 4.68s, others were near-instant. Broad quick gate: devtools verify --quick run 20260704T094203Z-quick-3978795-9a5f5b8c passed. Remaining 20d.9 scope: raw-materialization status is still stale with one actionable parse-failed group, and deliberate degraded archive-copy AC is still open.\n\n2026-07-04 degraded-copy self-healing proof slice: added devtools workspace degraded-archive-proof, an executable deterministic proof that seeds a demo archive copy, deliberately degrades only rebuildable state (messages_fts freshness, WAL, planner stats), runs the same bounded FTS repair/checkpoint/PRAGMA optimize primitives used by daemon upkeep, and writes JSON/Markdown proof artifacts. The command resolves output paths before demo seeding chdir and removes the temporary archive by default so .agent/demos stays readable; --keep-archive is available for debugging. Current generated proof at .agent/demos/degraded-archive-proof/current reports: seeded 3 sessions / 23 messages; FTS ready clean=True -> degraded=False -> after=True; WAL 189552 -> 24752 bytes; checkpoint mode truncate; optimize_ran=5; no checkpoint/optimize errors; FTS repair success with 63/63 messages, 4/4 work events, 3/3 threads. Verification: devtools test tests/unit/devtools/test_degraded_archive_proof.py tests/unit/devtools/test_command_catalog.py tests/unit/devtools/test_devtools_main.py -k \"degraded_archive_proof or command_specs_have_unique or list_commands_json_includes_generated_surface\" -> 4 passed; devtools workspace degraded-archive-proof --out-dir .agent/demos/degraded-archive-proof/current --json -> ok true; devtools workspace demo-shelf --root .agent/demos --json -> ok true; devtools verify --quick run 20260704T095436Z-quick-3997764-fd5f9fd9 -> exit 0. Remaining 20d.9 scope: prove/finish the always-running trigger surface beyond the deterministic proof where still missing, and settle raw-materialization convergence debt in daemon paths.\n\n2026-07-04 direct archive ingest upkeep slice: parse_sources_archive now runs bounded post-commit upkeep on every direct archive ingest commit boundary, both work-batched commits and the per-session escape hatch. The upkeep calls maybe_checkpoint_archive_wals(... allow_truncate=False) and maybe_optimize_archive_tiers(reason=archive_ingest_commit), records an archive_post_commit_upkeep observation, and preserves the final archive_file_set write observation as the last batch observation for existing status/API contracts. Verification: devtools test tests/unit/pipeline/test_archive_ingest_commit_batching.py -> 6 passed; devtools test tests/unit/pipeline/test_ingest_batch_wal_checkpoint.py -k 'optimize_archive_tiers or optimize_sqlite or archive_wals or wal_checkpoint' -> 10 passed; combined focused command -> 16 passed; devtools verify --quick run 20260704T100228Z-quick-4005830-1864b677 -> exit 0. Remaining 20d.9 scope: status/find ready-while-degraded proof and any remaining raw-materialization convergence gap.\n\n2026-07-04 daemon fast-path search honesty slice: fixed the CLI daemon-backed root query projection so `/api/sessions?query=...` degraded route states are preserved as degraded failures instead of being collapsed into ordinary no-results. `_emit_daemon_search_payload` now detects `route_state.state == \"degraded\"`, emits the daemon route_state/diagnostics for JSON/YAML, prints the search-index reason for text output, exits 1, and never opens SQLite as a misleading fallback. Regression coverage added in tests/unit/cli/test_query_exec_laws.py for JSON and plain degraded daemon search payloads, plus guard that ArchiveStore is not opened. Verification: devtools test tests/unit/cli/test_query_exec_laws.py -k 'daemon_degraded_search or uses_daemon_for_supported_session_pages or falls_back_when_daemon_unavailable' -> 4 passed; devtools test tests/unit/storage/test_archive_tiers_search_guard.py tests/unit/storage/test_perf_rescue_1314.py -k 'search_rejects_ready_freshness_row_when_triggers_missing or search_session_hits' -> 3 passed; devtools verify --quick run 20260704T100908Z-quick-4021947-0bb84347 -> exit 0. Remaining 20d.9 scope: status/find truth is now covered for daemon degraded search projection and storage readiness guards; still need final raw-materialization convergence/lost-source-evidence disposition before closing the Bead.\n\n\n2026-07-04 explicit archive blob-root convergence slice: fixed raw replay and direct archive ingest so blob reads/writes derive from the same explicit archive root as source.db/index.db instead of ambient XDG blob_store_root(). Root cause on live archive: raw row c2ca... had a retryable parse_error pointing at .cache/dev-loop/.../xdg-data/polylogue/blob even though the blob existed under /home/sinity/.local/share/polylogue/blob. Changes: process_ingest_batch now passes service.archive_root/blob to workers; source parsing accepts an explicit blob_root for capture_raw group providers; parse_sources_archive threads archive_root/blob through sequential and process-pool paths; _archive_raw_payload reads blob_hash payloads from the explicit archive blob root. Also classified same-native raw gaps whose indexed session points at missing source raw evidence as lost-source-evidence-alias, eliminating the vague unchecked raw_id_join_gap while keeping raw_materialization_ready false through lost_source_evidence_count. Live proof: stopped old dev daemon, ran _drain_raw_materialization_once(limit=1) with POLYLOGUE_ARCHIVE_ROOT=/home/sinity/.local/share/polylogue; parse_failed/actionable went 1 -> 0, unchecked stayed 0, classified stayed 385, category_counts gained lost-source-evidence-alias=1, raw_materialization_ready remains False because exact source evidence is still missing. Verification: devtools test tests/unit/pipeline/test_ingest_batch.py -k 'archive_root_blob_store or iter_ingest_results_sync_runs_inline' -> 2 passed; devtools test tests/unit/pipeline/test_archive_ingest_commit_batching.py -k 'explicit_archive_blob_root or per_session_escape_hatch' -> 2 passed; devtools test tests/unit/storage/test_repair.py -k 'raw_materialization_retries_restored_missing_blob_parse_errors or raw_materialization_replay_uses_batch_parse_call' -> 2 passed; devtools test tests/unit/storage/test_archive_readiness.py -k 'lost_source_evidence or unexplained_gaps or source_path_aliases' -> 3 passed; devtools verify --quick run 20260704T102353Z-quick-4042540-6c055e14 passed. Remaining 20d.9 scope: exact lost source evidence still blocks full raw-materialization readiness until the missing original raw artifact is recovered or represented as permanent loss; the daemon must be restarted from the fixed commit so it no longer re-stamps the stale XDG parse failure.\n\n2026-07-04 raw materialization source-truth replay slice: resolved the last live lost-source-evidence blocker by making raw materialization replay force-write durable source evidence all the way through duplicate-precedence and stale-freshness guards. Root cause was layered: repair replay used normal duplicate protection; the final storage writer could skip older source evidence while batch counts still reported changed; and session id generation treated canonical origin strings as unknown. Fixes: raw replay calls parse_from_raw(force_write=True); _write_session counts stale skips honestly and passes force_replace to write_parsed_session_to_archive; session_id()/origin_from_provider accept canonical Origin tokens; regression tests cover canonical origin ids and force replacing a newer stale index row with older durable source. Live proof on /home/sinity/.local/share/polylogue: session claude-code-session:315bcba7-700a-4c0e-b318-ab86d8636376 now points at current raw_id c2ca323edf53f3a6540e14b9fb1925aef9e0aceb886802906f1f137d7a5e7a4c with 62 messages; devloop-status --quick reports raw_materialization state=ready, replayable=0, lost_source_evidence_count=0. Focused proof: py_compile over touched modules; devtools test tests/unit/core/test_public_surface_origin_vocabulary.py tests/unit/pipeline/test_ingest_batch.py tests/unit/storage/test_repair.py -k origin_from_provider_accepts_canonical_origin_tokens/write_session_force_write_replaces_older_freshness/raw_materialization_replay... -> 6 passed.\n\n2026-07-04 direct status readiness-contract slice: direct JSON fallback no longer reports archive unhealthy merely because the default path intentionally skips expensive exact transform/archive-readiness probes. `_direct_transform_component` now maps `direct_status_default_skips_exact_archive_readiness` to transforms state=unknown with transform registry/version evidence and no session_count claim; real exact-readiness failures still map to blocked. `_show_direct_json` computes direct `ok` from hard component failures, treating intentionally unknown probes as neutral and preserving stale/degraded/blocked as unhealthy. Live proof against /home/sinity/.local/share/polylogue: `polylogue --plain ops status --format json` now reports ok=True, raw_materialization=ready, embeddings=ready, assertions=ready, transforms=unknown/direct_status_default_skips_exact_archive_readiness. Focused proof: `devtools test tests/unit/cli/test_status.py -k 'skipped_transform_readiness or blocks_transforms_when_archive_readiness_fails or skips_exact_archive_readiness_by_default'` -> 3 passed. Broad quick gate: `devtools verify --quick` run 20260704T111152Z-quick-4118424-da3e68ce passed. This closes the false-blocked status gap while retaining the 20d.9 no-ready-while-degraded invariant for real stale/degraded/blocking components.\n2026-07-04 closure-proof contract slice: strengthened the degraded archive proof so the artifact records machine-readable contract fields instead of relying on prose inference: healing_driver=daemon_owned_upkeep_primitives, degraded_inputs=(messages_fts_freshness, split_tier_wal, split_tier_sqlite_stat1), daemon_owned_primitives=(repair_stale_fts_rows, maybe_checkpoint_archive_wals, maybe_optimize_archive_tiers), always_running_paths=(daemon_startup_fts_readiness, daemon_convergence_fts_surface_debt, daemon_periodic_wal_checkpoint, daemon_periodic_db_optimize, direct_archive_ingest_post_commit_upkeep). Regenerated .agent/demos/degraded-archive-proof/current. Closure audit: AC is satisfied by deterministic degraded-copy proof plus daemon wiring tests, not by waiting a literal 24h optimize interval; the artifact now says exactly what is proven. Verification: devtools test tests/unit/devtools/test_degraded_archive_proof.py -> 2 passed; devtools test tests/unit/daemon/test_daemon_cli.py -k periodic_wal_checkpoint_targets_archive_root_tiers/or/periodic_db_optimize_targets_archive_root_tiers/or/drain_convergence_debt_retries_* -> 4 passed; devtools workspace degraded-archive-proof --out-dir .agent/demos/degraded-archive-proof/current --json -> ok true; devtools workspace demo-shelf --root .agent/demos --json -> ok true; devtools verify --quick run 20260704T112022Z-quick-4135735-75b7345f passed.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-03T05:43:00Z","status":"closed","title":"Self-healing degraded state: WAL/ANALYZE/freshness enforcement in always-running paths","updated_at":"2026-07-04T11:21:29Z"} -{"_type":"issue","acceptance_criteria":"Each demo child (212.1 post-hoc forensic Q&A, 212.2 D1, 212.3 D2, 212.4 D4, 212.5 D5, 212.6 D8) ships in two variants: (a) a public seeded-corpus variant (seed 1843) reproducible with one documented command, and (b) a live-archive operator variant. GROUND RULE: every displayed number resolves, on click or --explain, to structural evidence (outcome fields, usage events, provenance refs, raw bytes) \u2014 never regex over prose. COMPOSITIONALITY: every demo decomposes into product primitives (DSL queries, saved views, read-package layouts, render profiles, workflow-registry entries); shell/python is glue only, and any bespoke logic beyond glue is first filed and built as a product primitive. D3/D6/D7 are explicitly out of scope (covered by the context-loop/uplift/forensics campaigns). Epic closeable when all non-deferred children are closed and a cold-reader can drive each public variant to first result unaided. Verify: each child's own acceptance + devtools verify doc-commands over the demo commands.\n\nAll child titles, workflow IDs, manifests, and cross-program references use PF-D*; an unqualified D8 reference fails the demo-catalog lint as ambiguous with AI-D8 fleet convergence.","comment_count":0,"created_at":"2026-07-03T04:50:57Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Ground rule for all: every displayed number resolves, on click or --explain, to structural evidence (outcome fields, usage events, provenance refs, raw bytes) \u2014 never regex over prose. Each runs on the deterministic demo corpus (seed 1843) for public reproduction + a live-archive operator variant. D3 (resurrect a dead session) is covered by the context-loop preamble bead + uplift campaign; D6 (Wrapped/one-year-four-assistants) is the forensics campaign artifact; D7 (candidates on trial) is the context-loop judgment flow \u2014 do not duplicate them here.\n\nCOMPOSITIONALITY RULE (operator, 2026-07-03): every demo must decompose into product primitives \u2014 DSL queries, saved views, read-package layouts, render profiles, workflow registry entries. Shell/python is allowed only as glue (sequencing, narration). If a demo needs bespoke logic beyond glue, that logic is a missing product primitive: file the primitive as a bead, build it, THEN ship the demo on top. Demos are the forcing function for product algebra, not a parallel scripts directory (the agent_forensics.py -> polylogue analyze fold in tf2.2 is the template).\n\nCLARIFICATION (2026-07-08): the glue restriction targets hidden bespoke business logic masquerading as a demo, not the demo agents own reasoning. A demo may run a query, read the result, and decide what to query next based on that judgment \u2014 that adaptive loop is not \"bespoke logic requiring a product primitive,\" it is often the very capability being demonstrated (e.g. 212.1 post-hoc forensic Q&A, 212.9 foreman-rhetoric analysis). Only non-primitive DATA TRANSFORMS or COMPUTATIONS belong to the \"file it as a primitive first\" rule; agent-in-the-loop decision-making does not.","design":"Portfolio contract (see 212.7): every demo = executable PROMPT.md emitting the uniform Demo Finding Packet; product primitives only, shell as glue; anti-demo (212.8) ships beside successes. IDEA MENU: a 60-item grounded demo catalog from the 2026-07-06 corpus digestion is preserved at .agent/handoffs/polylogue-gpt-pro-2026-07-06/D-demos.md \u2014 pull from it when extending the portfolio; most items converge on six primitives now tracked elsewhere (query runs rxdo.3, cohorts rxdo.2, annotation batches rxdo.7, artifact edges 1vpm.3, analysis runs rxdo.8, context-compile runs 37t.11/gjg.4). Standouts beyond the current children: Beads swarm autopsy + before/after backlog-quality audit (process story), stale-docs-vs-code reality check, notes-sidecar trap detector, GitHub external-ref reconciliation (operator checklist, never auto-mutation), commit<->session archaeology both directions (7xv), memory-utility analytics (37t.17), flat-dump-vs-compiled-context (gjg.4/37t.11 arm), archive-root pitfall detector (fold into doctor/adoption lane).\n\nDEMO NAMESPACE DECISION 2026-07-13: this portfolio uses PF-D* identifiers. The archive-intelligence catalog polylogue-rxdo.10 uses AI-D*. Historical unqualified D1/D2/... text remains an alias only inside its owning parent; cross-program dependencies and external-adoption prose must use the qualified identifier.","id":"polylogue-212","issue_type":"epic","labels":["area:demos","delivery:L-external-legibility","horizon:mid","lane:docs-demos-launch"],"notes":"PORTFOLIO ORDER (corpus-digested 2026-07-06, defended): first public mini-portfolio = THREE packets: D1 receipts (212.2, the wedge), D4 behavioral archaeology (212.4, query breadth), anti-demo (new child, honesty). Second wave: D3 post-hoc forensic QA (212.1) + method-trace swarm-to-beads (process story \u2014 safest inbound narrative per situation brief; must show mistakes/gates/held changes, not velocity porn). Third (after packet runner + rxdo.7 annotation import): cost-by-outcome (212.3, needs outcome join), resume-triage (212.6), external annotation loop (new when rxdo.7 lands), delegation rhetoric (annotation-recipe variant first; true delegation unit 1vpm.1 later \u2014 Fable is a cohort, not a silo). Full-direction demos (work reconstruction 7xv.1, context-compile-after-compaction gjg.4, query-objects analysis DAG rxdo) stay LAST \u2014 fronting them recreates the deferral pattern the brief warns about. Packet contract + runner + registry = new child; corpus coverage check for seed-1843 should be the first runner step (unverified claim: seeded corpus has fixtures for every today-prompt).\n[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/191_polylogue_212.md (depth: epic-checklist; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-10 legibility-kit digest, fable] Demo doctrine now public: docs/demos.md (claim/oracle/controls/falsifier/non-claims per demo). New children: polylogue-212.11 (Incident 14:32 shared proof world) + polylogue-212.12 (Demo Packet v2 contract) \u2014 these are the kit-recommended substrate BEFORE flagship demos; kit merge order puts them ahead of 212.2 Receipts. Kit expanded portfolio (rejected demos, controls, launch arc) escrowed: .agent/handoffs/polylogue-legibility-kit-2026-07-10/02b-demo-portfolio-expanded.md. Recommended public arc: Receipts -> Count It Once -> (sinex) Missing Source -> (sinex) Changes-Mind-Honestly -> joint World Around the Claim; Resume Under Oath is the honest memory demo (three-arm, stale-memory traps, independent ground truth).","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Proof-world demo portfolio: PF-D1/PF-D2/PF-D4/PF-D5/PF-D8","updated_at":"2026-07-13T07:00:18Z"} -{"_type":"issue","acceptance_criteria":"1. Against one completed multi-hour session, the demo answers each forensic question live using existing reads (get_postmortem_bundle, session_work_events, session_phases, neighbor_candidates, git correlation): first-bad-assumption entry, file churned before the regression, cited evidence for a design choice, and resembling prior failed attempts. 2. One explicit 'we cannot answer X' slide is included (construct-validity honesty). Verify: the demo runs end-to-end against a chosen archived session (recorded output/artifact) using only existing reads (no new query machinery).","comment_count":0,"created_at":"2026-07-03T04:50:58Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:50:57Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.1","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:53:14Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:14Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:15Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:16Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:17Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:18Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.1","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":1,"description":"The category-separation demo: take one completed multi-hour coding-agent session and answer post-hoc questions live \u2014 when did the bad assumption first enter; which file churned before the regression; what evidence did the agent cite for a design choice; which prior failed attempts resemble today's failure. Composes existing reads (postmortem bundle, work events, phases, neighbor candidates, git correlation); packaging is the work, plus one honest 'we cannot answer X' slide (construct validity).","design":"A category-separation demo: take one completed multi-hour coding-agent session and answer post-hoc questions live, when the bad assumption first entered; which file churned before the regression; what evidence the agent cited for a design choice; which prior failed attempts resemble today's. Composes existing reads (postmortem bundle, work events, phases, neighbor candidates, git correlation); packaging is the work, plus one honest 'we cannot answer X' slide for construct validity.","id":"polylogue-212.1","issue_type":"task","labels":["area:demos","area:legibility","delivery:L-external-legibility","lane:docs-demos-launch"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/122_polylogue_212_1.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"Post-hoc forensic Q&A demo: questions a tracer cannot answer","updated_at":"2026-07-08T20:15:20Z"} -{"_type":"issue","acceptance_criteria":"A conforming analytical packet proves every aggregate and quote resolves through claim to query/result/sample/evidence. Broken ref, changed denominator, unselected specimen, invalid label span, and undeclared public transformation fixtures each fail with named errors. Existing non-analytical packets remain valid under their current profile. The Fable private/public packets use the analytical profile. The command remains part of the existing demo-packet registry/validation surface.","comment_count":0,"created_at":"2026-07-10T08:10:41Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T10:10:41Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.10","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-10T10:10:41Z","created_by":"Sinity","depends_on_id":"polylogue-212.7","issue_id":"polylogue-212.10","metadata":"{}","type":"discovered-from"},{"created_at":"2026-07-15T20:34:53Z","created_by":"Sinity","depends_on_id":"polylogue-37t.14","issue_id":"polylogue-212.10","metadata":"{}","type":"blocks"}],"dependency_count":1,"dependent_count":1,"description":"The shipped Demo Finding Packet validator checks file shape and minimal provenance fields but does not prove that labels resolve to evidence spans, numbers resolve to query results, samples resolve to manifests, or public artifacts are declared transformations of private packets. Analytical demos can therefore be structurally green while their claims are ungrounded.","design":"Extend the existing packet profiles and runner, but adapt packet query/result/sample/annotation/claim/evidence/public-transform refs into 37t.14's shared evidence graph evaluator. Packet-specific work remains schema/profile validation, deterministic manifests, private\u2192public transformation rules, and report/receipt packaging; cycle, stale hash, unresolved ref, compatibility, partial support, and decisive witness semantics are not reimplemented. Mutation fixtures remove evidence, change denominators/hashes, create circular claims, and inject an undeclared public quote, then assert the shared verdict plus packet failure/held outcome.","id":"polylogue-212.10","issue_type":"task","labels":["area:demos","area:verification","delivery:L-external-legibility","horizon:frontier","lane:docs-demos-launch"],"notes":"2026-07-15 mechanism placement: analytical packet validation consumes 37t.14 for evidence ancestry/support. This bead retains packet schemas, manifests, annotation/sample checks, and public transformation validation; it no longer owns a separate graph-integrity algorithm.\nPriority calibration 2026-07-15: P2 to P3. This remains part of the full project ambition, but it is a sequenced demo, experiment, governed analytic extension, or evaluation layer rather than a present failure of archive truth, bounded queryability, durability, or source fidelity. Priority is urgency, not deletion or scope reduction; horizon is unchanged.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Validate analytical demo packets against their evidence graph","updated_at":"2026-07-15T20:07:24Z"} -{"_type":"issue","acceptance_criteria":"1. Each new construct (conflicting success claim + verified repair; compaction omission; source outage; parser v1/v2 dual interpretation; ambiguous duplicate; cross-source 14:32 event hooks) has a row in the construct verifier and docs/plans/demo-corpus-construct-audit.md regenerates green.\n2. All fixtures enter through real provider parsers (no direct DB writes); demo tour stays within FULL_TOUR_BUDGET_S and passes 100% declared constructs.\n3. Anti-vacuity: for each new construct, a withhold-the-evidence test proves the dependent surface goes red/not_supported.\n4. Existing demos/tests keep passing unmodified or with reviewed updates only.","comment_count":0,"created_at":"2026-07-10T14:48:28Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T16:48:28Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.11","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Replace scattered per-demo synthetic fixtures with ONE public-safe incident world that every flagship demo (Receipts, Count It Once, compaction autopsy, context autopsy, honest-refusal) replays from a different angle. The existing demo corpus (polylogue/scenarios/corpus.py, seed 1843, 11 sessions / 30 declared constructs) already covers structural failure, lineage fork, subagent, compaction, attachments, overlays. Source: GPT-5.6 Pro external-legibility kit 02b (escrow .agent/handoffs/polylogue-legibility-kit-2026-07-10/), adjudicated 2026-07-10; kit is inspiration, not authority \u2014 every construct must be verified against live parsers.","design":"Extend the existing deterministic corpus rather than inventing a parallel one. Missing constructs to add (kit 02b inventory, verified against current scenarios/corpus.py):\n1. An assistant SUCCESS CLAIM that conflicts with a structural failure in the same session (the Receipts anchor) followed by a later VERIFIED REPAIR (second verifier run, exit 0).\n2. A compaction summary that OMITS the failed attempt (compaction-honesty anchor).\n3. A deliberate SOURCE OUTAGE window (for missing-source / coverage honesty demos; pairs with Sinex Missing Source).\n4. Same material parsed under semantics v1 and v2 (parser-revision construct; enables changes-mind-honestly demo).\n5. An ambiguous cross-material duplicate (import-twice / occurrence-identity construct).\n6. Terminal/Git/Beads-shaped observed events around the incident timestamp 14:32 so joint world-around-the-claim demos have cross-source hooks.\nConstraints: every new construct gets a row in the construct verifier (polylogue/demo/verify.py + docs/plans/demo-corpus-construct-audit.md regenerated); fixtures must flow through REAL parsers (provider-native shapes), not direct DB writes; keep seed determinism; no growth in tour wall-time budget beyond FULL_TOUR_BUDGET_S.\nAnti-vacuity witness: for each added construct, a test that DELETES/withholds the evidence and asserts the dependent demo goes red/not_supported (fixture/matrix-vacuity doctrine).\n","id":"polylogue-212.11","issue_type":"task","labels":["area:demos","delivery:L-external-legibility","horizon:frontier","lane:docs-demos-launch"],"notes":"[2026-07-10 fable, legibility-v2] Partial delivery via PR #2662: corpus v2 evidence-lab-receipts family lands construct 1 of this bead (success claim contradicted by structural failure + later verified repair) plus the anti-grep control, 34 declared constructs total. STILL OPEN here: compaction-omission, source-outage interval, parser v1/v2 dual interpretation, ambiguous duplicate, cross-source 14:32 event hooks. The kit v2 also built a STANDALONE product-independent incident-1432 corpus (declarative materials + independent oracle.json + verify_incident.py, 15 material hashes / 24 oracle facts verified in its sandbox) \u2014 but the materials/ and parser/ dirs were NOT in the operator download (see escrow MISSING-FROM-DOWNLOAD.txt); re-download or regenerate before consuming. Its oracle/manifest/verifier ARE escrowed and match this bead anti-circularity AC.\n[2026-07-10 fable] PR #2674 merged: constructs 34->37 (source-outage interval incl. daemon-twin survival write, cross-material duplicate, compaction-omits-failure) with anti-vacuity witnesses. Remaining scope: parser v1/v2 dual interpretation (design sketch in the PR branch commits \u2014 needs a real semantics-versioning primitive) and cross-source 14:32 event hooks (AC item 6).\n[GPT-Pro branch assimilation 2026-07-11] Branch 17 (`6a5112fd`; mission 02 Incident 14:32) 27KB implementation kit recovered. The model explicitly did not certify it; it is candidate material only. Scenario/oracle/mutation separation accepted; most scope superseded by #2674. Adapt only residual parser-version and cross-source event-hook constructs if the recovered kit helps. Matrix: `.agent/reports/chatgpt-pro-branch-assimilation-2026-07-11.md`.\n[Recovered Branch 17 no-import ruling, 2026-07-11] The authenticated Incident 14:32 kit contains zero changed repository paths and a zero-byte implementation patch. Its scenario.yaml/oracle.yaml/mutations.yaml and provider-shaped snippets are declarative fallback design, not a runnable corpus or verifier, and must not be imported as a second proof world or cited as green evidence. Keep #2674/current demo corpus authoritative. The only useful residual is input to the existing AC: a real versioned-interpretation path must preserve v1/v2 over the same acquired material before the semantics fixture is admitted, and terminal/Git/Beads event hooks must arrive through the typed cross-source/Sinex boundary rather than direct synthetic DB rows.\nPR #2795 merged: uses the existing receipts construct only; deferred the shared deterministic incident-world additions and construct verifier coverage this bead requires. Bead notes record prior delivery of the other constructs; parser v1/v2 interpretation and typed cross-source 14:32 hooks remain residual, out of this PR's scope.\n[2026-07-14 continued] PR #2885 (feature/demo/proof-world-real-slice) delivers the harness half of the real-archive-data extension: devtools demo real-slice-screen (devtools/proof_world_real_slice.py), read-only, opens the archive via Polylogue.get_session (read_only=True), screens flattened session text for secret/credential and PII-adjacent patterns, writes SCREENING_REPORT.md/manifest.json/transcripts to an arbitrary out dir, never writes into polylogue/scenarios/. Pushed a follow-up commit (dfd019090) addressing both CodeRabbit findings on that PR: screen_sessions() now opens one Polylogue instance and reuses it across the whole batch (was reopening per session id) with a regression test (test_screen_sessions_opens_the_archive_once_for_the_whole_batch) that counts real Polylogue.__aenter__ calls and is verified to fail if the fix regresses; _flatten_session_text's bare Any param replaced with a _SessionLike/_MessageLike Protocol pair (read-only @property members, so both the real Session/Message domain models and the tests' duck-typed doubles satisfy it structurally without mypy's invariant-attribute rejection). devtools verify --quick and the focused test file both green.\n\nPRIVACY DELIVERABLE (flagged for operator spot-check, NOT yet folded into any shared fixture path, gitignored, not part of the PR diff): ran the harness against 5 real sessions from /realm/db/polylogue \u2014 repo:polylogue coding-agent transcripts (flaky-test hunting, pipeline-idempotency test design, test-suite-compaction planning, issue #518 implementation, issue #864 implementation), all claude-code-session subagent branches, 2026-04-29 through 2026-05-07, ~193k words total. Result: 0 flagged (no secret/credential pattern fired), 3 \"review\" (all traced to test placeholders \u2014 test@example.com git-config fixtures, 127.0.0.1/93.184.216.34 loopback+RFC5737 doc IPs, and 4 occurrences of the operator's own /home/sinity/... path inside the harness's own \"output too large, saved to:\" truncation messages \u2014 not third-party PII), 2 fully clean. No NSFW, no third-party names/emails/personal data, no credentials. Independently re-verified the manifest.json/OPERATOR-SUMMARY.md this session (self-consistent, judgment concurred) rather than trusting the prior write-up blind. Held at .agent/scratch/real-slice-vetting-2026-07-14/ (OPERATOR-SUMMARY.md, SCREENING_REPORT.md, manifest.json, transcripts/) for operator review before promotion into polylogue/scenarios/.\n\nRESIDUAL AC ITEMS investigated this session, still open (consistent with PR #2795/#2674 notes): (1) parser v1/v2 dual interpretation \u2014 grepped storage/pipeline for a semantics-versioning primitive; none exists (parser_version only appears in maintenance/scope filtering and import_explain diagnostics, not as a mechanism for storing two interpretations of the same acquired material). Needs a real primitive design before a fixture can honestly demonstrate it, not a demo-layer workaround. (2) typed cross-source 14:32 event hooks (terminal/Git/Beads) \u2014 found the real typed cross-source primitive: mcp/session_commit correlate_session links a session to actual git commits (time-window + file-overlap scoring) and GitHub issue/PR refs extracted from message text; it is NOT Sinex-specific. Wiring a demo construct through it would need real git-commit-shaped fixture data landing in this repo's own history within a window matching the deterministic corpus's clock \u2014 new scope beyond a fixture-only change, and risks polluting this repo's real git history for a demo purpose. Left open rather than forcing a synthetic-DB-row shortcut that would violate the bead's own no-import ruling (2026-07-11 note) and the demo corpus's \"fixtures flow through real parsers\" rule.\n\nNot merged (per dispatch instruction \u2014 orchestrator runs the merge train). PR: https://github.com/Sinity/polylogue/pull/2885\nPriority calibration 2026-07-15: P2 to P3. This remains part of the full project ambition, but it is a sequenced demo, experiment, governed analytic extension, or evaluation layer rather than a present failure of archive truth, bounded queryability, durability, or source fidelity. Priority is urgency, not deletion or scope reduction; horizon is unchanged.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Incident 14:32 \u2014 one shared deterministic proof world for all flagship demos","updated_at":"2026-07-15T20:07:24Z"} -{"_type":"issue","acceptance_criteria":"1. Every registered Demo Packet v2 claim cites at least one receipt, every receipt carries sha256, and the registry gate resolves each cited ref/path and verifies the digest. 2. The current false-green repro fails for each independent mutation: missing claim.receipts, missing receipt.sha256, noncanonical Claim heading, falsifier triggered=true with result=pass, duplicate control id, and duplicate measurement name. 3. Valid committed packets and the minimal fixture pass the same production validator; all three current registered packets are migrated with no grandfathering. 4. Mutation evidence states which production check removal would make each negative fixture pass. 5. docs/demos.md and the example describe the enforced contract exactly. Verify with devtools test tests/unit/devtools/test_demo_packet.py tests/unit/demo/test_flagship_demos.py; devtools verify-demo-packet-registry; devtools verify --quick.","assignee":"Sinity","close_reason":"Residual false-green contract repaired in PR #2709: digest-bound claim receipts, semantic consistency, canonical report structure, unique identities, migrated registry, and six production-route mutation regressions are merged and verified.","closed_at":"2026-07-11T16:02:23Z","comment_count":0,"created_at":"2026-07-10T14:48:31Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T16:48:30Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.12","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Every public demo becomes a bounded experiment with a declared contract: one primary construct, claim stated before execution, independent oracle, negative + missing-evidence controls, baseline arm, explicit falsifier, resolvable receipts, machine-readable packet, human presentation, non-claims section, interruption/regeneration behavior. A validating JSON Schema + example exist in the external-legibility kit escrow (.agent/handoffs/polylogue-legibility-kit-2026-07-10/10-demo-packet-v2.schema.json + -example.yaml) \u2014 treat as draft input, not authority.","design":"Port the compact production semantics from recovered commit 2d42b61c5 onto current master rather than applying its whole generated-demo diff. In docs/schemas/demo-packet-v2.schema.json require claim.receipts and receipt.sha256. In devtools/demo_packet.py enforce exact canonical section headings, claim receipt-reference closure, receipt digest/path binding, falsifier state consistency, unique control ids, and unique measurement names. Migrate every registered packet and fixture to the strengthened schema with actual hashes and resolvable refs; keep current flagship/generated surfaces authoritative where the recovered branch conflicts. Extend the existing registry and focused validator tests with the reproduced false-green mutations. The validator must exercise production packet bytes and reference resolution, not a parallel test-only model.","id":"polylogue-212.12","issue_type":"task","labels":["area:demos","area:test","delivery:L-external-legibility","horizon:frontier","lane:docs-demos-launch"],"notes":"[GPT-Pro branch assimilation 2026-07-11] Branch 15 (`6a5112f5`; mission 03 Demo Packet v2) fully recovered as ZIP + Git bundle. Treat as candidate implementation, not proof: current-source worktree must re-run tests. Accepted AC inventory: predeclared claim, oracle, controls, falsifier, non-claims, digest binding, path confinement, ref closure, uniqueness, registry anti-vacuity. Recovered bytes: `/realm/inbox/gpt-pro-sol/recovered-branch-project-explanation-2026-07-11/polylogue/`. Matrix: `.agent/reports/chatgpt-pro-branch-assimilation-2026-07-11.md`.\n2026-07-11 recovered-session code audit reproduced the gap on current master. A copy of _packet-contract-stub remained ok=True after removing claim.receipts and receipt.sha256, using ## claimant, setting falsifier.triggered=true/result=pass, duplicating a control id, and duplicating a measurement name. Repro: /realm/tmp/ten-session-audit-packet-false-green. Recovered commit 2d42b61c5 has the relevant production hunks and negative tests, but its whole commit must not be applied because generated flagship packet surfaces have diverged. Assimilate schema/validator/test semantics selectively.\n2026-07-11 residual hardening merged via PR #2709 as 885b46da313c58e3c87215bc93486b97cb3b3797. Selectively ported recovered commit 2d42b61 semantics onto current master: claim.receipts and receipt.sha256 are required; ref/path/digest closure uses one read of confined artifact bytes; exact ordered canonical headings, falsifier consistency, and unique control/measurement identities are enforced. All three registered packets migrated without grandfathering. Six current-master false-green mutations fail the production validator and name the guard whose removal recreates the failure. Verification: 32 focused managed tests, registry 3/3, shelf gate, quick 13/13, all CI/CodeQL/Nix/type/demo checks green; CodeRabbit quota notice had no substantive finding.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-11T15:45:33Z","status":"closed","title":"Demo Packet v2: machine-readable bounded-experiment contract for every public demo","updated_at":"2026-07-11T16:02:23Z"} -{"_type":"issue","acceptance_criteria":"1. For a chosen merged agent-authored PR, the demo resolves the authoring session from session_commits/session_repos and produces a two-column claim-vs-evidence view: PR-body claim sentences beside the observed actions rows (invocation, exit_code, duration), drillable to the raw tool_result block. 2. The demo composes only existing reads (get_postmortem_bundle) with no new query machinery and includes the deleted-prose-miner motivation. Verify: run against a real merged PR and its authoring session (recorded artifact); the drill-through resolves to an actual tool_result block.","comment_count":0,"created_at":"2026-07-03T04:50:58Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:50:58Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.2","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:53:19Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:20Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:21Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:22Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:23Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:24Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.2","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":1,"description":"Pick a merged agent-authored PR; resolve PR -> authoring session via session_commits/session_repos; get_postmortem_bundle; render two columns: claimed (PR-body sentences: 'tests pass') vs observed (actions rows: the pytest invocation, exit_code, duration \u2014 drillable to the raw tool_result block). A PR body audited against ground truth in ~10 seconds. Nearly free: all reads exist. Tell the deleted-prose-miner story as part of the demo (why this exists).","design":"A demo: pick a merged agent-authored PR, resolve PR->authoring session via session_commits/session_repos, run get_postmortem_bundle, and render two columns, claimed (PR-body sentences like 'tests pass') vs observed (actions rows: the pytest invocation, exit_code, duration, drillable to the raw tool_result block). Audits a PR body against ground truth in ~10 seconds. All reads exist; tell the deleted-prose-miner story as motivation.","id":"polylogue-212.2","issue_type":"task","labels":["area:demos","delivery:L-external-legibility","lane:docs-demos-launch"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/123_polylogue_212_2.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n[2026-07-10 fable] Kit fork-prompt for this demo escrowed (.agent/handoffs/polylogue-legibility-kit-2026-07-10/fork-prompts/02-polylogue-receipts-demo.md). Two adjudicated upgrades from the GPT strategy-falsification round (dialogue entry [12]): add a COMPARATIVE baseline arm (what grep/naive search would conclude vs structural pairing) and an anti-grep control (prose containing the word error without a failed operation + a genuine structured failure whose output does not contain the word). Also gains substrate deps: prefer building on 212.11 (Incident 14:32) + 212.12 (packet v2) once they land. The private-archive Receipts BENCHMARK (n=60/60, census-gated) is a separate lane owned by the codex agent per the 2026-07-10 dialogue \u2014 this bead is the deterministic public demo only.\n[2026-07-10 fable, legibility-v2] Deterministic CONTRACT proof landed: polylogue demo receipts (PR #2662) \u2014 claim-vs-structural-receipt with later repair, anti-grep control, stable block/raw/blob refs, honest invalid_demo_evidence degradation. Per the kit v2 beads-delta (escrow .agent/handoffs/polylogue-legibility-kit-v2-2026-07-10/07-BEADS-DELTA.md) this SUPPORTS but does not close this bead: the field proof on a real merged agent PR remains the scope here. polylogue-xyel owns re-emitting it through the demo-packet contract.\n\nDEMO NAMESPACE DECISION 2026-07-13: this portfolio uses PF-D* identifiers. The archive-intelligence catalog polylogue-rxdo.10 uses AI-D*. Historical unqualified D1/D2/... text remains an alias only inside its owning parent; cross-program dependencies and external-adoption prose must use the qualified identifier.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"PF-D1 'The receipts': claim-vs-evidence on a real PR","updated_at":"2026-07-13T07:00:18Z"} -{"_type":"issue","acceptance_criteria":"1. The demo renders a five-axis cost basis with provider-reported-exact vs catalog-priced values clearly labeled and coverage stated (per-origin exact/estimate footnotes). 2. Cost-by-outcome pivot: total monthly spend, the fraction spent in abandoned or failing-final-action sessions, and the five most expensive failures, each drillable to the exact turn via the outcome-conditioned join. Verify: the demo runs via cost_rollups/session_costs against the seeded corpus (recorded output); depends on the action-outcome join bead (note dependency); `devtools test` selection covers the join query if new.","comment_count":0,"created_at":"2026-07-03T04:50:59Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:50:59Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.3","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:53:08Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:09Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:10Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:11Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:12Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:13Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.3","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":1,"description":"Five-axis cost basis shown honestly (provider-reported exact vs catalog-priced with stated coverage), then the pivot nobody else can do: cost by outcome \u2014 '$N this month; X% spent in sessions that ended abandoned or with a failing final action; five most expensive failures, click through to the exact turn.' Needs the outcome-conditioned join (action outcome fields bead); instruments otherwise exist (cost_rollups, session_costs, terminal-state profiles, per-origin exact/estimate labels rendered as footnotes).","design":"A demo: show the five-axis cost basis honestly (provider-reported exact vs catalog-priced with stated coverage), then the pivot no chat UI can do, cost by outcome: total monthly spend, the % spent in sessions that ended abandoned or with a failing final action, and the five most expensive failures each drillable to the exact turn. Needs the outcome-conditioned join (action outcome fields bead); cost instruments exist (cost_rollups, session_costs, terminal-state profiles, per-origin exact/estimate labels rendered as footnotes).","id":"polylogue-212.3","issue_type":"task","labels":["area:demos","area:usage","delivery:L-external-legibility","lane:docs-demos-launch"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/124_polylogue_212_3.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n\nDEMO NAMESPACE DECISION 2026-07-13: this portfolio uses PF-D* identifiers. The archive-intelligence catalog polylogue-rxdo.10 uses AI-D*. Historical unqualified D1/D2/... text remains an alias only inside its owning parent; cross-program dependencies and external-adoption prose must use the qualified identifier.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"PF-D2 'Where did the money actually go': cost by outcome","updated_at":"2026-07-13T07:00:18Z"} -{"_type":"issue","acceptance_criteria":"1. Six DSL queries are authored and run against the demo/seeded corpus, each producing sensible results: SEQ thrash-loop, failure-rate by model, tool-breakage by observed-event outcome, `near:` semantic probe across providers, abandoned-this-repo-this-quarter, and a query piped into `read`. 2. `explain_query_expression` is shown once demonstrating a query's parsed meaning. 3. The six queries are captured as the DSL reference-card content (committed demo/doc artifact). Verify: each query runs via `polylogue` against the `polylogue demo seed` corpus (recorded output); the demo script is exercised by the docs/visual lane where applicable.","assignee":"Sinity","close_reason":"Ran and packaged all 6 named DSL queries against the seeded demo corpus (11 sessions, 43 messages) as a conforming Demo Finding Packet under .agent/demos/d4-behavioral-archaeology/ (registered in .agent/demos/registry.json, mode public), passing devtools lab policy demo-packet-registry: (1) SEQ thrash-loop hunt seq(action:shell -> action:shell) -- 2/11 sessions match, verified via then select --json. (2) Tool call volume by tool: Bash 9, Read 8, Task 1, Write 1, exec_command 1. (3) Tool failure rate: Bash 4, exec_command 1. (4) near:\"flaky async test\" semantic probe -- 0 results, honestly attributed to the fixtures sparse embedding coverage (2/43 messages, both numerator and denominator independently cited per CodeRabbit review), not claimed as a search failure. (5) since:2y time-scoped population -- 9/11 sessions. (6) query piped into read (find origin:codex-session then read --first --view messages) -- resolves a real captured tool error and the agents next-step response. --explain shown once on query 1 proving the parsed AST. Shipped as PR #2590, merged 89e3ef445 (2 CodeRabbit findings addressed: filled a placeholder bead id, added the missing denominator citation for the 2/43 ratio).\n\nBonus: while authoring query 1, discovered and filed a real product defect (polylogue-70qb) -- bare `find \"sessions where \"` (no then-verb) silently ignores the predicate and returns the full unfiltered session list, while both `then select` and the compact query form correctly filter. Documented as a counterexample in report.md rather than hidden -- exactly the demos own thesis (a DSL query surfacing something a chat UI never could) playing out during its own authoring.\n\nAC honesty: all 3 AC clauses satisfied -- six queries authored and run producing sensible/honestly-caveated results; explain_query_expression shown once; captured as committed demo-shelf content (also doubles as informal DSL reference-card examples, though a dedicated reference-card document was not separately authored -- the queries and their syntax are demonstrated in report.md/PROMPT.md).","closed_at":"2026-07-09T00:43:35Z","comment_count":0,"created_at":"2026-07-03T04:51:00Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:50:59Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.4","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:53:02Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.4","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:02Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.4","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:03Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.4","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:04Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.4","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:05Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.4","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:07Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.4","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":1,"description":"Each answers a question an engineering lead would ask, each impossible in any chat UI: SEQ thrash-loop hunt; failure-rate by model; which tools break (observed-event outcomes by tool); near:'race condition' semantic probe across providers; abandoned-in-this-repo-this-quarter; then pipe straight into read. Show explain_query_expression once to prove the query means what it says. Nearly free: all reads exist. Doubles as the DSL reference-card content.","design":"A demo: six DSL queries, each answering a question an engineering lead would ask and each impossible in a chat UI, SEQ thrash-loop hunt; failure-rate by model; which tools break (observed-event outcomes by tool); a `near:'race condition'` semantic probe across providers; abandoned-in-this-repo-this-quarter; then a query piped straight into `read`. Show `explain_query_expression` once to prove a query means what it says. All underlying reads exist; packaging is the work, and the set doubles as the DSL reference-card content.","id":"polylogue-212.4","issue_type":"task","labels":["area:demos","area:query","delivery:L-external-legibility","lane:docs-demos-launch"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/125_polylogue_212_4.md (depth: bead-localized-from-export; urgency: T2-foundation-before-feature-proof). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n\nDEMO NAMESPACE DECISION 2026-07-13: this portfolio uses PF-D* identifiers. The archive-intelligence catalog polylogue-rxdo.10 uses AI-D*. Historical unqualified D1/D2/... text remains an alias only inside its owning parent; cross-program dependencies and external-adoption prose must use the qualified identifier.","owner":"ezo.dev@gmail.com","priority":4,"started_at":"2026-07-09T00:15:43Z","status":"closed","title":"PF-D4 'Behavioral archaeology': six DSL queries, rapid fire","updated_at":"2026-07-13T07:00:18Z"} -{"_type":"issue","acceptance_criteria":"A committed packet under .agent/demos/ where the recorded session's evidence (tool timing, exit codes, cost) annotates the session's own narrative; regeneration instructions work cold. Verify: packet passes the 212.7 shape check + cold-reader gate.","comment_count":0,"created_at":"2026-07-03T04:51:01Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T06:51:00Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.5","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:53:35Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.5","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:36Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.5","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:37Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.5","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:39Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.5","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:40Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.5","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:41Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.5","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":0,"description":"Live dev session with polylogued tailing; mid-session, query the archive for THIS session \u2014 messages typed a minute ago come back through MCP with ingest-cursor timestamps proving capture latency; end by generating the session's own postmortem before it ends. Stagecraft more than code; latency claims come from cursor rows, not assertion.","design":"The reflexive capture proof: run an agent session ABOUT polylogue while browser-capture + hooks record it, then produce the archive's account of that same session (timeline, tool calls, cost, claims) as a Demo Finding Packet (212.7 contract). The packet juxtaposes what the agent claimed in-session vs what the archive recorded \u2014 the honest-mirror demo. All substrate exists (capture e2e verified 2026-06-29; hooks channel live); this is composition + writeup, gated only by 212.7's packet shape.","id":"polylogue-212.5","issue_type":"task","labels":["area:daemon","area:demos","delivery:L-external-legibility","horizon:mid","lane:docs-demos-launch"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=D-horizon-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=D-horizon-ready.\nUNBLOCKED 2026-07-13: r4no (silent capture failure) fixed and merged (#2780) with the held-with-reason path tested; live-capture proof demo can now run without the trust caveat. Also cite 4g3n timeline (doing-nothing is a logged event) when it lands.\n\nDEMO NAMESPACE DECISION 2026-07-13: this portfolio uses PF-D* identifiers. The archive-intelligence catalog polylogue-rxdo.10 uses AI-D*. Historical unqualified D1/D2/... text remains an alias only inside its owning parent; cross-program dependencies and external-adoption prose must use the qualified identifier.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"PF-D5 'The session that watched itself': live capture proof","updated_at":"2026-07-13T07:00:18Z"} -{"_type":"issue","acceptance_criteria":"`polylogue-212.6` has an execution-grade design note before coding, lands behind the release gate `L-external-legibility`, and records a focused proof artifact. Acceptance requires one seeded positive case, one degraded/empty case where applicable, docs or generated-surface updates for any public behavior, and verification via one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof.\n\n## Corrective acceptance criteria (2026-07-13)\n\nThe descriptive demo reconstructs an unfinished session, produces an evidence-cited brief, and\nrecords actual continuation with compatibility/degradation status. A distinct matched experiment\ncompares resume treatments; without assignment/exposure receipts no causal improvement claim is\nemitted. A deliberately divergent-baseline fixture is rejected as confounded.","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-15T04:27:36Z","id":"019f6407-b96a-768c-af2a-fda621089b2c","issue_id":"polylogue-212.6","text":"[Dogfood 2026-07-15 / F-010] The known continuation command works, but unfinished-session discovery treats clean session termination as objective completion. A cleanly ended session with an explicit pending deployment decision is excluded or zero-weighted; blocker extraction is also gated off for clean_finish. New capability polylogue-37t.23 separates terminal state from objective posture. This demo now depends on it so abandoned-work triage cannot claim success from final-message presence or mere continuation."}],"created_at":"2026-07-03T13:08:23Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-03T15:08:23Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.6","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-15T06:25:18Z","created_by":"Sinity","depends_on_id":"polylogue-37t.23","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:30Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:31Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:32Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:33Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:34Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-13T07:48:34Z","created_by":"Sinity","depends_on_id":"polylogue-stc","issue_id":"polylogue-212.6","metadata":"{}","type":"related"},{"created_at":"2026-07-07T14:53:35Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"},{"created_at":"2026-07-03T15:08:23Z","created_by":"Sinity","depends_on_id":"polylogue-tsk","issue_id":"polylogue-212.6","metadata":"{}","type":"blocks"}],"dependency_count":8,"dependent_count":0,"description":"The memory-product moment as a demo: find_abandoned_sessions surfaces real abandoned work ranked by resumability; get_resume_brief composes the evidence-cited brief (every line resolvable); the operator picks one and actually continues it in the harness. Distinct from D1/D2/D4: those prove forensics; this proves the archive changes what you do NEXT \u2014 the capability the whole memory thesis rests on, demonstrated without waiting for the uplift experiment's statistics.\n\n## Authoritative corrective scope (2026-07-13)\n\nD8 remains a descriptive product proof: resume real unfinished work from cited evidence. Its causal\nevaluation is a separate matched-treatment experiment; deliberately divergent baselines are a\nconfounded control.","design":"Chain of existing primitives: find_abandoned_sessions -> get_resume_brief -> resume routing (37t.8 owns session->invocation mapping; until it lands, the demo ends with the composed `claude --resume ` command printed). Two variants per the epic rule: seeded-corpus public variant (the synthetic corpus has abandoned-session scenarios; verify scenario coverage, add one if missing) and live operator variant. Deliverable: recording via visual-tapes (3tl.5 machinery) + a workflow registry entry so `polylogue` ships the flow as a golden path, not a doc. Honesty rail: resume ranking currently keys on workflow shapes the classifier never emits (polylogue-tsk) \u2014 either land tsk first or exclude the dead scorer from the demo path; a demo must not showcase a scorer known to be 10% dead weight.\n\n## Authoritative corrective contract (2026-07-13)\n\nKeep the actual-resume flow and its evidence/compatibility receipts. Evaluate it with matched task\ninstances under different resume brief/prompt treatments using stc, with assignment, exposure,\nleakage, stopping, exclusions, and task outcomes preregistered. Do not compare intentionally easy\nversus hard prompts or call mere continuation a productivity gain. D3 runs first externally; D8 is\nthe stronger later continuity proof.","id":"polylogue-212.6","issue_type":"task","labels":["area:context","area:demos","delivery:L-external-legibility","delivery:ac-patched","horizon:mid","lane:docs-demos-launch"],"metadata":{"consumer_proof":"external-continuity"},"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=D-horizon-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=E-spec-needed.\nEASIER 2026-07-13: resume routing MERGED (37t.8 via hot-daemon lane: (origin, native_id) -> harness reopen command, continue verb emits it). D8 'pick up where I left off' now assembles from existing parts: find_resume_candidates + tsk fix + continue --exec.\n\nDEMO NAMESPACE DECISION 2026-07-13: this portfolio uses PF-D* identifiers. The archive-intelligence catalog polylogue-rxdo.10 uses AI-D*. Historical unqualified D1/D2/... text remains an alias only inside its owning parent; cross-program dependencies and external-adoption prose must use the qualified identifier.\nHorizon classification 2026-07-15: valuable retained scope, but sequenced behind named current mechanisms or proof prerequisites.\nPriority calibration 2026-07-15: P2 to P3. This remains part of the full project ambition, but it is a sequenced demo, experiment, governed analytic extension, or evaluation layer rather than a present failure of archive truth, bounded queryability, durability, or source fidelity. Priority is urgency, not deletion or scope reduction; horizon is unchanged.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"PF-D8 'Pick up where I left off': abandoned-session triage to live continuation","updated_at":"2026-07-15T20:07:24Z"} -{"_type":"issue","acceptance_criteria":"Packet schema documented + validated by the runner; one existing demo (D1 receipts) re-emitted through the runner produces a conforming packet on the seeded corpus; registry manifest lint catches a missing packet. Verify: runner fixture test + manifest check.","assignee":"Sinity","close_reason":"Built the Demo Finding Packet contract: devtools/demo_packet.py (PACKET_FILENAMES 7-file shape, PROVENANCE_STANZA_FIELDS 5-part stanza inlined provisionally pending 3tl.4, REPORT_SECTION_ORDER 8 fixed sections, validate_packet, DemoRegistryEntry, lint_demo_registry) plus devtools lab policy demo-packet-registry CLI command (plain+JSON), wired into devtools verify --lab. Proved the mechanism end-to-end with .agent/demos/_packet-contract-stub/ (a deliberately trivial fixture) registered in .agent/demos/registry.json -- devtools lab policy demo-packet-registry passes against it, and correctly fails (exit 1, names the missing packet) when a ghost registry entry is added. 18 tests passing. Shipped as PR #2589, merged 4e49b6ccd.\n\nGraph correction: found and fixed a backwards dependency edge -- 212.7 incorrectly listed 212.9 as ITS OWN blocker (212.7 blocked_by 212.9), while 212.9 itself never listed 212.7 as a dependency at all. This is backwards from the epic's own intended order (212.7 is the contract other demos including 212.9 build on; per the operators explicit chain \"212.7 (contract) -> 212.1-6/212.8 -> 1vpm.1 -> 212.9 last\"). Removed the bad edge and added the correct direction (212.7 blocks 212.9). bd-graph-lint clean after.\n\nAC honesty: the AC literally says \"one existing demo (D1 receipts) re-emitted through the runner\" -- 212.2 (D1 receipts) does not exist as an implemented demo, so this shipped the packet contract + validator proven against a stub fixture instead of the real D1 workflow. Also did not build an actual \"runner\" that invokes a coding agent against a PROMPT.md and packages the result -- what shipped is a validator (validate_packet/lint_demo_registry), not an agent-invocation harness; demos are still run by a human/agent manually per PROMPT.md, with this contract checking the output shape afterward. Filed polylogue-xyel to implement the real D1-receipts demo and register it.","closed_at":"2026-07-09T00:14:06Z","comment_count":0,"created_at":"2026-07-05T23:38:38Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:38:37Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.7","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:52:56Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:57Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:58Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:59Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:00Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.7","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:01Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.7","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":1,"description":"Convert 212 from a shelf of named demos into a PORTFOLIO CONTRACT: every demo is an executable PROMPT.md handed to a coding agent, and every prompt emits the identical Demo Finding Packet: PROMPT.md, finding.yaml (five-part provenance stanza per 3tl.4: archive cursor, measure/query version, commit SHA, sample-frame predicate, run date), report.md (fixed section order: claim, corpus, method, findings, specimens, counterexamples, limits, reproduce), evidence.ndjson (one row per cited ref), queries.ndjson (text + lowered spec), annotations.ndjson (optional), checks.json (pass/fail + unsupported claims + coverage notes), run.log. The registry manifest lists every prompt file, expected packet path, public/private mode, and required primitives \u2014 so the portfolio is enumerable and CI-checkable. Compositionality rule inherited from 212: steps are product primitives (polylogue argv), shell/python is glue only.","design":"Anchor: .agent/demos/ (existing shelf: agent-forensics, claim-vs-evidence, degraded-archive-proof, CURATED_CATALOG.md as the manifest seed). Contract: every demo directory gains PROMPT.md (executable instructions a coding agent runs cold) and emits an identical Demo Finding Packet: finding.yaml (five-part provenance stanza per 3tl.4), rendered artifact, and the exact reproduction commands. Build a registry manifest (extend CURATED_CATALOG.md or a demos.yaml) listing id, claim, packet path, substrate features exercised, last-regenerated. A prompt runner (thin script or devtools lab command) executes one demo prompt end-to-end and validates packet shape. Pitfall: demos run against the LIVE archive \u2014 packet outputs must be private-data-audited before any publication lane (3tl.4 owns publishing).","id":"polylogue-212.7","issue_type":"task","labels":["area:demos","delivery:L-external-legibility","horizon:frontier","lane:docs-demos-launch","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/120_polylogue_212_7.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\n2026-07-10 analytical follow-up: shape validation remains valid for existing packets, but it is not referential proof. polylogue-212.10 owns analytical profiles, claim/query/result/evidence resolution, sample/annotation validation, and public-transform mutation checks. Do not describe 212.7 alone as proof that an analytical packet numbers or quotes resolve.","owner":"ezo.dev@gmail.com","priority":4,"started_at":"2026-07-08T23:57:51Z","status":"closed","title":"Demo Finding Packet contract + prompt runner + registry manifest","updated_at":"2026-07-10T08:14:04Z"} -{"_type":"issue","acceptance_criteria":"Anti-demo packet passes the packet lint with not_supported verdict; report names each missing capability with the bead ref that would supply it; included in the registry manifest and the public mini-portfolio. Verify: runner emits + lint passes.","assignee":"Sinity","close_reason":"Shipped the anti-demo under .agent/demos/anti-demo-multi-source-reconstruction/ (registered in .agent/demos/registry.json, mode public), passing devtools lab policy demo-packet-registry (3/3 registry entries conform). Attempted claim: \"minute-by-minute, cross-source (chat + desktop window focus + shell history + browser tabs) reconstruction of operator activity for a given day.\" Refused with verdict: not_supported, evidenced by direct schema grep across every archive_tiers/*.py DDL file confirming zero matches for window-focus/shell-history/browser-tab telemetry tables in any Polylogue tier -- captured verbatim in run.log. Named what DOES exist (session_commits: session-grained git correlation, confidence-scored; session_repos: session-to-repo linkage) to make the gap precise rather than a vague \"not possible.\" Stated plainly that no bead currently owns cross-system (Polylogue+Lynchpin) timeline fusion, rather than inventing a plausible-sounding bead reference for an untracked capability gap. checks.json carries an additive verdict field alongside the packet contracts required pass/unsupported_claims/coverage_notes keys. Shipped as PR #2591, merged 64c079d6e.\n\nAC honesty: all 3 AC clauses satisfied -- packet passes the lint with verdict not_supported; report names the missing capability with an honest statement that no bead ref exists for it (rather than fabricating one, which would have been a worse failure mode than admitting the gap is untracked); included in the registry manifest. \"public mini-portfolio\" framing (a curated subset for external publication) is not a separately-tracked artifact yet -- this demo is committed and registry-listed, which is the concrete, verifiable part of that AC clause.","closed_at":"2026-07-09T00:51:57Z","comment_count":0,"created_at":"2026-07-05T23:38:39Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T01:38:39Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.8","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-07T14:52:51Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.8","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:52Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.8","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:52Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.8","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:53Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.8","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:54Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.8","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:52:55Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.8","metadata":"{}","type":"blocks"}],"dependency_count":6,"dependent_count":1,"description":"Ship a demo whose SUCCESS is refusal: attempt a tempting claim (e.g. minute-by-minute multi-source operator reconstruction) and emit the standard packet with verdict: not_supported, listing missing modalities, missing refs, and the exact query/evidence gap. Published BESIDE the successful demos, not hidden \u2014 this is the brand (\"refuses rather than fabricates\") made demonstrable, and it directly encodes the situation-brief praise for the honest deferral of the multi-source demo. Framing decision for operator in 212 notes: general \"no unsupported number is published\" vs concrete \"multi-source reconstruction is not ready\".","design":"Depends on the 212.7 packet contract \u2014 this demo is one more packet whose verdict field is not_supported. Pick the tempting claim: minute-by-minute multi-source operator reconstruction (needs modalities the archive lacks). The packet lists missing modalities, missing refs, and the exact query/evidence that WOULD support it, using the same finding.yaml shape. Anchor: .agent/demos// + the insight_rigor_audit surface to enumerate what evidence exists vs required. The success criterion is the refusal being specific, not vague: every missing item names the unit/table/modality that would have to exist.","id":"polylogue-212.8","issue_type":"task","labels":["area:demos","delivery:L-external-legibility","horizon:frontier","lane:docs-demos-launch","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=A-implementation-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/121_polylogue_212_8.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.","owner":"ezo.dev@gmail.com","priority":4,"started_at":"2026-07-09T00:44:16Z","status":"closed","title":"The honesty anti-demo: a tempting finding that emits verdict not_supported","updated_at":"2026-07-09T00:51:57Z"} -{"_type":"issue","acceptance_criteria":"The campaign has separate descriptive, comparative, and public children. The private descriptive packet is regenerated cold from the live archive with exact population/sample manifests and evidence-resolving labels. Comparative and public children either produce their stronger artifacts under their stated proof gates or produce explicit not_supported/held-private packets. No aggregate, quote, routing claim, or rhetoric label can survive packet validation without resolving to the declared query/result/evidence and transformation provenance.","comment_count":0,"created_at":"2026-07-06T02:51:17Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-06T04:51:17Z","created_by":"Sinity","depends_on_id":"polylogue-1vpm.1","issue_id":"polylogue-212.9","metadata":"{}","type":"related"},{"created_at":"2026-07-06T04:51:17Z","created_by":"Sinity","depends_on_id":"polylogue-212","issue_id":"polylogue-212.9","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-09T02:13:38Z","created_by":"Sinity","depends_on_id":"polylogue-212.7","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:11:02Z","created_by":"Sinity","depends_on_id":"polylogue-4c27","issue_id":"polylogue-212.9","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-07T14:53:25Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.28","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:26Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.29","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:26Z","created_by":"Sinity","depends_on_id":"polylogue-9e5.30","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:27Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.5","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-07T14:53:28Z","created_by":"Sinity","depends_on_id":"polylogue-cpf.6","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:11:04Z","created_by":"Sinity","depends_on_id":"polylogue-kmts","issue_id":"polylogue-212.9","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-10T10:11:03Z","created_by":"Sinity","depends_on_id":"polylogue-lph4","issue_id":"polylogue-212.9","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-06T04:51:17Z","created_by":"Sinity","depends_on_id":"polylogue-rxdo.7","issue_id":"polylogue-212.9","metadata":"{}","type":"related"},{"created_at":"2026-07-07T14:53:29Z","created_by":"Sinity","depends_on_id":"polylogue-svfj","issue_id":"polylogue-212.9","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:11:05Z","created_by":"Sinity","depends_on_id":"polylogue-xiyv","issue_id":"polylogue-212.9","metadata":"{}","type":"relates-to"},{"created_at":"2026-07-10T10:11:02Z","created_by":"Sinity","depends_on_id":"polylogue-y964","issue_id":"polylogue-212.9","metadata":"{}","type":"relates-to"}],"dependency_count":7,"dependent_count":0,"description":"Use Fable as the first cohort for a general delegation-analysis workflow. The first claim is descriptive: how Fable writes work orders to subagents in this local archive slice. Comparative claims about authoritarianism, routing quality, success, or behavioral effects are separate later children and may return not_supported. The campaign must use canonical delegation attempts, typed judgments, deterministic cohorts, and evidence-resolving packets; it must not introduce a Fable-specific extractor or analyzer.","design":"Three terminal children: (1) private descriptive packet over action-observed Fable delegation attempts, with coverage audit, independently reviewable labels, distributions, template sensitivity, specimens, counterexamples, and limits; (2) matched comparative extension only when dispatch-turn and child-model attribution plus controls are adequate; (3) sanitized public derivative with an explicit transformation manifest and reviewed excerpts. Structural facts remain separate from rhetoric judgments. The analysis agent may adapt its queries, but records each observation, decision, query ref, and result ref. Every unsupported layer emits a valid not_supported packet instead of bypassing Polylogue.","id":"polylogue-212.9","issue_type":"epic","labels":["area:demos","campaign","delivery:L-external-legibility","horizon:mid","lane:docs-demos-launch","tech-tree"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=L-external-legibility; lane=docs-demos-launch; readiness=D-horizon-ready; proof=one-command demo log, claims-ledger coverage report, install matrix, cold-reader proof. Original readiness=D-horizon-ready.\n[RATIFIED 2026-07-08, decision brief] Ratified path via rxdo.7 when available, interim Task-block queries fine for private packet; privacy gate at the end as designed.\n2026-07-10 stop-the-line audit supersedes the prior interim-Task-block readiness note: the shipped delegations view reverses canonical child-to-parent session_links and aliases branch points as dispatches; direct-SQL tests encode the inverse direction. The campaign must not analyze live delegations until polylogue-y964 and the evidence-card path are satisfied. Safe initial external wording is descriptive, not comparative: how Fable writes work orders to subagents in this local archive slice.\n2026-07-15 landed-core priority correction: the P1 private descriptive packet child 212.9.1 is closed. Remaining matched comparison and sanitized-public derivative are P2 and may validly return not_supported/held_private. Parent moves to P2 mid-horizon; no analytical or publication ambition is removed.\nPriority calibration 2026-07-15: P2 to P3. This remains part of the full project ambition, but it is a sequenced demo, experiment, governed analytic extension, or evaluation layer rather than a present failure of archive truth, bounded queryability, durability, or source fidelity. Priority is urgency, not deletion or scope reduction; horizon is unchanged.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Fable-as-Foreman campaign: prove delegation discourse before comparing it","updated_at":"2026-07-15T20:07:24Z"} -{"_type":"issue","acceptance_criteria":"Cold regeneration produces either a complete private analytical packet or a specific not_supported packet. The complete packet records population, action-observed/edge-only/unresolved counts, deterministic selected refs, exact-template sensitivity, annotation schema and batches, adjudication/disagreement, explicit denominators/n/missingness, specimens, counterexamples, and limits. Every label span, aggregate, and excerpt resolves to evidence. No comparative authoritarianism, success, utility, or routing-quality claim appears.","close_reason":"PR #2814 merged: fable_packet.py now has an archive-backed cold-regeneration adapter reading canonical delegations + durable annotation schema (DurableAnnotationSchema) + active assertion labels before compiling \u2014 closes the gap PR #2775's review honestly marked partial","closed_at":"2026-07-13T02:27:48Z","comment_count":0,"created_at":"2026-07-10T08:10:45Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T10:10:44Z","created_by":"Sinity","depends_on_id":"polylogue-212.9","issue_id":"polylogue-212.9.1","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-10T10:10:51Z","created_by":"Sinity","depends_on_id":"polylogue-4c27","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:52Z","created_by":"Sinity","depends_on_id":"polylogue-g8km","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:54Z","created_by":"Sinity","depends_on_id":"polylogue-kmts","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:52Z","created_by":"Sinity","depends_on_id":"polylogue-lph4","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:53Z","created_by":"Sinity","depends_on_id":"polylogue-rxdo.7","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:56Z","created_by":"Sinity","depends_on_id":"polylogue-xiyv","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:50Z","created_by":"Sinity","depends_on_id":"polylogue-y964","issue_id":"polylogue-212.9.1","metadata":"{}","type":"blocks"}],"dependency_count":7,"dependent_count":2,"description":"Produce the first honest Fable-as-Foreman artifact: how Fable writes work orders to subagents in this local archive slice. This is descriptive, private, and non-comparative. It must census action-observed attempts, disclose edge-only/unresolved coverage, label a deterministic cohort, report distributions and template sensitivity, and include typical cases, extremes, disagreements, and counterexamples.","design":"Preflight canonical delegation extraction and dispatch-model coverage. Build a deterministic population/sample manifest with exact-template caps. Use a versioned delegation-discourse schema that keeps directive mode, prohibitions, autonomy, output contract, scope control, verification demand, checkpoint/escalation, relational frame, rationale visibility, applicability, confidence, and evidence spans separate; do not compute sentiment or an iron-fist score. Import independent candidate label batches, adjudicate, join accepted labels to structural targets, aggregate with explicit denominators/n/missingness, and emit an adaptive analysis trace. If any load-bearing substrate or coverage is insufficient, emit a valid not_supported packet naming the gap.","id":"polylogue-212.9.1","issue_type":"task","labels":["area:analytics","area:demos","campaign","delivery:L-external-legibility","horizon:frontier","horizon:mid","lane:docs-demos-launch","tech-tree"],"notes":"Dep on fnm.1 removed 2026-07-13: the slice 212.9.1 needed (multi-field aggregates with denominators) merged in #2775; fnm.1's remaining scope (percentiles/time buckets) is not a blocker for the archive-backed cold-regeneration gap that keeps this bead open. Resolves the backlog's only P1-blocked-by-P2 inversion.","owner":"ezo.dev@gmail.com","priority":1,"status":"closed","title":"Produce the private descriptive Fable delegation packet","updated_at":"2026-07-13T02:27:48Z"} -{"_type":"issue","acceptance_criteria":"The packet states the matching frame, exclusions, per-cohort n/missingness, attribution coverage, labeler independence, disagreement handling, effect/uncertainty estimates, and confounds. Random agreement-sample size and invalidation threshold are declared before labeling. Removing dispatch-turn attribution or a control stratum makes the comparative claim fail or render not_supported. The descriptive packet remains valid independently.","comment_count":0,"created_at":"2026-07-10T08:10:47Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T10:10:46Z","created_by":"Sinity","depends_on_id":"polylogue-212.9","issue_id":"polylogue-212.9.2","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-10T10:10:57Z","created_by":"Sinity","depends_on_id":"polylogue-212.9.1","issue_id":"polylogue-212.9.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:57Z","created_by":"Sinity","depends_on_id":"polylogue-4c27","issue_id":"polylogue-212.9.2","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:58Z","created_by":"Sinity","depends_on_id":"polylogue-xiyv","issue_id":"polylogue-212.9.2","metadata":"{}","type":"blocks"}],"dependency_count":3,"dependent_count":0,"description":"Only after the descriptive packet is sound, test whether Fable delegation discourse differs from matched non-Fable orchestrators. The stronger claim requires dispatch-turn model attribution, matched or stratified controls, label reliability, uncertainty, and explicit confounds.","design":"Reuse the accepted delegation-discourse schema and deterministic cohort machinery. Match or stratify on repository, time, harness, task/agent type, prompt-template family, and available context. Independently relabel at least 25 percent of the comparison sample, report agreement and disagreements, and separate lexical features from judgment labels. Routing comparisons use requested and actual child identity separately. Unsupported coverage or correlated-labeler risk yields not_supported.","id":"polylogue-212.9.2","issue_type":"task","labels":["area:analytics","area:demos","campaign","delivery:L-external-legibility","horizon:mid","lane:docs-demos-launch","tech-tree"],"notes":"Priority calibration 2026-07-15: P2 to P3. This remains part of the full project ambition, but it is a sequenced demo, experiment, governed analytic extension, or evaluation layer rather than a present failure of archive truth, bounded queryability, durability, or source fidelity. Priority is urgency, not deletion or scope reduction; horizon is unchanged.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Compare Fable discourse against matched orchestrator controls","updated_at":"2026-07-15T20:07:24Z"} -{"_type":"issue","acceptance_criteria":"The public packet and thread are subsets/declared transformations of the accepted private packet, pass referential and privacy validation, distinguish live empirical provenance from seeded method reproduction, and include counterevidence and limitations. Changed private source hashes invalidate regeneration. Operator review is recorded. A held_private/not_supported outcome is valid and explicit; silent omission or invented replacement text is not.","comment_count":0,"created_at":"2026-07-10T08:10:49Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-10T10:11:00Z","created_by":"Sinity","depends_on_id":"polylogue-212.10","issue_id":"polylogue-212.9.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:10:48Z","created_by":"Sinity","depends_on_id":"polylogue-212.9","issue_id":"polylogue-212.9.3","metadata":"{}","type":"parent-child"},{"created_at":"2026-07-10T10:10:59Z","created_by":"Sinity","depends_on_id":"polylogue-212.9.1","issue_id":"polylogue-212.9.3","metadata":"{}","type":"blocks"},{"created_at":"2026-07-10T10:11:01Z","created_by":"Sinity","depends_on_id":"polylogue-3tl.4.1","issue_id":"polylogue-212.9.3","metadata":"{}","type":"blocks"}],"dependency_count":3,"dependent_count":0,"description":"Derive a public finding from the accepted private Fable packet without exposing raw operator prompts or pretending a seeded corpus reproduces the empirical result. The public hook stays bounded to claims actually supported by the private packet.","design":"Use the analytical packet profile and live-derived publication transform. Publish reviewed aggregates, typical/extreme/counterexample excerpts, limitations, and a separate seeded reproduction of mechanics. Every public claim and excerpt is selected from accepted structured private claims through public_transform.json. If safe transformation or evidence coverage is inadequate, hold private or publish not_supported.","id":"polylogue-212.9.3","issue_type":"task","labels":["area:demos","area:legibility","area:privacy","campaign","delivery:L-external-legibility","horizon:mid","lane:docs-demos-launch","tech-tree"],"notes":"Priority calibration 2026-07-15: P2 to P3. This remains part of the full project ambition, but it is a sequenced demo, experiment, governed analytic extension, or evaluation layer rather than a present failure of archive truth, bounded queryability, durability, or source fidelity. Priority is urgency, not deletion or scope reduction; horizon is unchanged.","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"Derive the sanitized public Fable finding and thread","updated_at":"2026-07-15T20:07:24Z"} -{"_type":"issue","close_reason":"PR #2864 merged (fix(storage): map v7 source revisions by name). Live v36 cutover activated successfully \u2014 source.db migration through v9 completed clean (quick_check=ok, FK check empty), proving the positional-copy bug (predecessor_source_revision shifting into revision_authority) is fixed.","closed_at":"2026-07-13T23:05:57Z","comment_count":0,"created_at":"2026-07-13T19:03:14Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Live v35\u2192v36 activation on a verified source v7 archive fails in source migration 008 with `NOT NULL constraint failed: raw_sessions.revision_authority`. The migration must preserve existing rows while installing the v8 authority invariant.\\n\\nAcceptance criteria:\\n- Upgrade a representative v7 source fixture with NULL revision_authority rows to v9.\\n- Every migrated row has semantically correct non-NULL authority.\\n- Existing backup-manifest authentication remains required.\\n- Focused regression test exercises the real migration runner.","id":"polylogue-25vy","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":0,"status":"closed","title":"Repair v7 source migration authority backfill","updated_at":"2026-07-13T23:05:57Z"} -{"_type":"issue","comment_count":1,"comments":[{"author":"Sinity","created_at":"2026-07-26T22:10:28Z","id":"019fa07a-c42c-7595-b4ca-85d545a18ed4","issue_id":"polylogue-26hv","text":"Found 2026-07-27 during a broader filesystem-organization pass: /realm/inbox/_mess/claude_huge.md (Claude 'Cross-Referential Analysis: Messages to SMH vs. Psychometric Profile', sensitive psychometric content) and /realm/inbox/_mess/2026-01-01_02-58-23_ChatGPT_I._Mathematical_formalization_of_a_system.md (ChatGPT temporary-chat export via 'Save my Chatbot' extension). Both searched by distinctive-phrase FTS against the live archive \u2014 no match; only unrelated sessions quoting the same underlying raw email material, or meta-references to the filenames. The ChatGPT one is a temporary-chat export by construction, so it will never appear in a normal GDPR/account-history ingest \u2014 this file may be the only path to ever capturing it. An exact-duplicate second copy of claude_huge.md (claude_huge_1.md) was deleted; the sole copy is untouched."}],"created_at":"2026-07-21T19:17:05Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Data-cartography campaign (spec+ledger: /realm/data/knowledgebase/ops/, master index data-cartography-2026-07.md) verified 5 chat captures absent from the archive. Ingest queue:\n1. /realm/inbox/cartography-quarantine-2026-07/6a3f9296-3500-83eb-b31b-f4ccf9720574.md \u2014 chatgpt 'DMS Analysis and Structure', 4409 nodes, no id/content match.\n2. /realm/inbox/cartography-quarantine-2026-07/2026-06-27_22-19-13_Claude_Chat_Optimizing_NixOS_Configuration_Blueprints_-_Claude_-_https.md \u2014 claude a9790559-8755-475c-b6a1-7ead43d80c66, absent.\n3. /realm/inbox/polylogue-browser-spool-2026-07-10/chatgpt/6a506bcf-852c-83eb-82e6-e23ac8a418e1-d42dead8db48.json \u2014 'Project Explanation and Relevance', 21 turns.\n4. /realm/inbox/polylogue-browser-spool-2026-07-10/chatgpt/6a50b7cc-0b24-83eb-bd15-2edadd846f2b-1e4985548d7c.json \u2014 'Branch \u00b7 Project Attachment Comparison', 328 turns (never-ingested sibling fork of indexed 6a506b3f).\n5. /realm/inbox/hermes-project-comparison-browser-capture/ \u2014 chatgpt-export:temporary:b5e53115cf353f807b9708f5 temp chat, Borg-recovered, only copy (packet README documents identity).\nMinor: grok dom-e4e24461 (X/Twitter DOM capture in the spool) has no session home.\nAfter ingest+verification, the source files become dedup-verified and join the deletion queue in the cartography ledger.","id":"polylogue-26hv","issue_type":"task","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Ingest capture-gap sessions found by 2026-07 data cartography","updated_at":"2026-07-21T19:17:05Z"} -{"_type":"issue","acceptance_criteria":"Standalone excision removes a seeded span across source/user/index/FTS/embeddings/blob refs, and ordinary local re-ingest does not resurrect it. Against a fault-injecting versioned Sinex contract fake, mirror/primary requests remain visibly pending through simulated network loss and restart, deleting ops.db preserves the durable request, rejection cannot report success, and primary invalidates local replicas only after a synthetic confirmation. This bead does not claim a real Sinex purge, clean Sinex rebuild, disconnected-replica closure, or backup-restore proof; polylogue-303r.6 owns those integration proofs. Blob deletion obeys 83u refs/leases. Secret scanning finds a fake credential as a non-injectable candidate without storing or logging the value. Dry-run, confirmation, and audit behavior matches kwsb.\n\n## Corrective acceptance criteria (2026-07-13)\n\nA seeded secret-bearing definition is exercised as ad-hoc, promoted, used in a finding/report,\nembedded, and backed up. Dry-run enumerates every affected ref and tier. Apply removes or tombstones\nall in-scope copies, reconciles replicas through 303r.6, preserves unrelated promoted history, and\nemits a complete receipt. Re-running all resolvers finds no unreported surviving copy.","close_reason":"The standalone/off-mode excision and candidate-secret contract landed on master in PR #2875 (c2fd1e902), including non-resurrection and durable mirror/primary request mechanics. Real Sinex lifecycle/replica proof remains explicitly owned by polylogue-303r.6; later promoted query/finding/report consumers retain their own privacy wiring obligations.","closed_at":"2026-07-14T23:05:04Z","comment_count":0,"created_at":"2026-07-03T17:01:33Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-13T10:49:10Z","created_by":"Sinity","depends_on_id":"polylogue-b5l","issue_id":"polylogue-27m","metadata":"{}","type":"related"},{"created_at":"2026-07-04T21:47:44Z","created_by":"Sinity","depends_on_id":"polylogue-kwsb","issue_id":"polylogue-27m","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":1,"description":"Own Polylogue-local excision mechanics and secret-candidate intake without creating a second backed-mode lifecycle authority. Standalone/off mode can authoritatively excise local evidence. Mirror/primary mode implements the durable lifecycle-request/outbox and local pending/invalidation mechanics against the versioned Sinex contract and a fault-injecting fake; polylogue-303r.6 owns binding those mechanics to real Sinex confirmation, purge, residual, rebuild, and backup proof. Secret detection remains candidate-only and never logs matched values.\n\n## Authoritative corrective scope (2026-07-13)\n\nExcision covers analysis provenance before broad query persistence: durable definitions, short-lived\n@last payloads, promoted relation members, findings, judgments/experiments, reports/manifests,\nvectors, exports, and derived/backed replicas.","design":"REUSED MECHANISMS:\n- polylogue-kwsb owns destructive-operation dry-run/confirmation/audit conventions;\n- polylogue-83u owns blob refs, leases, reference accounting, and byte acquisition/GC integrity;\n- polylogue-4be owns real restore-from-backup verification in polylogue-303r.6;\n- polylogue-303r.6 owns real backed-mode authority, privacy_invalidation_scope, transport/replica residuals, Sinex confirmation, and non-resurrection proof.\nNo parallel purge vocabulary.\n\nLOCAL/CONTRACT SCOPE:\n- off/standalone: source.db redaction/tombstone plus affected local-tier rebuild is authoritative. Durable source/user rows record removed-hash marker, reason, actor, prior revision, and no-secret span coordinates. ops.db may mirror diagnostics but is not audit authority.\n- mirror: create a durable user.db lifecycle-request/outbox record before local mutation. Local views may hide the target immediately, but state remains pending. A versioned contract fake exercises acknowledgement, rejection, retry, and confirmation without claiming a real Sinex purge.\n- primary: emit the same durable request and wait for a contract confirmation before local replica invalidation. The fake proves ordering and crash recovery only.\n- polylogue-303r.6 replaces the fake with real Sinex, owns capability/retention/purge semantics, and proves clean-rebuild and backup non-resurrection.\n\nLocal excision recomputes the content revision and records aliases/tombstones so ordinary local re-ingest cannot resurrect content. Blob removal uses 83u reference/lease discipline. Scanning emits secret_candidate assertions with span refs and no literal secret; accepted candidates enter the same mode-aware local/request operation.\n\n## Authoritative corrective contract (2026-07-13)\n\nUse one purge/excision vocabulary and plan-authorize-apply-receipt-reconcile lifecycle across these\nsurfaces while retaining per-tier actuators. Resolve lineage/derivation edges before apply, report\nheld/unsupported replicas explicitly, and prove completion by re-query plus artifact/backup\nreconciliation. Ad-hoc ops payloads are independently addressable and may be removed without\ndeleting promoted history.","id":"polylogue-27m","issue_type":"task","labels":["area:ops","area:substrate","delivery:A-trust-floor","horizon:frontier","lane:security-privacy"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=A-trust-floor; lane=security-privacy; readiness=A-implementation-ready; proof=negative Host/Origin/token/spool/security fixture suite. Original readiness=A-implementation-ready.\n[Prework packet 2026-07-07] Static execution packet (anchors, mechanism, plan, tests, verification): .agent/handoffs/polylogue-gpt-pro-2026-07-07/prework-v2/task_packets/131_polylogue_27m.md (depth: bead-localized-from-export; urgency: T1-critical-path-correctness). Generated from master @ 8a975a40 2026-07-06 \u2014 verify source anchors before coding; line numbers are snapshot-relative.\nEDGE DEMOTED 2026-07-13 (backlog-structure pass): blocks-dependency on b5l (blue-green rebuilds) converted to related. Rationale: excision can purge derived index copies through the EXISTING rebuild path (ops reset --index + reingest) \u2014 degraded for the rebuild window but correct. b5l removes the downtime, an operational-quality improvement, not a hard correctness prerequisite; blocks=hard-ordering-only per tech-tree conventions. This un-blocks the P1 excision lane.\n[Implementation 2026-07-14] PR #2875 (branch feature/security/excision-secret-hygiene-27m): implements the ORIGINAL (non-corrective) scope in full -- standalone/off-mode local excision, candidate-only secret scanner, and mirror/primary durable lifecycle mechanics against a fault-injecting SinexContractFake.\n\nScope satisfied:\n- Standalone excision removes a seeded session across source.db/index.db/embeddings.db/blob_refs/user.db (real cross-tier DELETE, not a toy replica) -- tests/unit/security/test_excision.py.\n- Ordinary local re-ingest does not resurrect excised content: new durable `excised_content` ledger (source.db migration 010, SOURCE_SCHEMA_VERSION 9->10) consulted at the single acquire-time write chokepoint `write_source_raw_session` (shared by CLI import + daemon watch path). ContentExcisedError is caught by the batch orchestrator (skip-not-abort) so one excised file cannot abort a whole re-ingest run. Proven via a real `parse_sources_archive` round trip through the synthetic-corpus fixture generator, not a hand-rolled JSONL.\n- Mirror/primary requests remain visibly pending through simulated network loss and a simulated process restart (fresh SinexContractFake instance, same durable row); an ops.db deletion does not erase the request (it lives in user.db); rejection cannot report success (LifecycleInvalidationOutcome.success is False with an explicit reason for every non-confirmed state); primary invalidates local replicas only after a synthetic confirmation -- tests/unit/security/test_excision_lifecycle.py.\n- Blob deletion obeys 83u refs/leases: excision removes blob_refs/raw_sessions rows and lets the existing reference-counted blob GC reclaim bytes on its own next run; no direct blob unlink.\n- Secret scanning finds a fake credential (AWS/GitHub/Slack/OpenAI/Anthropic key shapes, PEM headers, JWTs, entropy-filtered generic assignment) as a non-injectable SECRET_CANDIDATE assertion (author_kind=\"detector\" -> forced CANDIDATE + non-inject via the shared upsert_assertion chokepoint) without storing or logging the matched value anywhere -- tests/unit/security/test_secret_scan.py includes an explicit \"no matched literal anywhere in the database file\" byte-scan assertion.\n- Dry-run/confirmation/audit matches the reset command's kwsb-style conventions (--dry-run, --yes, --json emitting MutationResultPayload) -- polylogue ops excise.\n\nExplicitly deferred / NOT claimed (per the bead's own non-goal, this bead's design text, and its own AC): a real Sinex purge, a clean Sinex rebuild, disconnected-replica closure, or a backup-restore proof. SinexContractFake is test-only; nothing in this repo drives a mirror/primary request against a real Sinex confirmation yet. polylogue-303r.6 owns that binding.\n\nThe 2026-07-13 \"Authoritative corrective scope/AC\" text (analysis-provenance: query definitions, @last payloads, promoted relation members, findings, reports/manifests, vectors) depends on substrate that does not exist as production-wired runtime yet (rxdo.2/rxdo.3's query-definition/promotion/evaluation-receipt tables landed schema-only per their own notes -- \"no production callers\", \"envelopes not populated\"). Treated as out of this PR's honest scope: there is no promoted query-definition/finding/report pipeline in production for excision to hook into yet. Flagging as a misframed-for-now corrective AC rather than silently skipping it -- worth a follow-up bead once rxdo.2/rxdo.3/303r.6 have real runtime wiring to excise against.\n\nVerification: devtools verify --quick (exit 0); devtools test tests/unit/security/test_secret_scan.py tests/unit/security/test_excision.py tests/unit/security/test_excision_lifecycle.py tests/unit/cli/test_excise.py (41 passed); devtools test tests/unit/storage/test_durable_migrations.py (33 passed, 4 pre-existing tests updated for the new migration version); devtools test tests/unit/security/test_no_secret_leak_in_logs.py (2 passed); devtools lab policy schema-versioning (intact).\n\nPR: https://github.com/Sinity/polylogue/pull/2875","owner":"ezo.dev@gmail.com","priority":1,"status":"closed","title":"Excision and secret hygiene: the archive can forget on purpose","updated_at":"2026-07-14T23:05:04Z"} -{"_type":"issue","acceptance_criteria":"From an agent session over MCP: record_correction, add_tag, blackboard_post succeed and their rows carry the authoring session ref; delete_session without confirm parameter is refused; affordance-usage report shows the write calls. claude-lean profile remains read-only.","assignee":"Sinity","close_reason":"Completed implementation and rollout: Sinnix commit 7151697 is live via switch; Claude/Codex full/evidence/browser generated MCP configs pass --role write and lean passes --role read; Polylogue MCP add_tag and record_correction now accept author_ref/author_kind and persist them to assertion-backed user rows; blackboard_post already carried author attribution; delete_session confirm contract remains covered. Proof: focused devtools test selection over tag/correction/blackboard/MCP schema/user-tier paths passed 10 tests; devtools verify --quick run 20260704T161955Z-quick-636992-6314bf9b passed. Fresh-agent affordance-usage observation moved to follow-up polylogue-ahqd because this Codex process predates the Home Manager activation.","closed_at":"2026-07-04T16:20:57Z","comment_count":0,"created_at":"2026-07-03T13:08:20Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"The entire feedback flywheel is agent-inaccessible in practice: server_mutation_tools.py implements add_mark/add_tag/bulk_tag/blackboard_post/record_correction/annotations/saved views/workspaces/recall packs \u2014 but the registered agent-facing MCP server runs role='read'. Agents can query but cannot leave a correction, tag a session, post to the blackboard, or file a candidate assertion, so the candidate->judgment loop cannot spin without manual operator entry. OPERATOR DIRECTION (2026-07-03): agents get MORE power and affordances, not a curated subset \u2014 the safety mechanism is attributability (every agent action is itself captured in the archive and auditable), not capability restriction.","design":"(1) Default agent profile runs the FULL mutation role: marks, tags, bulk tagging, annotations, corrections, blackboard, saved views, workspaces, recall packs, metadata, candidate assertions \u2014 and the maintenance/deletion tools stay available rather than stripped; a destructive call (delete_session) should demand an explicit confirm parameter in the tool contract, not be absent. Assertion PROMOTION remains a judgment act by design of the memory model (candidates land inject:false), but agents can create, update, and argue for candidates freely. (2) Audit-not-gate: every mutation tool result includes the actor identity + session ref of the calling agent session (the archive already captures the calling session; make the write row carry the authoring session ref so 'which agent wrote this and why' is one query \u2014 user.db assertion rows already have author_ref, extend the same discipline to marks/tags). (3) Registry wiring is sinnix-side: flake/data/mcp-registry.nix flips claude/codex full profiles to the mutation role (claude-lean can stay read). polylogue side is build_server(role=...) which already exists. (4) Registration traps memory applies for any new tool name: EXPECTED_TOOL_NAMES + TOOL_CONTRACT + render openapi/cli-output-schemas regen. (5) Contract smoke: mutation role can record a correction AND delete-with-confirm on the seeded corpus; write rows carry author session refs. (6) Measure adoption via affordance-usage after rollout; if agents still do not write, the friction is discoverability (the cookbook bead), not permissions.","id":"polylogue-27p","issue_type":"feature","labels":["area:context","area:mcp","spine","wave:1"],"notes":"Implementation checkpoint 2026-07-04: Sinnix commit 7151697 pushed to master adds profile-specific Polylogue MCP args: full/evidence/browser -> --role write, lean -> --role read, with runtime generation assertions for Claude/Codex/Gemini. Polylogue-side contract proof: devtools test tests/unit/mcp/test_contract_evidence.py tests/unit/mcp/test_per_tool_contracts.py tests/unit/mcp/test_tag_idempotency.py tests/unit/mcp/test_blackboard_tools.py tests/unit/mcp/test_cli.py -> 222 passed. Direct registry proof: nix eval of selectClientServersForProfile gives full/evidence/browser [--role write], lean [--role read]. Not closed yet because live Sinnix activation and an affordance-usage observation after agents use write tools remain to be recorded.\nCheckpoint: MCP write-role config implemented in Sinnix; live activation/adoption observation remains\nCheckpoint: Closed MCP write-role rollout; follow-up polylogue-ahqd owns fresh-agent adoption report","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-04T16:02:41Z","status":"closed","title":"Agent MCP write access: full mutation surface, audited not restricted","updated_at":"2026-07-04T16:22:34Z"} -{"_type":"issue","acceptance_criteria":"Repro-or-postmortem artifact recorded in bead notes; a synthetic hang (test sleeping forever while the master keeps emitting output) is detected and killed within the stall window by the new detector; idle_s in .cache/verify/current-pytest-progress.json reflects event staleness during an active run; VERIFY: devtools test tests/unit/devtools -k \"verify and (stall or progress or heartbeat)\" plus a manual synthetic-hang demonstration logged in notes.","assignee":"Sinity","close_reason":"Fixed devtools/verify.py:_run_pytest_with_heartbeat to key stall detection off test-event progress (devtools/pytest_progress_plugin.py events, cross-worker via latest_event_from_paths), not just raw output bytes. Root cause confirmed: the xdist master keeps emitting its own output/heartbeat chatter while every worker is D-state-wedged, so the old output-silence-only check never fires -- the 45-minute ceiling was the only real backstop.\n\nAdded a parallel progress-staleness signal: last_progress_marker tracks the latest test events own updated_at timestamp; last_progress_at is the local monotonic time that marker was last observed to change. The stall check fires on EITHER output silence (existing) OR progress silence (new), gated behind seen_any_progress_event. Fixed the idle_s=0.0 hardcode: idle_s now consistently reports progress-event staleness.\n\nNew regression test (test_pytest_run_terminates_on_progress_stall_despite_flowing_output) reproduces the exact confirmed hang shape.\n\nVerify: devtools test tests/unit/devtools/test_verify.py -k \"progress_stall or output_stall\" (2 passed); devtools test tests/unit/devtools/test_verify.py (60 passed); devtools verify --quick green. Merged as PR #2581.\n\n(Re-closed: an earlier close of this bead was reverted by a concurrent bd import race in this shared-checkout session -- see memory concurrent-agent-same-checkout-collision.)","closed_at":"2026-07-08T18:47:08Z","comment_count":0,"created_at":"2026-07-08T17:29:36Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Two confirmed hangs on 2026-07-08 (bd memory devtools-verify-testmon-forkserver-deadlock): the default `devtools verify` testmon step (-n 4 xdist) stalls with all 4 workers in D-state at ~8-10% CPU for 30+ minutes. The stall detector (devtools/verify.py:577) fires only on OUTPUT silence; the xdist master keeps emitting, so it never fires and the 45-min ceiling (verify.py:192) is the only backstop. Worse, the progress ledger hardcodes idle_s=0.0 on every output event (verify.py:607), so monitoring actively lies during the hang. Consequence: the standing operator guidance is \"never run bare devtools verify\", which erodes the local pre-merge net at exactly the time per-PR CI runs no tests (ci.yml:48-49). The heartbeat already samples worker /proc state, cpu_pct, and the latest pytest event nodeid (verify.py:616-632) - all the ingredients for honest stall detection are collected but unused.\n","design":"(a) Reproduce under controlled conditions: testmon --testmon-forceselect -n 4 after a multi-file change; when hung, capture py-spy dump / /proc//stack of D-state workers. Suspects: testmon sqlite (testmondata) contention under xdist, tmpfs basetemp IO, or forkserver+coverage interaction. Record the postmortem in bead notes even if not fully root-caused. (b) Event-ledger stall detection: terminate (existing rc-124 path, verify.py:678-692) when no NEW pytest event (tests/infra events ledger consumed at verify.py:628) arrives within the stall window AND worker processes show D/S state with ~0 CPU; keep output-silence detection as the secondary trigger. (c) Write honest idle_s: time since last EVENT (not last output write) on all progress-file writes, including the event=output branch. (d) Surface the termination diagnosis (state summary, last event nodeid) in VerifyRun + current-run.json so postmortems do not require live observation. Interacting beads: none tracked previously; memory devtools-verify-testmon-forkserver-deadlock is the evidence trail.\n","id":"polylogue-27rb","issue_type":"bug","labels":["area:devloop","area:test","horizon:frontier"],"owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-08T18:46:50Z","status":"closed","title":"Testmon+xdist D-state deadlock: root-cause + stall detection keyed on test-event progress, not output bytes","updated_at":"2026-07-08T18:47:08Z"} -{"_type":"issue","acceptance_criteria":"1. /realm/db/polylogue's user.db and source.db (at minimum; ideally all durable tiers) are captured by an automated backup job that survives the nested-subvolume gap \u2014 verified by restoring a fresh archive/snapshot produced by that job and confirming it is NOT the empty-directory artifact (i.e. actually contains current-content .db files, not zero bytes).\n2. A follow-up restore drill (or an ad hoc check) confirms `borg list db/polylogue` (or wherever the new job's target path is) shows real file entries, not just the bare directory.\n3. Either the nested-subvolume conversion is reverted (preferred if no independent-subvolume semantics are actually needed) or the dedicated backup job is deployed and its timer is active with a passing first run.\n4. A systematic audit of /realm's other nested subvolumes for the same gap is recorded (even if fixing all of them is out of scope for this bead).","comment_count":0,"created_at":"2026-07-27T16:44:18Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Discovered 2026-07-27 while executing the first real restore drill (polylogue-4be). `/realm/db/polylogue` (the actual on-disk location of the live archive tiers; `/realm/data/captures/polylogue/*.db` are symlinks to it) was converted to its own nested Btrfs subvolume on 2026-07-06 (`btrfs subvolume list /realm` shows `ID 3862 gen 196381 top level 5 path db/polylogue`).\n\nbtrbk snapshots and borgbackup-job-realm both operate on the PARENT `/realm` subvolume only. A nested subvolume does not get recursed into by a parent snapshot \u2014 it shows up as an empty directory in every snapshot and every Borg archive since 2026-07-06. Verified directly: `borg list db/polylogue` returns only the bare directory entry (`drwxr-xr-x root root 0 ... db/polylogue`) with zero children \u2014 none of `user.db`, `source.db`, `index.db`, `ops.db`, `embeddings.db`, or the `blob/` store are present.\n\nThis is the exact same failure class that `sinex`'s blob repository hit (fixed by adding the dedicated `borgbackup-job-sinex-blobs.service`) and that `state/machine-telemetry`/`db/machine-telemetry` hit (fixed by adding `machine-telemetry-sqlite-backup.service`, a `sqlite3 .backup` + zstd job run directly against the live db path rather than relying on the parent snapshot). Polylogue's durable tiers (`user.db` irreplaceable, `source.db` rebuild-root) currently have no equivalent dedicated backup job \u2014 they have been completely unprotected by Borg since the nested subvolume was created 2026-07-06.\n\nThe polylogue-4be restore drill only produced a real durable-tier restore because an older, already-durable pre-deploy backup snapshot happened to sit under `/realm/inbox/polylogue-backups/` (a plain directory, not a nested subvolume, so it IS covered by borg-realm-v2). That snapshot is 17+ days stale and not a substitute for continuous coverage of the live tiers.","design":"Fix in sinnix (not polylogue): add a dedicated backup job for /realm/db/polylogue's durable tiers, following the machine-telemetry-sqlite-backup.service pattern (modules/services/machine-telemetry.nix:347-424) \u2014 `sqlite3 \".backup ''\"` against user.db and source.db directly (bypassing the nested-subvolume snapshot gap entirely), zstd-compress, retain N generations locally, then drain into Borg (either the existing borg-realm-v2 repo via an explicit archive path, or a small dedicated repo like borg-sinex-blobs-v1's pattern). Also consider: (a) whether /realm/db/polylogue should simply NOT be a nested subvolume at all \u2014 if there's no reason it needs independent snapshot/quota semantics from /realm, converting it back to an ordinary directory would eliminate the whole gap class for free; (b) auditing all of /realm for other nested subvolumes with the same invisible-to-snapshot problem (only sinex, db/machine-telemetry, and db/polylogue found so far via `btrfs subvolume list /realm`, but the audit should be systematic, not ad hoc). This bead belongs in sinnix's tracker/CLAUDE.md workflow, not polylogue's \u2014 filed here first since it was discovered during a polylogue-scoped task; move/mirror to sinnix if that repo has its own separate tracking substrate.","id":"polylogue-2a6d","issue_type":"bug","labels":["area:ops","horizon:frontier","lane:operational-resilience"],"notes":"2026-07-27 correction: the 'zero Borg coverage' framing was too broad. polylogue-sqlite-backup.service (sqlite3 .backup direct on live files, staged into /realm/staging/polylogue-sqlite/, weekly timer) already exists and DOES get backed up by Borg -- verified directly: latest borg archive (realm-realm.20260727T213000+0200, taken ~90min before this check) contains staging/polylogue-sqlite/{source,user,index,ops}-20260726T030458Z.sqlite.zst. Manually triggered a fresh run this session (21:56-21:58 CEST): source.db and user.db both integrity_check=ok, dated 2026-07-27T19:56:07Z. The REAL gap is narrower than originally framed: only the DIRECT filesystem-level snapshot of the nested /realm/db/polylogue subvolume is invisible to Borg -- this separate content-level backup path is real, working, and weekly. Still worth a dedicated fix (the sinnix-side nested-subvolume gap for defense-in-depth), but this is not a 'zero coverage since 07-06' situation as first stated.","owner":"ezo.dev@gmail.com","priority":1,"status":"open","title":"Live polylogue durable db (/realm/db/polylogue) has zero Borg coverage \u2014 nested btrfs subvolume invisible to realm snapshot","updated_at":"2026-07-27T20:01:17Z"} -{"_type":"issue","acceptance_criteria":"A committed demo-shelf packet with regeneration commands; every number carries frame + validity caveats; excluded-ground section names the four blocking beads; at least one finding is genuinely non-obvious (not a restatement of counts); no claim exceeds Claude-side data honesty.","comment_count":0,"created_at":"2026-07-17T23:15:13Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Warroom deliverable (operator-approved 2026-07-18): a Fable-authored v0 of the fable-as-foreman analysis/demo \u2014 how coordinator sessions treat their subagents \u2014 using ONLY data that is honest today: Claude Code Task sidechain lineage (~7.4k subagents), delegation_facts/action_pairs (PR #3018), MCP topology/tree/workflow-shape/session-work-events surfaces, and the t8t parallel-agent known-answer population (129 coordinator children). Products: delegation-shape distributions (fan-out, depth, child duration), child outcome proxies from structured tool results, foreman-instruction characterization via material_origin, wasted-vs-used child heuristics with explicit validity caveats, and a written findings note on the demo shelf. Known excluded ground (stated in the artifact, not silently): Codex delegations (polylogue-j2zz), compaction mis-parented children (polylogue-4ts.3), honest child terminal-state labels (vhjs/wofr annotation program), claim-to-repository-effect join (polylogue-1vpm.6.2, in flight). Full demo upgrades after those land.","design":"Read-only against the live archive (POLYLOGUE_ARCHIVE_ROOT export pitfall). Prefer first-party representation per the It.12 discipline: register core selections as named durable queries with result sets/receipts where the production write routes allow; findings follow the Lane A analysis-kernel vocabulary once it lands (if Lane A has not merged, keep findings in the demo README and file the promotion as follow-up). Shelf location: .agent/demos/foreman-v0/ with README + regeneration commands + cold-reader-gate checklist. Target: Sunday 2026-07-20, after wave intake settles.","id":"polylogue-2asj","issue_type":"task","owner":"ezo.dev@gmail.com","priority":2,"status":"open","title":"Foreman v0: coordinator subagent-treatment analysis over Claude-side archive data","updated_at":"2026-07-17T23:15:13Z"} -{"_type":"issue","acceptance_criteria":"1. A merge where chunk 1 has title=None and chunk 2 carries a real title yields the real title; placeholder(=session id) titles are still replaced. 2. A merge with duplicate provider_message_ids yields exactly one is_active_leaf=True (the final positional message). 3. Regression tests cover both via parse_stream_payload on synthetic chunked JSONL.","comment_count":0,"created_at":"2026-07-17T00:45:17Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"description":"Audit finding 2026-07-17, sources/dispatch.py merge_parsed_session_chunks (~line 444). Two data-quality defects on the streaming Claude Code merge path (parse_stream_payload -> merge of _claude_code_stream_sessions chunks): (1) TITLE: the merge keeps existing.title unless it equals existing.provider_session_id. When the first chunk has title=None (common for early JSONL slices), None != provider_session_id, so the merged session keeps None forever and a real title arriving in a later chunk is dropped. Fix shape: prefer the first non-empty, non-placeholder title: existing.title if (existing.title and existing.title != existing.provider_session_id) else (session.title or existing.title). (2) ACTIVE LEAF: merged messages recompute is_active_leaf as provider_message_id == last message provider id; with duplicate provider ids (variants/retries) MULTIPLE messages get is_active_leaf=True in one session, feeding MCP payloads (mcp/payloads.py:429) and archive_query message output. Same comparison pattern exists in parsers/antigravity.py:410 \u2014 fix should pin uniqueness (flag only the last positional occurrence) and add a shared regression test with duplicate provider_message_ids across merged chunks.","id":"polylogue-2hwl","issue_type":"bug","owner":"ezo.dev@gmail.com","priority":3,"status":"open","title":"merge_parsed_session_chunks drops later-chunk titles and can multi-flag active leaf","updated_at":"2026-07-17T00:45:17Z"} -{"_type":"issue","acceptance_criteria":"Decision recorded (a vs b) with consumer audit; DDL change lands with the next batched index-tier bump; measured index size reduction and whale-replace write time on the benchmark corpus; query surfaces reading pair text keep byte-identical outputs via the join.","assignee":"Sinity","close_reason":"AC complete. (1) Decision recorded: direction (a) \u2014 full consumer audit showed every reader goes through the actions VIEW; one-join view rewrite re-serves tool_input/output_text from blocks byte-identically (golden fixtures pinned pre-change pass unchanged). (2) DDL landed with the v41 index bump (#3159, IndexDeltaDeclaration CACHE_REMOVAL+VIEW_ONLY). (3) Measured on the promoted live archive 2026-07-22 via dbstat: action_pairs = 1.05 GB / 1,808,715 rows (~580 B/row) at the FULL 83K-session corpus, vs 4.1 GB (~4.7 KB/row) measured on v40 at a PARTIAL corpus \u2014 the overflow-chain class is gone; whale-replace: the v40 walk died on a single >3h whale write, the v41/v42 walk completed the entire 101,347-raw corpus (36 passes, 662.9 min driver total) including that whale. (4) Byte-identity via join proven by unchanged golden fixtures + planner-stats USING INDEX assertions. Residual duplication in delegation_facts text tracked as polylogue-m8nj; v40 declaration gap tracked as polylogue-5h5y.","closed_at":"2026-07-21T22:57:30Z","comment_count":0,"created_at":"2026-07-19T13:19:32Z","created_by":"Sinity","dependency_count":0,"dependent_count":0,"design":"Found 2026-07-19 via dbstat on the live rebuild generation: action_pairs = 4.10GB for 868,522 rows (~4.7KB/row) vs blocks = 4.61GB \u2014 the pair table stores COPIES of tool_input and output_text, so every tool interaction exists ~3x (blocks.text/search_text, action_pairs.output_text/tool_input, plus messages_fts when populated). Consequences measured live: (1) index.db ~19.6GB where content would suggest half that; the b-tree working set exceeds page cache and whale session replaces degrade to storage-bound random IO (164MB/s reads observed); (2) write amplification \u2014 refresh_action_pairs (called per session write AND by the ad/ai/au trigger family for non-writer mutations) does DELETE-all + INSERT-all of the session pairs including the text copies, so a whale replace rewrites GBs; (3) every byte is paid again in backup/checkpoint/cache. Design directions (decide explicitly): (a) action_pairs stores only the join/rank/outcome columns (tool_use_block_id, tool_result_block_id, session_id, message_id, tool_id, use_rank, tool_name, semantic_type, tool_command, tool_path, is_error, exit_code) and text is read from blocks by block_id at query time (the actions VIEW already joins; read surfaces need the join added \u2014 audit consumers of action_pairs.output_text/tool_input via rg); (b) keep tiny previews (first N chars) for list surfaces, full text via join. Derived-tier schema change: canonical DDL + INDEX_SCHEMA_VERSION bump + rebuild (batch with other pending index-tier changes per schema regime). Cross-ref: the FTS-empty bulk-mode bead (skip action_pairs refresh during bulk entirely), l3tk (this table was also the planner-pathology site), 20d interactive perf (smaller table = better cache behavior for the action-heavy queries).","id":"polylogue-2i2w","issue_type":"task","notes":"2026-07-19 implementation trail (worktree agent-ab497ea4f525afdd2):\n\nConsumer audit: grepped every reader of action_pairs.output_text/tool_input across storage/repository, insights, daemon, MCP, CLI, api, webui-facing SQL. Result: EVERY consumer reads through the `actions` VIEW (polylogue/storage/sqlite/archive_tiers/index.py) -- none reads action_pairs columns directly except the DDL/refresh/lifecycle machinery itself (action_pairs.py, write.py's refresh_action_pairs calls, schema_bootstrap.py's stat1 seed rows, archive_verification.py's planner-stats-coverage table-name list, lifecycle.py's clear-projection-rows table list). This meant direction (a) could be implemented by changing ONE join in the `actions` view -- zero changes needed in api/archive.py, storage/repository/archive/sessions.py, storage/sqlite/queries/{tool_usage,filter_builder}.py, daemon/http.py, cli/commands/status.py, sources/import_explain.py, demo/{receipts,constructs}.py, devtools/{affordance_usage,daemon_workload_probe}.py. One indirect consumer: delegation_facts_source/delegation_facts (subagent-dispatch cohort) reads actions.tool_input/output_text and materializes its OWN copy (instruction_payload/artifact_text) -- also transparently fixed by the view rewrite (verified via tests/unit/storage/test_delegations_view.py + tests/unit/pipeline/test_delegation_provider_fixtures.py passing unchanged); filed polylogue-m8nj to track that this smaller table still duplicates a subset of the text (out of scope here, never measured via dbstat).\n\nImplemented direction (a): action_pairs drops tool_input/output_text (polylogue/storage/sqlite/archive_tiers/index.py DDL + polylogue/storage/sqlite/action_pairs.py refresh SQL); the `actions` VIEW now INNER JOINs blocks by tool_use_block_id (NOT NULL FK, cascade) and LEFT JOINs blocks by tool_result_block_id (nullable, SET NULL) to re-serve tool_input/output_text at read time, same column names/order, so every reader is byte-identical with zero code change.\n\nSchema: INDEX_SCHEMA_VERSION 40->41. Added IndexDeltaDeclaration(version=41, classes=(CACHE_REMOVAL, VIEW_ONLY), ...) to polylogue/storage/sqlite/lifecycle.py (copy-forward safe, no semantic reparse). Discovered PRE-EXISTING gap: v40 (query_unit_frame_state, PR #3068) never got a declaration -- confirmed independent of this change by reverting my files to HEAD and re-running `devtools lab policy schema-versioning` (same \"missing: [40]\" failure before my edit). Filed polylogue-5h5y to track/fix that gap separately; left it unfixed here to keep this PR's blast radius to action_pairs.\n\nNoted this bump on polylogue-bo9n and polylogue-v6i3 per the task's batching instruction (their own decisions NOT implemented -- session_events aggregation and FTS-bulk-mode work both remain open).\n\ndocs/internals.md: added the \"Index schema version 41\" changelog entry ahead of v37 (v38/v39/v40 already had no entries -- pre-existing gap, not backfilled here).\n\nByte-equivalence proof: tests/unit/storage/test_archive_tiers_ddl.py already pins exact output_text/tool_command/is_error/exit_code values through the `actions` view across matched/unmatched/error/reemitted-tool_id/variant-tie/empty-string-tool_id scenarios (test_archive_tiers_index_generates_ids_and_actions_view, test_actions_view_pairs_reemitted_tool_id_by_transcript_rank_not_cross_product, test_actions_view_ranks_variant_messages_deterministically, test_actions_view_never_cross_pairs_empty_string_tool_id) -- all pass unchanged post-rewrite, which IS the golden-fixture proof (values pinned before this change, reproduced by the new join-based view). test_agent_action_and_delegation_views_are_indexed_projections (asserts \"USING INDEX\" in the actions-view query plan, and no WINDOW/WITH in the view SQL) also still passes -- confirms the rewritten view still resolves via action_pairs's indexes, and the join doesn't introduce a CTE/window into the view itself. Added a new regression test (test_action_pairs_does_not_materialize_text_copies) asserting action_pairs' exact column set no longer includes tool_input/output_text. tests/unit/sources/test_codex_event_stream_contract.py's hand-rolled action_pairs schema updated to match (join blocks for output_text in its final assertion) -- exercises the same real refresh_action_pairs/action_pairs_refresh_sql production code.\n\ntest_planner_statistics_seed.py (session-scoped index-usage plan assertion) passes unchanged -- confirms the trimmed refresh SQL still resolves via idx_blocks_session_position, not a full tool_use-population scan.\n\nVerification: devtools test on all directly-touched + consumer test files (tests/unit/sources/test_codex_event_stream_contract.py, tests/unit/storage/test_archive_tiers_{ddl,write,assertions}.py, tests/unit/storage/test_planner_statistics_seed.py, tests/unit/maintenance/test_archive_verification.py, tests/unit/storage/test_schema_policy_contracts.py, tests/unit/insights/test_tool_usage.py, tests/unit/storage/test_delegations_view.py, tests/unit/pipeline/test_delegation_provider_fixtures.py, tests/unit/storage/test_schema_safety.py) = all green except 4 pre-existing failures in test_tool_usage.py/test_delegations_view.py (\"unknown database user_tier\" / \"unable to open database file\" -- confirmed identical failure count/names on unmodified HEAD via checkout+revert, unrelated to this change). devtools verify --quick exit 0. devtools render all --check exit 0 (no \"out of sync\"). devtools lab policy docs-drift: zero unhandled drift. devtools lab policy schema-versioning: 1 pre-existing failure (v40 gap, tracked as polylogue-5h5y), no new failures from v41. Broader testmon-affected `devtools verify` run in progress at time of this note (seeding testmon fresh in this worktree).\n\nIndex-size estimate (not directly measured -- no live archive access from this isolated worktree per the isolation preamble): the removed tool_input/output_text bytes are essentially ALL of the ~4.7KB/row action_pairs footprint (the surviving 12 join/rank/outcome columns are short strings/ints/ids, already part of that row and small by comparison), so action_pairs should collapse from ~4.1GB to a small fraction of that (likely low hundreds of MB, in-page, no more overflow chains) once a real archive is rebuilt on this schema -- i.e. most of the measured 4.1GB is expected to be reclaimed from index.db's ~19.6GB total. This needs confirming with a real `polylogue ops reset --index && polylogued run` + dbstat pass on an actual generation, which is the coordinator's call per the task brief.\n2026-07-19 16:45: OPERATOR DECISION executed \u2014 path (B): #3159 merged (8b8d5b165, v41), pass10 killed, v40 generation gen-1784422147106 abandoned (19.6GB + 8 census scratch orphans queued for post-promote cleanup), fresh v41 rebuild launched as a new operation. Rationale: single v40 whale write exceeded 3h (overflow-chain cost this PR removes); one v41 rebuild does strictly less total work than v40-finish + mandatory v41 cycle. Census receipts persist; replay restarts clean on slim pairs.","owner":"ezo.dev@gmail.com","priority":1,"started_at":"2026-07-19T14:02:29Z","status":"closed","title":"action_pairs materializes full text copies: ~2x index bloat and massive write amplification","updated_at":"2026-07-21T22:57:30Z"} -{"_type":"issue","close_reason":"PR #2794 merged: durable capture_mode evidence added before Origin collapse (v8 migration), GEMINI vs Drive now distinguishable for future captures, pre-migration provenance stays unknown rather than fabricated. Byte-identical dual-mode captures sharing one raw ID is out of this bead's scope, tracked separately at polylogue-buns.","closed_at":"2026-07-13T00:04:29Z","comment_count":0,"created_at":"2026-07-12T05:28:27Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-12T07:28:33Z","created_by":"Sinity","depends_on_id":"polylogue-4rrv","issue_id":"polylogue-2ilz","metadata":"{}","type":"discovered-from"}],"dependency_count":0,"dependent_count":0,"description":"polylogue-4rrv built a Source-family family_hint disambiguator for provider_from_origin (core/sources.py) so a caller with independent context can recover Provider.GEMINI vs Provider.DRIVE for an Origin.AISTUDIO_DRIVE session. Investigation while building it proved this only helps callers that already have that context out-of-band (e.g. an explicit user filter parameter) -- it structurally cannot recover the acquisition mechanism for an *already-ingested* session, because no current storage tier persists it:\n\n- sessions (index.db) only stores `origin`, not `provider`/acquisition mechanism (PRIMARY KEY(origin, native_id); session_id is a generated column off origin+native_id).\n- raw_sessions (source.db) also only stores `origin`, no finer field.\n- session_profiles.source_name is set directly from session.origin (storage/insights/session/profiles.py:341), same collapse.\n- The two providers share one parser (sources/parsers/drive.py, DRIVE_LIKE_PROVIDERS = {GEMINI, DRIVE}) and produce structurally identical JSON shapes (chunkedPrompt/chunks) regardless of acquisition mechanism, so re-parsing raw bytes cannot re-derive it either -- detect_provider() is shape-based only and both fibers are indistinguishable in content. The distinguishing signal (live Google-Drive-API poll vs offline Takeout/AI-Studio export bundle) exists only at acquisition/config time in sources/live/batch_support.py and sources/drive/gateway.py, and is discarded by the time a session is written.\n\nFixing this for real (recovering which fiber member every already-ingested and future aistudio-drive session came from) needs a durable additive column -- most likely on raw_sessions (source.db, durable tier) capturing the acquisition-time provider/capture-mode before the Origin collapse, following the additive-migration + backup-manifest schema regime (see CLAUDE.md \"Schema regimes\"). Historical rows acquired before the column exists would need to stay NULL/unknown (no way to backfill without re-acquiring), which should be made explicit in any read surface that reports it.","design":"Add a nullable capture_mode or acquisition_provider TEXT column to raw_sessions (source.db) via a new numbered migration under storage/sqlite/migrations/source/, populated at write time from the already-known runtime_provider in the acquisition/parsing pipeline (pipeline/services/ingest_batch, sources/dispatch.py's _lower_payload_specs) before it collapses to origin. Backfill is not possible for historical rows; document that explicitly. Once persisted, provider_from_origin's family_hint parameter (polylogue-4rrv) can be fed from this column at read time for genuine per-session disambiguation, closing the loop this bead's advisory-only hint mechanism could not.","id":"polylogue-2ilz","issue_type":"task","labels":["area:substrate","discovered-from:polylogue-4rrv"],"owner":"ezo.dev@gmail.com","priority":3,"status":"closed","title":"Durable capture-mode field to split GEMINI export vs live-Drive AISTUDIO_DRIVE sessions","updated_at":"2026-07-13T00:04:29Z"} -{"_type":"issue","acceptance_criteria":"(Vision \u2014 no fabricated AC) Requires: fs1.10 SpecCard schema landed; a first hand-built card set (~10 issues) proving the reconstruction recipe; leakage policy written. States WHY: turns the repo's own history into an honest agent-eval asset no public benchmark provides.","comment_count":0,"created_at":"2026-07-03T04:51:21Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:13:27Z","created_by":"Sinity","depends_on_id":"polylogue-rxdo","issue_id":"polylogue-2jj","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"Research lane (gpt-pro synthesis + raw-log agent-evals idea): closed beads/issues with their authoring sessions become benchmark tasks \u2014 time-to-first-patch, search depth, question count, spec-mismatch count, rework, context tokens to green; and the raw-log variant: agents experiment with their own setup (context/memory configurations) and store judged observations as assertions. Needs the beads-history ingestion bead + uplift experiment machinery first; park until both exist.","design":"Real closed issues as a coding-agent benchmark: sample N closed polylogue GH issues with verifiable outcomes (merged PR + tests), reconstruct the pre-fix repo state (base commit before the fix PR), and package issue text + repo ref + the fix PR's test as SpecCards (fs1.10 schema \u2014 internal schema first, adapters second per the D07 doctrine). The archive adds what SWE-bench lacks: the ORIGINAL agent sessions that solved each issue become reference trajectories (recorded_reward semantics from fs1.5). Leakage gate: agents evaluated on these must not have the fix in training/context \u2014 timestamp partitioning documented per card.","id":"polylogue-2jj","issue_type":"task","labels":["area:analytics","delivery:N-horizon","horizon:vision","lane:horizon-spec","research"],"notes":"[Delivery upgrade 2026-07-07T00:05:00Z] Release=N-horizon; lane=horizon-spec; readiness=D-horizon-ready; proof=decision memo or execution-grade spec with explicit pull-forward gate. Original readiness=D-horizon-ready.\n[RATIFIED 2026-07-08, decision brief] Ratified as vision; park until fs1.10 + cfk machinery; leakage gate is load-bearing.\nUNPARKED 2026-07-13: beads-history ingestion landed (#2800). Remaining prerequisite is the uplift/experiment machinery (wnse eval_run object + rxdo.9.10). Sequence: wnse -> this.","owner":"ezo.dev@gmail.com","priority":4,"status":"open","title":"IssueBench: real issues as coding-agent effectiveness benchmarks","updated_at":"2026-07-13T04:02:33Z"} -{"_type":"issue","acceptance_criteria":"Classify the intended raw-artifact contract after write_parsed. If parsed_at is authoritative, update the fixture to use frozen time and assert the exact parsed timestamp; if it should remain absent on this path, repair the production write. The exact node passes on master and a regression distinguishes acquired-only from parsed raw rows.","assignee":"Sinity","close_reason":"Fixed in PR #3355: classified parsed_at as the authoritative raw-artifact lifecycle contract (set once at parse finalize, never rewritten by later materialize/index). Pinned test_archive_tiers_api_raw_artifacts_read_source_tier to frozen_clock (frozen_clock_modules on polylogue.storage.sqlite.archive_tiers.archive) asserting the exact parsed_at ISO value, and added a finalize_raw_parse=False regression proving acquired-only rows keep parsed_at=None until finalize. No production write needed repair. Anti-vacuity verified: removing the frozen-clock marker breaks the exact-timestamp assertion against real wall-clock time; forcing always-finalize breaks the acquired-only None assertion.","closed_at":"2026-07-27T20:46:17Z","comment_count":0,"created_at":"2026-07-12T10:32:03Z","created_by":"Sinity","dependencies":[{"created_at":"2026-07-15T19:07:02Z","created_by":"Sinity","depends_on_id":"polylogue-2qx","issue_id":"polylogue-2kvn","metadata":"{}","type":"parent-child"}],"dependency_count":0,"dependent_count":0,"description":"On current origin/master e5e607f89, tests/unit/api/test_facade_contracts.py::test_archive_tiers_api_raw_artifacts_read_source_tier deterministically fails in isolation: write_parsed now populates raw_sessions.parsed_at, while the expected raw-artifact payload still asserts parsed_at=None. Discovered during the polylogue-g8km affected-route batch; it reproduces unchanged on master and is unrelated to delegation query/card changes.","design":"Define raw-artifact lifecycle timestamps from state transitions, then derive all writer and reader behavior from that contract: acquired_at records durable raw acquisition, parsed_at is set exactly when a parsed write for that raw identity commits, and later materialize/index activity cannot rewrite it. Canonical raw-artifact fixtures use the frozen clock and cover acquired-only, parsed, reparse, failed-parse, and idempotent replay. Generated/API expectations consume the same lifecycle declaration rather than hand-maintaining null assumptions.","id":"polylogue-2kvn","issue_type":"bug","labels":["area:api","area:durability","area:test","discovered-from:polylogue-g8km","horizon:frontier"],"notes":"Horizon classification 2026-07-15: deterministic raw-lifecycle contract drift is execution-grade; priority remains P3 until evidence shows production timestamp semantics are wrong rather than the fixture.\nPriority correction 2026-07-15: promoted P3 to P2 during invariant review. The bead covers a current single-writer, resource-containment, durable-lifecycle, verification-gate, or interactive-latency contract with concrete evidence; promotion does not automatically admit it to the active execution set.","owner":"ezo.dev@gmail.com","priority":2,"started_at":"2026-07-27T20:46:05Z","status":"closed","title":"Align raw-artifact parsed_at contract with parsed writes","updated_at":"2026-07-27T20:46:17Z"} -{"_type":"issue","acceptance_criteria":"Every sink identified (web_shell.py onclick/action-rail interpolation, web_shell_attachments.py row builder) uses a single escaping helper proven correct for its context (HTML text vs HTML attribute vs JS string-in-attribute -- three different escaping rules, not one escAttr for all). Negative-test fixtures: attachment/session with mime_type/origin/meta containing quotes, backslashes, angle brackets, and script tags must render inert in the captured HTML output (assert absence of unescaped