Skip to content

Connect original sources, board previews and personal planning across experiences - #2866

Open
Chris0Jeky wants to merge 61 commits into
mainfrom
codex/2808-overhaul-integration
Open

Connect original sources, board previews and personal planning across experiences#2866
Chris0Jeky wants to merge 61 commits into
mainfrom
codex/2808-overhaul-integration

Conversation

@Chris0Jeky

@Chris0Jeky Chris0Jeky commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Taskdeck now keeps original sources, saved thinking and personal planning connected across Classic, Studio, Companion and Unified. This main-based integration preserves the individually reviewed commits from #2852, #2855, #2856, #2857, #2861, #2870 and #2872 through #2877. It continues #2808; the wider overhaul remains open.

  • Companion explicitly selects private original text and retains exact source receipts. Ten-item indexed cursors keep complete histories accessible, including ordinal zero and modality gaps. Source permissions, revisions and blocked sends remain enforced.
  • Private audio retains original bytes before any answer or transcription exists. Drafts bind to the question revision present when they begin; question removal preserves unuploaded drafts. The original library keeps earlier sources discoverable, uses bounded metadata reads and preserves host413 errors. Both account-export routes hold a consistent read snapshot across their five source-storage sections.
  • Chat and both Review layouts open a checked proposal overlay on saved board objects. Both board renderers show affected cards/columns without applying changes. Close, expiry, access changes and stale responses retract markers; approval and Apply remain in Review.
  • The personal plan shares List/Board/Horizon and Focus across experiences. Classic Home resumes saved Focus in both renderers. Calendar-day deadlines retain their date in western time zones; Today/tomorrow use local days without rescheduling cards.
  • Manual comparison files retain stable identities and compatible imports across releases and HTTP LAN use. Grove themes and all switchable experiences remain available; no telemetry, random assignment or statisticalA/B claim.

Verification

Combined local evidence at the final integration runtime:

  • Full backend solution: 9,186 passed, 34 existing skips (Domain 1,639; Application 4,258; API 3,011; CLI 243; Architecture 28; Integration 7).
  • Full frontend:6377passed,3existing skips across412files. Typecheck and productionbuild pass.
  • Sixteen selected Chromium journeys have passing evidence: initial combined batch15pass/1ambiguous test locator; after selecting the memory checkbox by role, the complete contextual and original-source specs both pass. Includes four experiences,both board renderers,LAcalendar dates,Classicresume,375px/nooverflow/accessibility,source permissions,exact audio bytes,review/apply and3production-policy cases.
  • Two comparisonidentity and two audio-policy Nodecontracts,11failure-ledger projection tests,doclinks/governance/diffchecks pass.
  • Each feature has one bounded independent review. The fresh combined interaction review is CLEAN for HIGH/CRITICAL. Runtime merged without conflict; additive documentation conflicts were reconciled without dropping feature evidence. No commits squashed.

Earlier failed evidence is retained: old navigation-dialog names, the newly ambiguous memory-title locator, and a manually appended generated ledger entry. Locators now target the actual controls; ledger entries live in JSONL with a regenerated Markdown projection. These are identified causes, not blind reruns or claims of flakiness.

Remaining scope

Automatic transcription/provider processing, broader original-representation backfill and export graph work, observation usefulness/opt-in attention, plan failure/navigation/load-coalescing refinements and comparison appearance attribution remain tracked under #2808. Source-storage consistency does not claim one snapshot across every account section or tested restoration. Physical microphones/devices,liveproviders,productiondeployment and release/owner decisions remain unverified. OUTSTANDING_TASKS.md human choices are unchanged.

All browser databases are synthetic under C:/Taskdeck-overhaul/evidence; temporary services are stopped. The primary checkout and working database are untouched. Exact-head hosted checks must pass before merge. Keep contained PR branches until the integration lands, then reconcile their PR/project state and late comments.

…omparisons

# Conflicts:
#	docs/IMPLEMENTATION_MASTERPLAN.md
…omparisons

# Conflicts:
#	docs/STATUS.md
#	docs/product/WORKSPACE_OVERHAUL_VALIDATION.md
@Chris0Jeky

Copy link
Copy Markdown
Owner Author

Final recovery qualification

Head75f92c71e preserves private audio/text drafts by disabling question-layer removal (including an already-open removal prompt) until the draft is kept or explicitly discarded. Hosted finding3974598891 is confirmed HIGH due to browser-only recording loss and is repaired. Fresh bounded Luna repair review is CLEAN. 18 targeted components, typecheck, production build, scopedESLint and docs/governance pass.

Required run34424282948 at9bac failed exactly two retired dialog-title locators (207passed/13skipped/2failed). Both now name the actual Leave this thinking space? dialog. Both full specs passed locally: seven Chromium journeys in47.6s, isolated real API. The failed log is preserved; no blind rerun or weakened behavior assertions. Exact-head hosted qualification restarts on75f92c71e. Temporary5218/5318 services are stopped.

Hosted finding3974598894 (enabled retained-send control) is MEDIUM and already implemented in stacked PR2870. The source-export snapshot finding3974598902 is being scoped separately under #2808; its disposition will record actual snapshot boundaries rather than claim restore acceptance.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75f92c71e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


public Task<Result<ThinkingAudioDto>> WriteAsync(Guid userId, Guid id, ThinkingAudioWriteDto dto, CancellationToken ct) => TransactionAsync(async () =>
{
var answer = await OwnedAsync(userId, id, ct);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject writes after the source question changes

When another collaborator edits or removes the question after this recording was loaded, OwnedAsync verifies only ownership and active-board access, so the stale PUT still appends a written representation to the old recording. ConfirmAsync performs the missing current-question/hash check, and the retained library otherwise treats recordings whose questions changed as read-only; resolve the question and compare QuestionHash before staging this transcript.

Useful? React with 👍 / 👎.

Comment on lines +135 to +137
<button type="button" :disabled="!text.trim() || !dirty || busy || loading || !sourceReady" @click="write">Save written version</button>
<label>How to treat the confirmed answer<select v-model="status" aria-label="Audio answer status" :disabled="pending"><option value="statement">Statement</option><option value="assumption">Assumption</option><option value="unknown">Unknown</option><option value="needsReview">Needs review</option></select></label>
<button type="button" :disabled="!saved.representationId || dirty || busy || loading || !sourceReady || answerAlreadyKept" @click="confirm">Confirm written version as my answer</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disable mutations after an unsuccessful reload

When a reload fails, load() sets loaded to false but leaves the prior saved receipt rendered; these Save and Confirm buttons can therefore appear enabled even though mutate() immediately returns when !loaded. This occurs after a failed manual reload or a failed reload triggered by a question revision, leaving controls that silently do nothing; include !loaded in both disabled predicates or otherwise mark the retained receipt non-actionable.

AGENTS.md reference: frontend/AGENTS.md:L5-L5

Useful? React with 👍 / 👎.

Comment on lines +59 to +60
saved.value = next; loaded.value = true
if (!hadDraft && text.value === initialText) text.value = next?.writtenVersions.find(x => x.id === next.representationId)?.text ?? ''

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep written drafts accessible after question revisions

When the user has an unsaved written version and then saves an edit to the shared question, the revision reload returns no matching recording and this assignment replaces saved with null while deliberately retaining text. The !saved template renders only the audio recorder, so the written draft remains dirty but becomes invisible with no way to copy or discard it; the revision repair tracks only file drafts, so preserve a visible stale-written-draft state before replacing the receipt.

AGENTS.md reference: frontend/AGENTS.md:L5-L5

Useful? React with 👍 / 👎.

@Chris0Jeky

Copy link
Copy Markdown
Owner Author

Final disposition of hosted feedback after9bac:3974598891 is HIGH due to loss of browser-only drafts and is repaired in75f92c71e;18focusedcomponents,7browserjourneys,typecheck/build and independent Luna repair reviewpass.3974598894 is MEDIUM disabled-control consistency, already addressed inPR2870.3974598902 is MEDIUM archival source-section consistency, confirmed statically and now implemented in local source-export-snapshot31087565d:11realAPItests pass and independentLunareviewCLEAN;fullbackendqualification is running before publication. Whole-account point-in-time/restore acceptance remains explicitly outside that narrow claim.

Current integrationheade3be111a9 adds only the generated-ledger correction after75f92c71e:11projectiontests,doclinks/governance/diffpass. The exact cause of the prior docs failure is recorded in the canonical JSONL and regenerated Markdown. RequiredCI is requalifying; no merge with failing or missing checks.

# Conflicts:
#	docs/product/WORKSPACE_OVERHAUL_VALIDATION.md
# Conflicts:
#	docs/IMPLEMENTATION_MASTERPLAN.md
#	docs/STATUS.md
#	docs/product/WORKSPACE_OVERHAUL_VALIDATION.md
# Conflicts:
#	docs/IMPLEMENTATION_MASTERPLAN.md
#	docs/STATUS.md
#	docs/product/WORKSPACE_OVERHAUL_VALIDATION.md
@Chris0Jeky Chris0Jeky changed the title Deliver original sources, audio library and retained comparisons together Connect original sources, board previews and personal planning across experiences Sep 10, 2026
@Chris0Jeky

Copy link
Copy Markdown
Owner Author

The consolidated head a5abe34 preserves the reviewed inputs through #2877. Fresh bounded Luna review of cross-slice identity/cursor/send gating, overlay close/expiry, export snapshot/library and Classic plan continuity found no HIGH/CRITICAL integration defect. Full backend passed 9,186 tests with 34 existing skips; full frontend passed 6,377 with three existing skips; build/typecheck passed. Sixteen selected browser journeys have passing evidence after one checkbox-locator correction and a complete two-spec rerun. The production audio policy, comparison identity and generated-ledger checks also pass. Detailed evidence and limitations are in the updated PR body and workspace validation document.

Exact-head hosted CI remains pending. This PR is the single main-based integration gate; contained source PRs should be reconciled after it lands. #2808 remains open for the remaining product capabilities and acceptance work.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a5abe349e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +40 to +44
const status = (cause as { response?: { status?: number } }).response?.status
if (status === 403 || status === 404) {
items.value = []; loaded.value = false; nextAfterOrdinal.value = -1; emit('change', [])
error.value = 'You no longer have access to these private originals. Check board access before retrying.'
} else error.value = 'Originals could not be checked. Retry, or refresh all sources if this memory changed.'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear selections when the memory revision conflicts

When an original is already selected and another client revises its memory before the user loads the next page, the source endpoint returns 409, but this branch retains the loaded items and emitted selection. The send controls therefore remain enabled even though ResolveAsync will reject every attempted message using that stale revision; treat 409 as an invalidated selection by clearing it or disabling it until all sources are refreshed.

AGENTS.md reference: frontend/AGENTS.md:L3-L6

Useful? React with 👍 / 👎.

services.AddScoped<IManualRepresentationStore, EfManualRepresentationStore>();
services.AddScoped<IThinkingAudioRepository, ThinkingAudioRepository>();
services.AddScoped<ISourcePortabilityStore, SourcePortabilityStore>();
services.TryAddSingleton(_ => configuration.GetSection("SourceStorage").Get<BlobStorageSettings>() ?? new BlobStorageSettings());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate source-storage quotas during startup

When an operator supplies a nonpositive SourceStorage override such as SourceStorage__OwnerQuotaBytes=0, this singleton binding allows the application to start successfully, but the first audio upload reaches SqliteBlobStore.CheckQuota, throws InvalidOperationException, and becomes a generic 500. Register these settings with range validation and ValidateOnStart, as is already done for database settings in this method, so deployment mistakes fail before user traffic.

Useful? React with 👍 / 👎.

@Chris0Jeky

Copy link
Copy Markdown
Owner Author

Bounded hosted-feedback reconciliation at the combined checkpoint:

  • 3974815071: MEDIUM source-write consistency follow-through. Written alternatives can still be appended to an owned retained recording after its question changes; confirmation remains guarded. Track the current-question/hash gate with the remaining audio lifecycle work in Continue prototype interactions, context and continuity after the switchable overhaul #2808.
  • 3974815077: MEDIUM control-state defect. Failed audio reload retains a receipt whose mutation handler refuses action, but Save/Confirm can still appear enabled. Track explicit disabled state in the same follow-through.
  • 3974815082: MEDIUM draft recovery defect. A question revision can hide retained written draft text when the matching receipt disappears; the dirty guard retains it in memory, but a visible recovery/copy/discard surface is needed. Track under Continue prototype interactions, context and continuity after the switchable overhaul #2808 with an explicit regression case.
  • 3975016183: MEDIUM stale-selection feedback. A pagination 409 retains source selection; server resolution rejects it before model processing. Track picker invalidation and recovery under Continue prototype interactions, context and continuity after the switchable overhaul #2808.
  • 3975016187: MEDIUM startup validation. Invalid operator quota configuration fails at first upload; add options validation during the source-storage follow-through.

These are accepted, tracked product follow-through items, not a new broad audit or an approval/Apply bypass. No new HIGH/CRITICAL path was established in this bounded triage. The consolidated shipping head remains a5abe34; required CI is still pending. The independent plan-operation recovery and comparison-attribution continuations proceed separately.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7886fc93cc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +145 to +147
var answer = await OwnedAsync(userId, id, ct);
if (answer.ConfirmedMemoryId.HasValue) return await MapAsync(answer, ct);
if (answer.Revision != dto.ExpectedRevision || answer.RepresentationId != dto.RepresentationId) throw Conflict();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject mismatched retries after audio confirmation

When another tab has already confirmed the recording, this early return accepts any subsequent confirm payload without validating its revision, representation, deck revision, or status. For example, a stale tab can request assumption after the first tab stored statement and receive 200 even though that status was not persisted; preserve lost-response idempotency only when the request matches the completed confirmation and return a conflict otherwise.

AGENTS.md reference: backend/AGENTS.md:L22-L25

Useful? React with 👍 / 👎.

Comment on lines 307 to +310
// The send already succeeded and its messages are retained locally. A
// failed reconciliation must not hold continuation behind read retries.
const result = await chatApi.getSession(sessionId, { skipRetry: true })
if (isDisposed || requestedSessionId !== sessionId || selectedSession.value?.id !== sessionId) return
if (!isCurrent()) return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Put a timeout on the post-send receipt refresh

When this GET remains pending because the API or connection stalls, chatApi.getSession forwards only skipRetry and the shared Axios client has no request timeout. Since the send path awaits this refresh while refreshingReceipt disables every send control, the successfully sent conversation can remain blocked indefinitely without ever reaching the new retry/error state; give this reconciliation read a bounded timeout or cancellation path.

Useful? React with 👍 / 👎.

Comment on lines +171 to +175
<router-link
v-if="proposal.boardId && !props.readOnly && ['PendingReview', 'Approved'].includes(normalizeProposalStatus(proposal.status))"
class="td-review-card__links-dropdown-item"
role="menuitem"
:to="{ path: `/workspace/boards/${proposal.boardId}`, query: { proposalId: proposal.id } }"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expose board preview for non-Queue proposals

When Classic/Legacy Review displays a Chat or Manual/MCP proposal, ReviewProposalCard.hasProvenanceContext is false because it recognizes only Queue capture references. This link is nested inside the surrounding v-if="hasProvenance" block, so those pending or approved board proposals never receive the new Preview on board action, even though Paper Review exposes it independently; place the preview action outside the capture-provenance-only disclosure.

Useful? React with 👍 / 👎.

Comment thread autodoc/AGENT_INDEX.md

| Domain | Entry points | Invariants (load-bearing) | Verify |
| --- | --- | --- | --- |
| Private audio answers | `Api/Controllers/ThinkingAudioController.cs` → `Application/Services/ThinkingAudioService.cs`; `CaptureIntakeService.StageAudioAnswerAsync` is the canonical capture writer; `Infrastructure/Storage/SqliteBlobStore.cs`, `Repositories/EfManualRepresentationStore.cs`, `Repositories/SourcePortabilityStore.cs`; frontend `components/thinking/ThinkingAudioAnswer.vue` + `AudioAnswerRecorder.vue`; owner library `components/workspace/OriginalAudioLibrary.vue` from Memory, API `library` list/detail/original | Audio alone is untranscribed/unanswered; explicit human writing and confirmation are separate immutable representations. Owner-scoped bytes and current board access; read-only library also permits archived boards with current permission and owner-linked deleted-board originals; upload ID/hash retry; question/revision conflicts; quotas before bounded reads; caller transaction; account erasure deletes representation dependants before source assets. No queued/remote transcription. Legacy representation backfill is separate. Avoid generated migration designers except for schema work; product/status sync: `docs/product/WORKSPACE_OVERHAUL.md` + validation ledger and STATUS/MASTERPLAN | API `ThinkingAudioApiTests`, `SqliteBlobStoreTests`, `ManualRepresentationStoreTests`, `DataPortabilityApiTests`; frontend `ThinkingAudioAnswer.spec.ts`, `AudioAnswerRecorder.spec.ts`, `OriginalAudioLibrary.spec.ts`, `ThinkingQuestionAnswer.spec.ts`, `ThinkingWorkspaceContinuity.spec.ts`; Chromium `tests/e2e/thinking-audio.spec.ts` with an isolated `TASKDECK_E2E_DB`; full backend/frontend per CLAUDE before PR |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reconcile the Context Fabric entries with the implementations

This new seam row declares SqliteBlobStore, EfManualRepresentationStore, and SourcePortabilityStore as the production entry points, but the existing Context Fabric row at line 47 and its linked architecture map still say IBlobStore/IRepresentationStore are contract-only with no implementation registered. Because this index is the repository's required first-hop seam map, the contradictory entries can send subsequent work away from the newly shipped persistence path; update the older entries as part of this implementation change.

AGENTS.md reference: AGENTS.md:L13-L16

Useful? React with 👍 / 👎.

@Chris0Jeky

Copy link
Copy Markdown
Owner Author

Required CI34434084906 passed at7886fc93; before merge, main had advanced through the separate CI-adapter PR2864 to c6a97b7. Reconciled that base to d0e08d5. Backend/frontend/deployment product inputs remain unchanged; new continuation tests and doclinks pass. The new exact-head gate is running; no merge is claimed.

New hosted comments are classified once as MEDIUM and retained under #2808: 3975276160 (reject mismatched retries of an already-confirmed audio answer), 3975276166 (bound post-send receipt reconciliation), 3975276175 (show preview for non-Queue proposals in Legacy Review), and 3975276181 (reconcile older Context Fabric interface-map entries with concrete source stores). They do not authorize board writes, overwrite originals or change access boundaries, and will be handled in focused follow-through rather than restarting this reviewed application diff.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0e08d570b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +97 to +99
if (!live) return
if (playbackUrl.value) URL.revokeObjectURL(playbackUrl.value)
playbackUrl.value = URL.createObjectURL(blob)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Discard playback responses after recording changes

When playback starts and the shared question is revised before the download finishes, the revision reload can clear or replace saved, but this response is still accepted because it checks only live, not the requested recording ID or generation. If the revised question already has—or subsequently receives—a recording, the stale blob is rendered and downloaded under the new receipt and filename; capture the request generation/recording ID and discard or revoke responses after the receipt changes.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

Status: Review

Development

Successfully merging this pull request may close these issues.

1 participant