Skip to content

fix: complete consolidated cleanup audit - #170

Closed
looptroop-ai wants to merge 12 commits into
mainfrom
fix/consolidated-cleanup-audit
Closed

looptroop-ai wants to merge 12 commits into
mainfrom
fix/consolidated-cleanup-audit

Conversation

@looptroop-ai

Copy link
Copy Markdown
Owner

Summary

  • Complete the consolidated cleanup, recovery, security, and delivery audit already on this branch.
  • Accept help and ? as aliases for per-command CLI help alongside --help.

Verification

  • npm exec -- vitest run --project server-integration server/cli/__tests__/cliUpdate.test.ts
  • npm run build:server
  • npm exec -- eslint server/cli/cli.ts server/cli/__tests__/cliUpdate.test.ts
  • Website npm run verify:site

…alog state

Resolve Windows executable siblings through PATHEXT before trust checks, preserve safe arguments across command wrappers, and recognize verified user-namespace mappings. Regenerate both installers from the accepted resolver source.

Recover installer locks immediately only for confirmed dead owners, release owned locks on interruption, and refuse unsafe replacement when a damaged binary cannot establish daemon state. Reject empty PowerShell values and restore verified Linux Node guidance.

Preserve YAML payload text through formatting repairs, enforce canonical alias priority without changing distinct-field precedence, retain accurate repair warnings, and guard cache invalidation with complete parser-source hashes.

Reconcile asynchronous modal history, correct overlay Escape and focus behavior, and release mobile-drawer containment after resizing or losing ticket data. Update app documentation, audit dispositions and the Unreleased changelog; published website changes are reviewed separately.

Each packet passed an independent Astra review with focused regression checks. Full repository integration and packaging checks remain scheduled after the remaining audit packets; native Windows and end-to-end checks are not claimed.
Install container dependencies from the release lockfile while retaining the npm tarball runtime layout. Record installed image package versions and attest the finished multi-architecture digest in isolated jobs with explicit registry login.

Keep attestation permissions away from dependency builds, limit channel credentials, validate manifest asset names, and isolate Renovate notice artifacts. Add a real affected-file Windows gate and bounded npm fetch retries.

Use structured doctor facts in package smokes, strict release-script argument parsing, independent install-catalog fixtures, and accurate npm failure classification. Update contributor guidance, unreleased notes, and audit evidence. This is an integration checkpoint; part-specific PR branches are assembled separately. Native Windows and Docker execution remain CI verification limits.
Use awaited bounded Git mutations with descendant cleanup, opaque NUL-delimited paths, safe refs, generated-file exclusions, staged-deleted handling, and expected-head leases for remote branch deletion. Preserve caller SSH and credential-helper configuration.

Validate YAML recovery proofs and complete JSONL rewrites, retain uncertain file generations, handle exact short writes and contained paths, and block startup before hydration when interrupted fallback ownership cannot be established. Use native SQLite transactions for persistent Manual QA evidence locks and handle final symlinks without following external targets.

Update app and published-doc companion prose plus workflow descriptions and Details. Distinguish harmless orphan warnings, process-level recovery blocking, transient cleanup and worktree deletion. Checkpoint only independently accepted source snapshots; newer bead and CLI edits remain unstaged.

Verification: independent Git 229 tests across 18 files plus earlier 174 downstream checks; durable IO 198 passed with 4 platform skips; metadata 44 tests; website 87 tests/build/site/license checks; scoped lint, types and diff checks. Native Windows, physical power loss, full lifecycle and final part-wide verification remain outstanding. No part2 PR is opened by this checkpoint.
… drafts

Checkpoint independently reviewed authoritative bead reads, structured command producers and approval validation, dependency inverse and cycle checks, source-line diagnostics, immutable original draft conflicts, and accessible damaged-tracker UI. Preserve unknown metadata while preventing malformed trackers from reporting false completion or being silently rewritten.

Carry forward the already reviewed release-part native SEA runtime and launch diagnostics without mixing active process or remote-session edits. Update workflow descriptions and details, application documentation, changelog and audit evidence; published website prose is committed separately. Stage accepted bead snapshot blobs for shared paths so newer in-progress OpenCode changes remain untouched. Full isolated part verification and individual PR delivery remain separate gates.
…ries

Checkpoint independently reviewed cleanup revalidation, successor-safe daemon-state removal under the existing daemon lock, concurrent-start loser protection, captured process identity across executor and supervisor termination, and guarded group escalation. Preserve Git descendant cleanup while refusing missing or recycled process identities.

Keep log-follow handoff bytes, incomplete UTF-8 and partial lines intact; reset decoding on rotation, bracket IPv6 origins, redact Windows profile paths and serialize runtime restart ordering. Include focused race regressions and the previously reviewed canonical log test fixture from PR164. Update application guidance, changelog and audit records; publish matching upcoming-release website prose separately. Accepted snapshot staging leaves active OpenCode and interview edits untouched. Hooks and isolated part-three verification remain pending.
Keep resolved question identities suppressed across stale snapshots and fence responses across ticket removal and re-addition. Stabilize question polling, refresh all ticket query families on initial cursor recovery or replay gaps, and retain lightweight ordinary reconnect behavior.

Bound shared session-auth probes to five seconds without treating network failures as sign-out. Retry model discovery only for the explicit OpenCode startup response. Add actual-hook race, timeout and retry coverage, with matching changelog and audit dispositions.

Fresh source review passed 77 tests, lint, both TypeScript projects and diff checks. Documentation was independently checked against the frozen source; website guidance is published separately with next-release labels. Remaining workflow and log-history work is excluded from this checkpoint.
…integrity

Require confirmed remote stops before abandonment, restart, cancellation and cleanup; retain uncertain sessions through durable markers where storage permits. Scope session context and question handling to canonical project ownership, bound finite continuations, and preserve zero as unlimited.

Fence interview generation, edits and rollback with durable claims and latest-row content checks; validate batch identity and timestamps, reclaim expired or confirmed-dead ordinary claims, and keep pending-stop ownership non-expiring until confirmed.

Update status descriptions and Details, maintainer guidance, changelog and audit dispositions. Integrates only independently reviewed OpenCode and interview-core snapshots; newer approval-save and log-history revisions remain unstaged. Focused regression suites, application/test types, lint and documentation checks passed; native-platform and full lifecycle validation remain manual.
Keep temporary OpenCode step caps out of bead and squash commits while a valid restore marker exists, including app-created configs edited during execution. Preserve conflicting bytes across reset refusal, persist contained hook-validation recovery snapshots, and record bead HEAD before publishing in_progress.

Require original content hashes for PRD and interview edit saves. Fence post-approval restart work with the exact durable claim before and after awaited session stopping so expired writers cannot invalidate successor artifacts.

Coordinate normal and keepalive UI-state saves with shared generation guards. Preserve failed local drafts through completed refetches, learn server revisions before queued saves start, and acknowledge only the current saved snapshot.

Update repository guidance, changelog, status descriptions and Details with conditional recovery and best-effort flush limits. Website documentation is committed separately on its main branch.

Integrate only independently reviewed frozen hooks10, saves21 and docs6 manifests. Preserve active workflow, log and form edits outside this checkpoint. Scoped tests and independent race/recovery probes passed; full isolated part checks and PR acceptance remain pending. No E2E or lifecycle tests.
Preserve merge and Manual QA ownership, validate skip receipts, expose supported recovery actions, and retain submitted snapshots across later drafts. Bound log paging work without limiting complete user-requested history or exports, preserve server ordering, and reject expired cursors explicitly.

Track meaningful unsaved form changes, protect drafts across asynchronous saves and hydration, improve accessible controls, validate ticket payloads, and fence deleted-ticket caches against late requests and SSE events. Update status descriptions, detailed guidance, changelog, and the audit ledger alongside reviewed published documentation.

Integrates 79 explicit files from independently accepted workflow, log, forms, cache, and documentation snapshots. Credential filtering and lint/security work remain separate and unstaged. Full isolated part checks and part-specific PR assembly follow; this integration branch is not a PR.
Validate cookie origins against the actual request scheme and canonical authority, retain explicit development origins, reserve SSE admission before asynchronous work, and validate Manual QA action identifiers. Filter internal daemon credentials after child environment merges while preserving intentional provider credentials and trusted daemon handoffs.

Enforce operation-scoped filesystem and process-launch lint boundaries using existing helpers. Update security documentation and audit dispositions; isolate database-backed interview batch tests and use the existing React Query re-export for historical log cancellation.

Exact combined tree passed 6458 tests with 13 skips, lint, both TypeScript projects, production/package/version/install/license checks, actionlint and ShellCheck, native Linux Node 26.9.0 SEA build, and amd64 container build/version/help. Fresh independent review verified all 31 overlay paths and ran 129 tests with one platform skip. Remaining part PR delivery is tracked separately; no lifecycle, E2E, CI, merge, or unsupported-platform acceptance claimed.
Record the exact open PR heads and dependency bases, the accepted 154-finding source checkpoint, and combined local verification results. Mark earlier pending delivery counts as historical while preserving native-platform, lifecycle, publication, and CI limitations.

Clarify local Host versus Origin parsing scope without changing runtime behavior. This reporting-only update passed 19 documentation tests, exact commit and link checks, whitespace and NUL checks, and a fresh independent review. All seven PRs remain unmerged; CI acceptance is reserved for the owner.
Route the second positional token help or ? through the existing per-command --help path so all three spellings return identical output without running the command. Update the built-in usage text and Unreleased changelog, and add a regression covering all aliases. Top-level --help and unknown-command handling remain unchanged.

@sourcery-ai sourcery-ai 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.

Sorry, we are unable to review this pull request

The GitHub API does not allow us to fetch diffs exceeding 300 files, and this pull request has 360

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-20T13:19:21.312357Z 3037800 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 359 files, which is 259 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 52f3376b-0334-4813-985a-6d917d7ce743

📥 Commits

Reviewing files that changed from the base of the PR and between 6384c2c and 3037800.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (359)
  • .dockerignore
  • .github/consolidated-audit-dispositions.md
  • .github/workflows/channel-republish.yml
  • .github/workflows/ci.yml
  • .github/workflows/container-republish.yml
  • .github/workflows/published-smoke.yml
  • .github/workflows/release-pr.yml
  • .github/workflows/release.yml
  • .github/workflows/renovate-notices.yml
  • CHANGELOG.md
  • CONTRIBUTING.md
  • Dockerfile
  • README.md
  • eslint.config.js
  • install.ps1
  • install.sh
  • package.json
  • scripts/audit-formula.ts
  • scripts/aur-push.ts
  • scripts/build-binary.mjs
  • scripts/channel-inputs.ts
  • scripts/choco-push.ts
  • scripts/dev-maintenance.ts
  • scripts/dev-opencode.ts
  • scripts/diagnose-runtime-stall.ts
  • scripts/installer-core.mjs
  • scripts/smoke-aur.ts
  • scripts/smoke-binary-install.mjs
  • scripts/smoke-choco.ts
  • scripts/smoke-container.mjs
  • scripts/smoke-install.mjs
  • scripts/smoke-lib.d.mts
  • scripts/smoke-lib.mjs
  • scripts/smoke-published.mjs
  • scripts/smoke-winget.ts
  • scripts/winget-submit.ts
  • server/__tests__/startupArtifacts.test.ts
  • server/__tests__/startupSessions.test.ts
  • server/cli/__tests__/cliUpdate.test.ts
  • server/cli/__tests__/logsCommand.test.ts
  • server/cli/cleanCommand.ts
  • server/cli/cli.ts
  • server/cli/commands.ts
  • server/cli/daemonProcess.ts
  • server/cli/doctorCommand.ts
  • server/cli/launcher.cjs
  • server/cli/logsCommand.ts
  • server/cli/processControl.ts
  • server/cli/setupCommand.ts
  • server/council/__tests__/councilSteps.test.ts
  • server/council/__tests__/voter.test.ts
  • server/council/drafter.ts
  • server/council/voter.ts
  • server/createRuntime.ts
  • server/daemon/startDaemon.ts
  • server/db/__tests__/opencodeSessionOrphan.test.ts
  • server/git/__tests__/github.test.ts
  • server/git/__tests__/push.test.ts
  • server/git/__tests__/repoScopedPath.test.ts
  • server/git/__tests__/repository.test.ts
  • server/git/__tests__/runCommand.test.ts
  • server/git/__tests__/runCommandFallback.test.ts
  • server/git/__tests__/statusPorcelain.test.ts
  • server/git/__tests__/worktreeRemoval.test.ts
  • server/git/github.ts
  • server/git/indexSnapshot.ts
  • server/git/push.ts
  • server/git/ref.ts
  • server/git/repoScopedPath.ts
  • server/git/repository.ts
  • server/git/runCommand.ts
  • server/git/statusPorcelain.ts
  • server/git/worktreeChanges.ts
  • server/git/worktreeRemoval.ts
  • server/index.ts
  • server/io/__tests__/atomicIO.test.ts
  • server/io/__tests__/fileLock.test.ts
  • server/io/__tests__/recoveryContainment.test.ts
  • server/io/atomicAppend.ts
  • server/io/atomicWrite.ts
  • server/io/fileLock.ts
  • server/io/recovery.ts
  • server/lib/__tests__/commandExecutor.test.ts
  • server/lib/__tests__/containedPath.test.ts
  • server/lib/__tests__/daemonPaths.test.ts
  • server/lib/__tests__/executablePath.test.ts
  • server/lib/__tests__/processTree.test.ts
  • server/lib/childEnvironment.ts
  • server/lib/commandExecutor.ts
  • server/lib/containedPath.ts
  • server/lib/daemonPaths.ts
  • server/lib/executablePath.ts
  • server/lib/processTree.ts
  • server/log/__tests__/commandLogger.test.ts
  • server/log/__tests__/executionLog.test.ts
  • server/log/commandLogger.ts
  • server/log/executionLog.ts
  • server/log/projection.ts
  • server/middleware/__tests__/hostGuard.test.ts
  • server/middleware/hostGuard.ts
  • server/opencode/__tests__/adapterDiagnostics.test.ts
  • server/opencode/__tests__/contextBuilder.test.ts
  • server/opencode/__tests__/logDiagnostics.test.ts
  • server/opencode/__tests__/sessionManager.test.ts
  • server/opencode/__tests__/supervisor.test.ts
  • server/opencode/adapter.ts
  • server/opencode/contextBuilder.ts
  • server/opencode/logDiagnostics.ts
  • server/opencode/openRouterRoutingConfig.ts
  • server/opencode/sessionManager.ts
  • server/opencode/supervisor.ts
  • server/phases/__tests__/coverageGapResolutions.test.ts
  • server/phases/beads/__tests__/beadsFile.test.ts
  • server/phases/beads/__tests__/coverageRevision.test.ts
  • server/phases/beads/__tests__/document.test.ts
  • server/phases/beads/__tests__/draft.test.ts
  • server/phases/beads/__tests__/refined.test.ts
  • server/phases/beads/beadsFile.ts
  • server/phases/beads/dependencyGraph.ts
  • server/phases/beads/document.ts
  • server/phases/coverageGapResolutions.ts
  • server/phases/execution/__tests__/executor.test.ts
  • server/phases/execution/__tests__/gitOps.test.ts
  • server/phases/execution/__tests__/opencodeStepsConfig.test.ts
  • server/phases/execution/executor.ts
  • server/phases/execution/gitOps.ts
  • server/phases/execution/opencodeStepsConfig.ts
  • server/phases/executionSetup/__tests__/hookValidation.test.ts
  • server/phases/executionSetup/__tests__/storage.test.ts
  • server/phases/executionSetup/generator.ts
  • server/phases/executionSetup/hookValidation.ts
  • server/phases/executionSetup/storage.ts
  • server/phases/executionSetupPlan/generator.ts
  • server/phases/finalTest/generator.ts
  • server/phases/integration/__tests__/squash.test.ts
  • server/phases/integration/squash.ts
  • server/phases/interview/__tests__/sessionIntegrity.test.ts
  • server/phases/interview/batchManagement.ts
  • server/phases/interview/finalDocument.ts
  • server/phases/interview/qa.ts
  • server/phases/interview/sessionSerializer.ts
  • server/phases/interview/snapshotValidation.ts
  • server/phases/manualQa/__tests__/checkpoint.test.ts
  • server/phases/manualQa/__tests__/fixBeads.test.ts
  • server/phases/manualQa/__tests__/operations.test.ts
  • server/phases/manualQa/__tests__/storage.test.ts
  • server/phases/manualQa/checkpoint.ts
  • server/phases/manualQa/fixBeads.ts
  • server/phases/manualQa/focusedDiff.ts
  • server/phases/manualQa/operations.ts
  • server/phases/manualQa/storage.ts
  • server/phases/prd/__tests__/refined.test.ts
  • server/phases/prd/document.ts
  • server/phases/prd/draft.ts
  • server/phases/prd/refined.ts
  • server/phases/preflight/__tests__/doctor.test.ts
  • server/phases/preflight/doctor.ts
  • server/prompts/__tests__/index.test.ts
  • server/prompts/index.ts
  • server/routes/__tests__/beads.test.ts
  • server/routes/__tests__/files.test.ts
  • server/routes/__tests__/logs.test.ts
  • server/routes/__tests__/stream.test.ts
  • server/routes/__tests__/tickets.basic.test.ts
  • server/routes/__tests__/tickets.beadsApproval.test.ts
  • server/routes/__tests__/tickets.cancel.test.ts
  • server/routes/__tests__/tickets.delete.test.ts
  • server/routes/__tests__/tickets.executionSetupPlanApproval.test.ts
  • server/routes/__tests__/tickets.interviewApproval.test.ts
  • server/routes/__tests__/tickets.interviewBatchSafety.test.ts
  • server/routes/__tests__/tickets.prdApproval.test.ts
  • server/routes/__tests__/tickets.retry.test.ts
  • server/routes/__tests__/tickets.skip.test.ts
  • server/routes/__tests__/tickets.skips.test.ts
  • server/routes/__tests__/tickets.verify.test.ts
  • server/routes/beads.ts
  • server/routes/files.ts
  • server/routes/stream.ts
  • server/routes/ticketHandlers/approvalHandlers.ts
  • server/routes/ticketHandlers/artifactHandlers.ts
  • server/routes/ticketHandlers/crudHandlers.ts
  • server/routes/ticketHandlers/executionSetupHandlers.ts
  • server/routes/ticketHandlers/interviewHandlers.ts
  • server/routes/ticketHandlers/lifecycleHandlers.ts
  • server/routes/ticketHandlers/logHandlers.ts
  • server/routes/ticketHandlers/manualQaHandlers.ts
  • server/routes/ticketHandlers/openCodeQuestionHandlers.ts
  • server/routes/ticketHandlers/routeUtils.ts
  • server/routes/ticketHandlers/schemas.ts
  • server/sse/broadcaster.ts
  • server/startup.ts
  • server/storage/__tests__/paths.test.ts
  • server/storage/__tests__/ticketArtifacts.test.ts
  • server/storage/__tests__/ticketQueries.test.ts
  • server/storage/__tests__/ticketRuntimeProjection.test.ts
  • server/storage/paths.ts
  • server/storage/projects.ts
  • server/storage/ticketArtifacts.ts
  • server/storage/ticketMutations.ts
  • server/storage/ticketQueries.ts
  • server/storage/ticketRuntimeProjection.ts
  • server/structuredOutput/__tests__/aliasPrecedence.test.ts
  • server/structuredOutput/__tests__/beadStatusAndIteration.test.ts
  • server/structuredOutput/__tests__/index.test.ts
  • server/structuredOutput/__tests__/refinementChanges.test.ts
  • server/structuredOutput/__tests__/repairWarningBookkeeping.test.ts
  • server/structuredOutput/__tests__/yamlUtils.test.ts
  • server/structuredOutput/beadsOutput.ts
  • server/structuredOutput/completionOutput.ts
  • server/structuredOutput/interviewDocument.ts
  • server/structuredOutput/interviewOutput.ts
  • server/structuredOutput/prdOutput.ts
  • server/structuredOutput/refinementChanges.ts
  • server/structuredOutput/voteOutput.ts
  • server/structuredOutput/yamlUtils.ts
  • server/ticket/initialize.ts
  • server/workflow/__tests__/beadsRefinePhase.test.ts
  • server/workflow/__tests__/executionPhase.test.ts
  • server/workflow/__tests__/executionSetupPhase.test.ts
  • server/workflow/__tests__/interviewBatchCas.test.ts
  • server/workflow/__tests__/interviewBatchClaims.test.ts
  • server/workflow/__tests__/lifecycleCleanup.test.ts
  • server/workflow/__tests__/openCodeLogCanonicalization.test.ts
  • server/workflow/__tests__/pullRequestPhase.test.ts
  • server/workflow/__tests__/questionWindows.test.ts
  • server/workflow/__tests__/runOpenCodePrompt.test.ts
  • server/workflow/__tests__/runner.test.ts
  • server/workflow/__tests__/skipReceipts.test.ts
  • server/workflow/__tests__/verificationFinalTestPhase.test.ts
  • server/workflow/mergeCompletion.ts
  • server/workflow/phases/beadsPhase.ts
  • server/workflow/phases/executionPhase.ts
  • server/workflow/phases/executionSetupPhase.ts
  • server/workflow/phases/integrationPhase.ts
  • server/workflow/phases/interviewPhase.ts
  • server/workflow/phases/pullRequestPhase.ts
  • server/workflow/phases/state.ts
  • server/workflow/phases/verificationPhase.ts
  • server/workflow/questionWindows.ts
  • server/workflow/runOpenCodePrompt.ts
  • server/workflow/runner.ts
  • server/workflow/skipReceipts.ts
  • shared/__tests__/yamlRepair.test.ts
  • shared/workflowMeta.ts
  • shared/yamlRepair.ts
  • src/App.test.tsx
  • src/App.tsx
  • src/components/config/ModelPicker.tsx
  • src/components/config/ProfileSetup.tsx
  • src/components/config/__tests__/ModelPicker.test.tsx
  • src/components/config/__tests__/ProfileSetup.test.tsx
  • src/components/kanban/TicketCard.tsx
  • src/components/kanban/__tests__/TicketCardProgress.test.tsx
  • src/components/navigator/BeadsApprovalNavigator.tsx
  • src/components/navigator/__tests__/BeadsApprovalNavigator.test.tsx
  • src/components/project/FolderPicker.tsx
  • src/components/project/ProjectForm.tsx
  • src/components/project/ProjectsPanel.tsx
  • src/components/project/__tests__/FolderPicker.test.tsx
  • src/components/project/__tests__/ProjectForm.test.tsx
  • src/components/prompts/PromptEditor.tsx
  • src/components/prompts/PromptsDialog.tsx
  • src/components/prompts/__tests__/PromptEditor.test.tsx
  • src/components/shared/CenteredModal.tsx
  • src/components/shared/DropdownPicker.tsx
  • src/components/shared/KeyboardShortcuts.tsx
  • src/components/shared/__tests__/CenteredModal.test.tsx
  • src/components/shared/__tests__/DropdownPicker.test.tsx
  • src/components/ticket/TicketDashboard.tsx
  • src/components/ticket/TicketForm.tsx
  • src/components/ticket/WorkspacePhaseSummary.tsx
  • src/components/ticket/__tests__/TicketDashboard.test.tsx
  • src/components/ticket/__tests__/TicketForm.test.tsx
  • src/components/ticket/__tests__/WorkspacePhaseSummary.test.tsx
  • src/components/ticket/renderedTickets.ts
  • src/components/workspace/ApprovalView.tsx
  • src/components/workspace/ArtifactContentViewer.tsx
  • src/components/workspace/BeadsApprovalEditor.tsx
  • src/components/workspace/CodingView.tsx
  • src/components/workspace/ErrorView.tsx
  • src/components/workspace/ExecutionSetupPlanApprovalPane.tsx
  • src/components/workspace/FullLogView.tsx
  • src/components/workspace/InterviewApprovalPane.tsx
  • src/components/workspace/InterviewQAView.tsx
  • src/components/workspace/ManualQAView.tsx
  • src/components/workspace/PendingQuestionsPanel.tsx
  • src/components/workspace/PhaseLogPanel.tsx
  • src/components/workspace/PrdApprovalPane.tsx
  • src/components/workspace/__tests__/ApprovalView.test.tsx
  • src/components/workspace/__tests__/ArtifactContentViewer.test.tsx
  • src/components/workspace/__tests__/BeadsApprovalEditor.test.tsx
  • src/components/workspace/__tests__/ErrorView.test.tsx
  • src/components/workspace/__tests__/ExecutionSetupPlanApprovalPane.test.tsx
  • src/components/workspace/__tests__/FullLogView.test.tsx
  • src/components/workspace/__tests__/InterviewApprovalPane.test.tsx
  • src/components/workspace/__tests__/InterviewQAView.test.tsx
  • src/components/workspace/__tests__/ManualQAView.render.test.tsx
  • src/components/workspace/__tests__/PendingQuestionsPanel.test.tsx
  • src/components/workspace/__tests__/PhaseLogPanel.test.tsx
  • src/components/workspace/__tests__/PrdApprovalPane.test.tsx
  • src/components/workspace/__tests__/approvalHooks.test.tsx
  • src/components/workspace/approvalHooks.ts
  • src/components/workspace/artifactViewers/__tests__/executionSetupViews.test.tsx
  • src/components/workspace/artifactViewers/executionSetupViews.tsx
  • src/components/workspace/logGroupingHelpers.ts
  • src/components/workspace/textDiffSegments.test.ts
  • src/components/workspace/textDiffSegments.ts
  • src/context/AIQuestionContext.tsx
  • src/context/__tests__/AIQuestionContext.test.tsx
  • src/context/__tests__/LogContext.test.ts
  • src/context/logUtils.ts
  • src/hooks/__tests__/clearTicketCaches.test.ts
  • src/hooks/__tests__/ticketDeleteBarrier.test.tsx
  • src/hooks/__tests__/useBatchSubmit.test.tsx
  • src/hooks/__tests__/useOpenCodeModels.test.ts
  • src/hooks/__tests__/useProjects.test.tsx
  • src/hooks/__tests__/useSSE.test.tsx
  • src/hooks/__tests__/useTicketAction.test.tsx
  • src/hooks/__tests__/useTicketHistoricalLogs.test.tsx
  • src/hooks/__tests__/useTicketUIState.test.tsx
  • src/hooks/useBatchSubmit.ts
  • src/hooks/useDialogFocus.ts
  • src/hooks/useOpenCodeModels.ts
  • src/hooks/useProjects.ts
  • src/hooks/useSSE.ts
  • src/hooks/useTicketHistoricalLogs.ts
  • src/hooks/useTickets.ts
  • src/lib/__tests__/beadsDocument.test.ts
  • src/lib/__tests__/sessionState.test.ts
  • src/lib/__tests__/ticketNormalization.test.ts
  • src/lib/__tests__/workflowMeta.test.ts
  • src/lib/beadsDocument.ts
  • src/lib/overlays.ts
  • src/lib/sessionState.ts
  • src/lib/ticketNormalization.ts
  • tests/channelInputs.test.ts
  • tests/cleanCommand.test.ts
  • tests/createRuntime.test.ts
  • tests/dev-maintenance.test.ts
  • tests/dev-opencode.test.ts
  • tests/docsInstallCatalog.test.ts
  • tests/doctorCommand.test.ts
  • tests/doctorSmokeContract.test.ts
  • tests/eslintAmbientProgram.test.ts
  • tests/eslintArtifactIo.test.ts
  • tests/fixtures/install-catalog.json
  • tests/fixtures/installer-lock-signal.mjs
  • tests/installScriptPolicy.test.ts
  • tests/installer.test.ts
  • tests/installerLock.test.ts
  • tests/packagingProbes.test.ts
  • tests/processControl.test.ts
  • tests/releaseScriptArgs.test.ts
  • tests/smokePublished.test.ts
  • tests/startCommandAbandon.test.ts
  • tests/stopCommand.test.ts
  • tests/wingetSubmit.test.ts
  • tests/workflowPolicy.test.ts
  • vitest.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@amazon-q-developer amazon-q-developer 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.

Summary

This PR successfully implements support for help and ? as aliases for per-command CLI help alongside --help. The implementation is clean, well-tested, and follows existing patterns in the codebase.

Key Changes Reviewed

  • CLI Help Aliases: Added support for looptroop <command> help and looptroop <command> ? in addition to --help
  • Test Coverage: Comprehensive test added to verify all three aliases produce identical output
  • Documentation: Updated usage text and comments to reflect the new aliases

Assessment

The changes are minimal, focused, and correct. The implementation properly handles the help aliases at the right point in the CLI argument parsing flow, and the test coverage ensures all three forms (--help, help, ?) work identically. No security, logic, or stability issues were identified in the changes.

With 360 files changed in this consolidated audit PR, I focused my review on the CLI changes mentioned in the PR description and found them to be well-executed. The broader cleanup and audit changes appear to be part of a systematic code quality improvement effort.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.


⚠️ This PR contains more than 30 files. Amazon Q is better at reviewing smaller PRs, and may miss issues in larger changesets.

@codacy-production

codacy-production Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 10 critical · 22 high · 9 medium

Alerts:
⚠ 41 issues (≤ 0 issues of at least minor severity)

Results:
41 new issues

Category Results
ErrorProne 9 medium
7 high
Security 10 critical
15 high

View in Codacy

🟢 Metrics 3541 complexity · 457 duplication

Metric Results
Complexity 3541
Duplication 457

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Comment thread server/io/atomicWrite.ts Dismissed
const descendant = [
'const fs = require("node:fs")',
'process.on("SIGTERM", () => {})',
`setTimeout(() => fs.writeFileSync(${JSON.stringify(marker)}, 'survived'), 1000)`,
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Complete consolidated reliability, security, and delivery audit

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Hardens recovery, process execution, workflow concurrency, parsing, and request validation.
• Reconciles UI dialog, approval, cache, streaming, and historical-log state.
• Strengthens installers, release pipelines, documentation, and cross-layer regression coverage.
Diagram

graph TD
  UI["Web client"] --> API["API routes"] --> Flow["Workflow engine"] --> Sessions["OpenCode sessions"]
  Flow --> Storage["Atomic storage"] --> Logs["Log projection"]
  CLI["CLI and installers"] --> Runtime["Trusted runtime"] --> Flow
  Delivery["Delivery pipelines"] --> CLI
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Split by subsystem
  • ➕ Produces smaller, independently reviewable diffs
  • ➕ Reduces simultaneous regression surface
  • ➕ Allows targeted rollback of installer, server, UI, or release changes
  • ➖ Cross-layer invariants may temporarily remain inconsistent
  • ➖ Requires careful dependency ordering across recovery, workflow, API, and UI fixes
  • ➖ Extends the period before the consolidated audit is fully resolved
2. Adopt external coordination primitives
  • ➕ Could replace custom claim and recovery mechanisms with established distributed-lock or queue semantics
  • ➕ May simplify ownership and cancellation guarantees long term
  • ➖ Adds operational dependencies and migration risk
  • ➖ Does not directly fit local-first SQLite and filesystem deployments
  • ➖ Would materially expand scope beyond audit remediation

Recommendation: Keep the implemented local-first approach: SQLite transaction locks, durable ownership markers, compare-and-set artifacts, and fail-closed recovery align with the existing architecture. For review and landing, however, subsystem-stacked PRs would normally be safer; retaining one consolidated PR is reasonable only because these audit packets share invariants and already include extensive focused regression coverage.

Files changed (360) +27154 / -3964

Enhancement (15) +1665 / -47
cli.tsAccept per-command help aliases +8/-6

Accept per-command help aliases

• Recognizes 'help' and '?' after commands and updates CLI guidance.

server/cli/cli.ts

indexSnapshot.tsAdd Git index snapshots +23/-0

Add Git index snapshots

• Captures index state for safe mutation rollback and comparison.

server/git/indexSnapshot.ts

ref.tsAdd canonical Git ref validation +39/-0

Add canonical Git ref validation

• Centralizes branch and ref checks before command execution.

server/git/ref.ts

childEnvironment.tsAdd sanitized child environments +23/-0

Add sanitized child environments

• Builds child-process environments without undefined or unsafe inherited values.

server/lib/childEnvironment.ts

projection.tsIndex native OpenCode history +1082/-27

Index native OpenCode history

• Adds incremental generation-based native log indexing, snapshots, canonical ordering, and cursor consistency.

server/log/projection.ts

logDiagnostics.tsAdd native OpenCode log reader +234/-13

Add native OpenCode log reader

• Discovers and parses native logs with contained paths, stable identities, and read statistics.

server/opencode/logDiagnostics.ts

dependencyGraph.tsAdd beads dependency graph +117/-0

Add beads dependency graph

• Provides cycle detection, validation, and deterministic dependency ordering.

server/phases/beads/dependencyGraph.ts

focusedDiff.tsAdd focused diff containment +6/-0

Add focused diff containment

• Builds bounded, repository-scoped diffs for manual QA.

server/phases/manualQa/focusedDiff.ts

ticketArtifacts.tsAdd artifact compare-and-set updates +56/-1

Add artifact compare-and-set updates

• Publishes phase artifacts only when the expected latest revision remains current.

server/storage/ticketArtifacts.ts

ticketRuntimeProjection.tsProject additional runtime state +1/-0

Project additional runtime state

• Exposes audited runtime metadata needed by lifecycle decisions.

server/storage/ticketRuntimeProjection.ts

WorkspacePhaseSummary.tsxAdd normalized phase summary +11/-0

Add normalized phase summary

• Displays canonical workflow phase progress and status.

src/components/ticket/WorkspacePhaseSummary.tsx

renderedTickets.tsAdd stable rendered-ticket selection +34/-0

Add stable rendered-ticket selection

• Normalizes ticket collections and safely resolves active tickets.

src/components/ticket/renderedTickets.ts

CodingView.tsxExpose coding cleanup state +2/-0

Expose coding cleanup state

• Displays additional audited runtime progress information.

src/components/workspace/CodingView.tsx

logGroupingHelpers.tsAdd canonical log grouping helpers +8/-0

Add canonical log grouping helpers

• Centralizes stable phase and operation grouping.

src/components/workspace/logGroupingHelpers.ts

textDiffSegments.tsAdd text diff segmentation +21/-0

Add text diff segmentation

• Builds renderable changed and unchanged text segments.

src/components/workspace/textDiffSegments.ts

Bug fix (156) +10071 / -2796
install.ps1Harden PowerShell installation +207/-41

Harden PowerShell installation

• Rejects empty parameters and incorporates trusted executable, namespace, recovery, and argument-preservation fixes.

install.ps1

install.shHarden shell installation +195/-39

Harden shell installation

• Regenerates the installer with audited executable trust, namespace, recovery, and Node guidance behavior.

install.sh

audit-formula.tsValidate formula audit inputs +21/-4

Validate formula audit inputs

• Hardens package formula inspection and failure reporting.

scripts/audit-formula.ts

aur-push.tsPreserve AUR push arguments +15/-3

Preserve AUR push arguments

• Passes validated release arguments safely through the AUR publication wrapper.

scripts/aur-push.ts

channel-inputs.tsValidate release channel inputs +20/-7

Validate release channel inputs

• Normalizes and rejects unsafe or inconsistent channel publication arguments.

scripts/channel-inputs.ts

choco-push.tsPreserve Chocolatey push arguments +15/-3

Preserve Chocolatey push arguments

• Forwards validated package publication arguments without lossy wrapper parsing.

scripts/choco-push.ts

dev-maintenance.tsHarden maintenance command execution +43/-13

Harden maintenance command execution

• Improves argument handling, executable resolution, and maintenance failure behavior.

scripts/dev-maintenance.ts

dev-opencode.tsPreserve OpenCode development arguments +4/-2

Preserve OpenCode development arguments

• Forwards development command arguments without unsafe re-parsing.

scripts/dev-opencode.ts

installer-core.mjsHarden shared installer resolver +194/-38

Harden shared installer resolver

• Adds PATHEXT-aware resolution, verified user-namespace ownership, safer recovery, and corrected Linux Node guidance.

scripts/installer-core.mjs

winget-submit.tsHarden WinGet submission +16/-13

Harden WinGet submission

• Validates and preserves submission arguments through package publication.

scripts/winget-submit.ts

cleanCommand.tsMake cleanup containment fail closed +80/-13

Make cleanup containment fail closed

• Validates cleanup targets and avoids deleting active or unproven runtime artifacts.

server/cli/cleanCommand.ts

commands.tsHarden CLI command orchestration +62/-32

Harden CLI command orchestration

• Improves daemon-state checks, argument preservation, and safe command transitions.

server/cli/commands.ts

daemonProcess.tsAlign daemon process environment +2/-1

Align daemon process environment

• Uses the hardened child-process environment contract.

server/cli/daemonProcess.ts

doctorCommand.tsAlign doctor command execution +2/-2

Align doctor command execution

• Uses audited command and diagnostic behavior.

server/cli/doctorCommand.ts

launcher.cjsPreserve launcher arguments +1/-1

Preserve launcher arguments

• Corrects argument forwarding from the packaged CLI launcher.

server/cli/launcher.cjs

logsCommand.tsHarden log retrieval command +68/-13

Harden log retrieval command

• Validates arguments and improves bounded streaming, formatting, and error handling.

server/cli/logsCommand.ts

processControl.tsHarden daemon process control +20/-9

Harden daemon process control

• Improves process identity validation, signaling, and stop confirmation.

server/cli/processControl.ts

setupCommand.tsAlign setup command arguments +4/-4

Align setup command arguments

• Preserves validated setup options through command wrappers.

server/cli/setupCommand.ts

drafter.tsHarden council drafting +93/-18

Harden council drafting

• Improves structured draft parsing, diagnostics, and recovery from malformed output.

server/council/drafter.ts

voter.tsHarden council voting +92/-12

Harden council voting

• Improves vote normalization, failure accounting, and deterministic selection.

server/council/voter.ts

createRuntime.tsAlign runtime construction +1/-1

Align runtime construction

• Wires the audited startup and runtime dependency contract.

server/createRuntime.ts

startDaemon.tsHarden daemon startup ownership +11/-4

Harden daemon startup ownership

• Improves startup artifact validation and daemon-state publication.

server/daemon/startDaemon.ts

github.tsHarden GitHub API interactions +56/-23

Harden GitHub API interactions

• Normalizes pull-request state and improves bounded, validated command handling.

server/git/github.ts

push.tsHarden branch publication +26/-20

Harden branch publication

• Validates refs and uses bounded noninteractive Git mutations.

server/git/push.ts

repoScopedPath.tsStrengthen repository containment +54/-8

Strengthen repository containment

• Rejects symlink and traversal escapes for existing and prospective paths.

server/git/repoScopedPath.ts

repository.tsMove Git mutations off sync path +17/-3

Move Git mutations off sync path

• Uses bounded asynchronous execution for hookable or long-running repository changes.

server/git/repository.ts

runCommand.tsHarden command execution and termination +173/-36

Harden command execution and termination

• Adds trusted resolution, sanitized environments, async Git mutations, and process-tree timeouts.

server/git/runCommand.ts

statusPorcelain.tsReject malformed status records +5/-0

Reject malformed status records

• Adds stricter validation to porcelain status parsing.

server/git/statusPorcelain.ts

worktreeChanges.tsImprove worktree change inspection +16/-11

Improve worktree change inspection

• Handles repository state and bounded Git operations more safely.

server/git/worktreeChanges.ts

worktreeRemoval.tsMake worktree removal asynchronous +8/-8

Make worktree removal asynchronous

• Uses bounded mutation execution for cleanup operations.

server/git/worktreeRemoval.ts

index.tsAlign server entrypoint startup +2/-1

Align server entrypoint startup

• Propagates audited asynchronous startup behavior.

server/index.ts

atomicAppend.tsHarden atomic append durability +26/-8

Harden atomic append durability

• Adds safer file identity, synchronization, and containment behavior.

server/io/atomicAppend.ts

atomicWrite.tsAdd durable atomic-write proofs +79/-8

Add durable atomic-write proofs

• Publishes checksummed proofs and synchronizes replacement metadata for reliable recovery.

server/io/atomicWrite.ts

fileLock.tsReplace stale lockfiles with SQLite locks +41/-77

Replace stale lockfiles with SQLite locks

• Uses transaction ownership that releases automatically when a process exits.

server/io/fileLock.ts

recovery.tsImplement fail-closed artifact recovery +610/-57

Implement fail-closed artifact recovery

• Validates containment, identities, proofs, and durable markers before replacing interrupted artifacts.

server/io/recovery.ts

commandExecutor.tsPreserve safe wrapper arguments +11/-4

Preserve safe wrapper arguments

• Avoids lossy command reconstruction when invoking audited tools.

server/lib/commandExecutor.ts

containedPath.tsTighten contained path checks +6/-2

Tighten contained path checks

• Corrects boundary validation for resolved filesystem paths.

server/lib/containedPath.ts

daemonPaths.tsSecure daemon runtime paths +38/-3

Secure daemon runtime paths

• Validates ownership, permissions, and containment before using daemon artifacts.

server/lib/daemonPaths.ts

executablePath.tsHarden trusted executable resolution +154/-16

Harden trusted executable resolution

• Resolves Windows PATHEXT siblings before trust checks and recognizes verified namespace mappings.

server/lib/executablePath.ts

processTree.tsImplement robust process-tree cleanup +187/-8

Implement robust process-tree cleanup

• Discovers and terminates descendants with platform-aware fallbacks and confirmation.

server/lib/processTree.ts

commandLogger.tsImprove command diagnostics +13/-1

Improve command diagnostics

• Records audited command outcomes without losing safe argument boundaries.

server/log/commandLogger.ts

executionLog.tsAlign execution log identity +3/-1

Align execution log identity

• Preserves canonical metadata needed by projection and deduplication.

server/log/executionLog.ts

hostGuard.tsHarden request authority validation +60/-32

Harden request authority validation

• Rejects invalid ports, scheme mismatches, alternate loopback spellings, and untrusted authority normalization.

server/middleware/hostGuard.ts

adapter.tsHarden OpenCode adapter execution +138/-57

Harden OpenCode adapter execution

• Improves trusted command invocation, diagnostics, cancellation, and response validation.

server/opencode/adapter.ts

contextBuilder.tsProtect model context construction +41/-11

Protect model context construction

• Uses contained, consistent artifact reads and clearer failure diagnostics.

server/opencode/contextBuilder.ts

sessionManager.tsPersist pending session ownership +547/-26

Persist pending session ownership

• Tracks remote creates durably and blocks unsafe cancellation or deletion when cleanup cannot be proven.

server/opencode/sessionManager.ts

supervisor.tsHarden OpenCode supervision +57/-21

Harden OpenCode supervision

• Coordinates process-tree termination, remote cleanup, and session-end reporting.

server/opencode/supervisor.ts

beadsFile.tsValidate beads dependency documents +115/-18

Validate beads dependency documents

• Normalizes bead records and enforces valid, deterministic dependency relationships.

server/phases/beads/beadsFile.ts

document.tsPreserve canonical beads content +50/-6

Preserve canonical beads content

• Uses validated dependencies and safer structured-output normalization.

server/phases/beads/document.ts

coverageGapResolutions.tsCanonicalize coverage-gap resolutions +70/-64

Canonicalize coverage-gap resolutions

• Reworks resolution normalization and deterministic precedence.

server/phases/coverageGapResolutions.ts

executor.tsHarden execution process cleanup +41/-5

Harden execution process cleanup

• Coordinates subprocess termination and avoids publishing success after interrupted work.

server/phases/execution/executor.ts

gitOps.tsMake execution Git mutations bounded +45/-14

Make execution Git mutations bounded

• Uses snapshots and asynchronous mutation commands for recoverable repository changes.

server/phases/execution/gitOps.ts

opencodeStepsConfig.tsHarden OpenCode step configuration +100/-26

Harden OpenCode step configuration

• Validates and normalizes step aliases without overriding distinct canonical fields.

server/phases/execution/opencodeStepsConfig.ts

generator.tsHarden execution setup generation +51/-20

Harden execution setup generation

• Improves validated structured output and hook configuration handling.

server/phases/executionSetup/generator.ts

hookValidation.tsSecure generated hook validation +259/-7

Secure generated hook validation

• Rejects unsafe commands, paths, shells, and untrusted executables before execution.

server/phases/executionSetup/hookValidation.ts

generator.tsHarden setup-plan generation +25/-9

Harden setup-plan generation

• Improves parser normalization and malformed-output recovery.

server/phases/executionSetupPlan/generator.ts

generator.tsHarden final-test generation +28/-8

Harden final-test generation

• Improves structured test-plan parsing and diagnostics.

server/phases/finalTest/generator.ts

squash.tsMake integration squash recoverable +68/-52

Make integration squash recoverable

• Uses guarded asynchronous Git mutations and restores repository state after failures.

server/phases/integration/squash.ts

batchManagement.tsStrengthen interview batch accounting +23/-1

Strengthen interview batch accounting

• Preserves snapshot identity across batch answers, skips, and retries.

server/phases/interview/batchManagement.ts

finalDocument.tsHarden final interview document +18/-3

Harden final interview document

• Validates normalized content before durable publication.

server/phases/interview/finalDocument.ts

qa.tsReconcile interview QA state +109/-75

Reconcile interview QA state

• Improves snapshot consistency, structured output handling, and concurrent answer safety.

server/phases/interview/qa.ts

sessionSerializer.tsAlign interview serialization +1/-1

Align interview serialization

• Uses canonical snapshot serialization semantics.

server/phases/interview/sessionSerializer.ts

snapshotValidation.tsTighten snapshot validation +45/-24

Tighten snapshot validation

• Rejects inconsistent revisions and malformed interview state before mutation.

server/phases/interview/snapshotValidation.ts

checkpoint.tsHarden manual QA checkpoints +51/-10

Harden manual QA checkpoints

• Validates revisions and persists checkpoints atomically.

server/phases/manualQa/checkpoint.ts

operations.tsHarden manual QA Git operations +20/-7

Harden manual QA Git operations

• Uses contained paths and bounded mutation execution.

server/phases/manualQa/operations.ts

storage.tsSecure manual QA artifact storage +32/-6

Secure manual QA artifact storage

• Adds contained reads and durable writes for QA state.

server/phases/manualQa/storage.ts

document.tsHarden PRD document publication +18/-3

Harden PRD document publication

• Validates normalized PRD content before persistence.

server/phases/prd/document.ts

draft.tsHarden PRD draft parsing +22/-8

Harden PRD draft parsing

• Improves structured-output repair and diagnostics.

server/phases/prd/draft.ts

refined.tsHarden refined PRD parsing +17/-5

Harden refined PRD parsing

• Preserves canonical fields while applying alias normalization.

server/phases/prd/refined.ts

doctor.tsConsolidate preflight diagnostics +59/-157

Consolidate preflight diagnostics

• Uses shared audited command checks and restores verified Node installation guidance.

server/phases/preflight/doctor.ts

index.tsComplete prompt cache source identity +1/-1

Complete prompt cache source identity

• Includes the full parser source in cache invalidation hashes.

server/prompts/index.ts

beads.tsHarden beads API mutations +167/-25

Harden beads API mutations

• Adds revision checks, dependency validation, and atomic artifact updates.

server/routes/beads.ts

files.tsSecure file-serving routes +16/-6

Secure file-serving routes

• Rejects traversal and symlink escapes through contained artifact resolution.

server/routes/files.ts

stream.tsReconcile SSE stream state +92/-68

Reconcile SSE stream state

• Improves replay ordering, disconnect cleanup, backpressure, and deleted-ticket behavior.

server/routes/stream.ts

approvalHandlers.tsMake approvals conflict safe +164/-101

Make approvals conflict safe

• Validates revisions and atomically reconciles approval artifacts with workflow state.

server/routes/ticketHandlers/approvalHandlers.ts

artifactHandlers.tsUse canonical artifact access +17/-18

Use canonical artifact access

• Routes artifact reads and writes through contained storage helpers.

server/routes/ticketHandlers/artifactHandlers.ts

crudHandlers.tsAwait durable ticket deletion +5/-2

Await durable ticket deletion

• Ensures asynchronous cleanup completes before reporting deletion.

server/routes/ticketHandlers/crudHandlers.ts

executionSetupHandlers.tsHarden execution setup actions +23/-11

Harden execution setup actions

• Validates revisions and safely persists setup decisions.

server/routes/ticketHandlers/executionSetupHandlers.ts

interviewHandlers.tsHarden concurrent interview actions +427/-157

Harden concurrent interview actions

• Coordinates claims, snapshot compare-and-set updates, stop barriers, and answer retries.

server/routes/ticketHandlers/interviewHandlers.ts

lifecycleHandlers.tsMake lifecycle cleanup fail closed +161/-18

Make lifecycle cleanup fail closed

• Confirms sessions and question windows stop before cancellation, deletion, or terminal transitions.

server/routes/ticketHandlers/lifecycleHandlers.ts

logHandlers.tsExpose consistent historical logs +33/-3

Expose consistent historical logs

• Adds native-history snapshots and explicit expired-cursor conflicts.

server/routes/ticketHandlers/logHandlers.ts

manualQaHandlers.tsHarden manual QA actions +18/-10

Harden manual QA actions

• Validates state and awaits contained repository operations.

server/routes/ticketHandlers/manualQaHandlers.ts

openCodeQuestionHandlers.tsProtect OpenCode question actions +23/-3

Protect OpenCode question actions

• Validates active windows and avoids applying stale answers.

server/routes/ticketHandlers/openCodeQuestionHandlers.ts

routeUtils.tsStrengthen route state utilities +52/-12

Strengthen route state utilities

• Centralizes revision, containment, and workflow action validation.

server/routes/ticketHandlers/routeUtils.ts

schemas.tsTighten ticket action schemas +7/-1

Tighten ticket action schemas

• Adds audited validation for lifecycle and approval payloads.

server/routes/ticketHandlers/schemas.ts

broadcaster.tsImprove SSE subscriber cleanup +14/-0

Improve SSE subscriber cleanup

• Tracks delivery failures and reliably releases disconnected subscribers.

server/sse/broadcaster.ts

startup.tsBlock startup on unsafe recovery +52/-12

Block startup on unsafe recovery

• Runs artifact and session reconciliation before serving potentially inconsistent state.

server/startup.ts

paths.tsTighten storage path construction +24/-13

Tighten storage path construction

• Normalizes roots and rejects paths escaping app-owned storage.

server/storage/paths.ts

projects.tsAlign project storage mutations +6/-6

Align project storage mutations

• Uses canonical contained project paths and asynchronous cleanup.

server/storage/projects.ts

ticketMutations.tsHarden ticket mutations +13/-11

Harden ticket mutations

• Coordinates asynchronous deletion and canonical state updates.

server/storage/ticketMutations.ts

ticketQueries.tsSecure ticket artifact queries +51/-34

Secure ticket artifact queries

• Adds contained path resolution and safe read/write helpers.

server/storage/ticketQueries.ts

beadsOutput.tsCanonicalize beads output aliases +43/-41

Canonicalize beads output aliases

• Applies alias priority without changing distinct-field precedence.

server/structuredOutput/beadsOutput.ts

completionOutput.tsCanonicalize completion output +51/-43

Canonicalize completion output

• Preserves canonical fields while normalizing accepted aliases.

server/structuredOutput/completionOutput.ts

interviewDocument.tsCanonicalize interview documents +26/-26

Canonicalize interview documents

• Uses shared precedence rules without overwriting distinct content.

server/structuredOutput/interviewDocument.ts

interviewOutput.tsAlign interview output aliases +7/-7

Align interview output aliases

• Applies canonical alias normalization consistently.

server/structuredOutput/interviewOutput.ts

prdOutput.tsCanonicalize PRD output aliases +24/-24

Canonicalize PRD output aliases

• Preserves canonical PRD fields during structured-output repair.

server/structuredOutput/prdOutput.ts

refinementChanges.tsHarden refinement change parsing +63/-54

Harden refinement change parsing

• Normalizes aliases deterministically and retains distinct change fields.

server/structuredOutput/refinementChanges.ts

voteOutput.tsAlign vote output normalization +2/-2

Align vote output normalization

• Uses the canonical structured-output precedence contract.

server/structuredOutput/voteOutput.ts

yamlUtils.tsPreserve YAML scalar payloads +153/-45

Preserve YAML scalar payloads

• Avoids stripping XML-like block content, improves warning bookkeeping, and completes parser cache identity.

server/structuredOutput/yamlUtils.ts

initialize.tsHarden ticket initialization cleanup +30/-17

Harden ticket initialization cleanup

• Publishes initial state atomically and removes partial resources after failure.

server/ticket/initialize.ts

mergeCompletion.tsHarden merge completion evidence +104/-17

Harden merge completion evidence

• Distinguishes verified merges from closed-unmerged pull requests and serializes completion.

server/workflow/mergeCompletion.ts

beadsPhase.tsAlign beads phase recovery +3/-3

Align beads phase recovery

• Uses canonical artifact and Git recovery behavior.

server/workflow/phases/beadsPhase.ts

executionPhase.tsHarden execution phase transitions +58/-36

Harden execution phase transitions

• Coordinates checkpoints, Git rollback, and session cleanup before state changes.

server/workflow/phases/executionPhase.ts

executionSetupPhase.tsHarden execution setup phase +18/-11

Harden execution setup phase

• Uses durable artifacts and safe resume behavior.

server/workflow/phases/executionSetupPhase.ts

integrationPhase.tsAlign integration phase mutation +1/-1

Align integration phase mutation

• Awaits the bounded integration Git operation.

server/workflow/phases/integrationPhase.ts

interviewPhase.tsMake interview batches race safe +351/-37

Make interview batches race safe

• Adds dead-owner recovery, stop barriers, snapshot fingerprints, claims, and compare-and-set publication.

server/workflow/phases/interviewPhase.ts

pullRequestPhase.tsPersist observed pull-request state +76/-27

Persist observed pull-request state

• Refreshes remote state safely and records failures without manufacturing merge evidence.

server/workflow/phases/pullRequestPhase.ts

state.tsStrengthen phase state transitions +31/-19

Strengthen phase state transitions

• Adds guarded state helpers and canonical phase metadata.

server/workflow/phases/state.ts

verificationPhase.tsAlign verification phase state +2/-2

Align verification phase state

• Uses canonical workflow phase identifiers and transitions.

server/workflow/phases/verificationPhase.ts

questionWindows.tsHarden question window cleanup +80/-28

Harden question window cleanup

• Coordinates fallback answers, session endings, receipts, and cancellation confirmation.

server/workflow/questionWindows.ts

runOpenCodePrompt.tsTrack prompt sessions before creation +59/-16

Track prompt sessions before creation

• Registers pending ownership and guarantees cleanup across creation, abort, and persistence failures.

server/workflow/runOpenCodePrompt.ts

runner.tsAdd workflow shutdown cleanup +25/-0

Add workflow shutdown cleanup

• Releases runtime resources and reports incomplete cleanup safely.

server/workflow/runner.ts

skipReceipts.tsHarden skip receipt persistence +28/-12

Harden skip receipt persistence

• Adds canonical identities and conflict-safe durable writes.

server/workflow/skipReceipts.ts

yamlRepair.tsPreserve block scalar boundaries +243/-46

Preserve block scalar boundaries

• Corrects sequence-mapping indentation and prevents formatting repairs from rewriting scalar payloads.

shared/yamlRepair.ts

App.tsxReconcile asynchronous modal history +63/-22

Reconcile asynchronous modal history

• Tracks pending Back targets, dirty modals, and drawer containment across route and data changes.

src/App.tsx

ModelPicker.tsxAlign model picker state +3/-3

Align model picker state

• Preserves canonical model selections through configuration updates.

src/components/config/ModelPicker.tsx

ProfileSetup.tsxProtect profile configuration drafts +77/-14

Protect profile configuration drafts

• Tracks dirty state, validation, and safe modal close behavior.

src/components/config/ProfileSetup.tsx

TicketCard.tsxCorrect ticket progress rendering +29/-5

Correct ticket progress rendering

• Uses normalized workflow metadata for accurate phase progress.

src/components/kanban/TicketCard.tsx

BeadsApprovalNavigator.tsxHarden beads approval navigation +46/-4

Harden beads approval navigation

• Handles normalized dependencies, missing beads, and stable selection.

src/components/navigator/BeadsApprovalNavigator.tsx

FolderPicker.tsxImprove folder picker accessibility +21/-5

Improve folder picker accessibility

• Corrects focus, selection, validation, and close interactions.

src/components/project/FolderPicker.tsx

ProjectForm.tsxProtect project form drafts +117/-8

Protect project form drafts

• Adds dirty-state reporting, validation, and guarded asynchronous submission.

src/components/project/ProjectForm.tsx

ProjectsPanel.tsxReconcile project panel state +12/-3

Reconcile project panel state

• Handles asynchronous project changes and modal close state.

src/components/project/ProjectsPanel.tsx

PromptEditor.tsxProtect prompt editor drafts +130/-35

Protect prompt editor drafts

• Adds conflict-aware saves, dirty state, reset handling, and stable selection.

src/components/prompts/PromptEditor.tsx

PromptsDialog.tsxExpose prompt dialog dirty state +2/-1

Expose prompt dialog dirty state

• Connects editor draft state to guarded modal closure.

src/components/prompts/PromptsDialog.tsx

CenteredModal.tsxCentralize modal focus behavior +8/-28

Centralize modal focus behavior

• Uses shared dialog focus and overlay semantics for Escape and containment.

src/components/shared/CenteredModal.tsx

DropdownPicker.tsxCorrect dropdown overlay behavior +23/-3

Correct dropdown overlay behavior

• Improves keyboard dismissal, focus, and active overlay ownership.

src/components/shared/DropdownPicker.tsx

KeyboardShortcuts.tsxAlign shortcut overlay handling +1/-1

Align shortcut overlay handling

• Uses corrected nested overlay Escape ownership.

src/components/shared/KeyboardShortcuts.tsx

TicketDashboard.tsxRelease stale ticket UI containment +45/-3

Release stale ticket UI containment

• Reconciles selection and drawer state when tickets disappear or viewport mode changes.

src/components/ticket/TicketDashboard.tsx

TicketForm.tsxProtect ticket form drafts +51/-7

Protect ticket form drafts

• Adds dirty-state reporting and safe asynchronous submission behavior.

src/components/ticket/TicketForm.tsx

ApprovalView.tsx

[Comment truncated to fit github's 65,536-char limit.]

@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: 3037800eaf

ℹ️ 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 thread server/io/recovery.ts
Comment on lines +323 to +326
if (KNOWN_TICKET_ROOT_ARTIFACTS.has(artifactPath)) return true
if (/^meta\/(?:ticket\.meta|manual-qa-origin)\.json$/.test(artifactPath)) return true
if (/^beads\/.+\/\.beads\/issues\.jsonl$/.test(artifactPath)) return true
if (/^runtime\/(?:owner\.json|state\.yaml|execution-setup-profile\.json|execution-log(?:\.debug|\.ai)?\.jsonl)$/.test(artifactPath)) return true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Include durable ownership markers in recovery allowlist

When the process crashes after safeAtomicWrite finishes a temp file but before rename, this allowlist excludes both runtime/opencode-pending-sessions.json and the root-level opencode-steps-restore.json. Startup therefore leaves those valid temps untouched: the first can make a remotely created OpenCode session undiscoverable after its database insert failed, while the second can strand a project opencode.json with LoopTroop's temporary step cap and lose the saved original configuration. Add these known LoopTroop artifacts to the ticket recovery allowlist.

Useful? React with 👍 / 👎.

Comment on lines +835 to +837
} else {
allConfirmed = false
console.warn(`[sessionManager] Could not confirm abort for OpenCode session ${session.sessionId}; retaining its active row`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Treat an already-missing remote session as stopped

When an active database row outlives its OpenCode session, OpenCodeSDKAdapter.abortSession returns false because directory resolution or the abort request reports the session missing. This branch retains the active row, and cancellation/deletion now requires abortTicketSessions to return true, so every retry is rejected until the daemon is restarted and startup reconciliation abandons the row. Confirm remote absence before aborting, or otherwise treat a definitive not-found response as successful termination.

Useful? React with 👍 / 👎.

Comment thread server/io/fileLock.ts
Comment on lines +44 to +48
database = new Database(lockPath)
// A native busy wait would block this process's event loop. Failed
// attempts return immediately and the caller yields between retries.
database.pragma('busy_timeout = 0')
database.exec('BEGIN IMMEDIATE')

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 Migrate stale legacy lock files before opening SQLite

After upgrading from the immediately preceding file-lock implementation, a process crash can leave index.json.lock containing the old JSON ownership record. Opening that path as SQLite and issuing the pragma fails with SQLITE_NOTADB, which is not classified as busy and is never cleaned up, so all later Manual QA evidence-index mutations remain broken. Detect and safely replace the legacy lock format when no old owner is live, or use a new database filename.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

The PR is not yet safe to merge because a failed post-approval planning restart can leave newly saved planning input paired with downstream artifacts generated from the previous input.

Findings

  1. P1 Save Commits Before Restart ▶

Summary

This PR consolidates a broad cleanup and safety audit across workflow persistence, recovery, Git operations, CLI/daemon behavior, release automation, structured output parsing, and frontend state handling. It also accepts help and ? as per-command CLI help aliases.

  • Adds extensive recovery, containment, concurrency, and lifecycle safeguards across server workflows and durable storage.
  • Hardens repository, process, installer, packaging, and release operations.
  • Expands automated coverage for backend, CLI, workflow, and frontend behavior.
  • No code changed after the previous review.

Reviews (2) · Last reviewed commit: "fix(cli): accept help aliases for comman..."

Comment on lines +180 to +182
result = saveApprovedPrdDocument(ticketId, document, rawParsed.data.expectedContentSha256!, { skipInvalidation: true })
restart = await preparePlanningRestart(ticketId, 'WAITING_PRD_APPROVAL', planningLock)
assertPlanningEditClaim(ticketId, planningLock)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Save Commits Before Restart

For a post-approval PRD edit, this writes the new authoritative document before preparePlanningRestart() confirms that active sessions stopped and the caller still owns the planning claim. If session shutdown fails or the claim is lost during that await, the endpoint returns an error but the new PRD remains stored while the previous downstream beads and artifacts remain valid. This can pair a new planning input with outputs generated from the old input. The interview save path has the same ordering in server/routes/ticketHandlers/interviewHandlers.ts.

Knowledge Base Used: Ticket state and durable storage

@qodo-code-review

qodo-code-review Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (8) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Evidence updates fail after upgrade 🐞 Bug ☼ Reliability
Description
tryAcquire now opens the existing index.json.lock as a SQLite database and rethrows errors that
are not lock contention. Installations that retain the JSON lock file written by the previous
implementation therefore receive a “file is not a database” error whenever the manual-QA evidence
index reaches withFileLock.
Code

server/io/fileLock.ts[44]

+    database = new Database(lockPath)
Relevance

●● Moderate

Upgrade compatibility concern is plausible, but no closely matching lock-migration precedent was
found.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed acquisition path treats only SQLite busy errors as retryable, while the evidence-index
writer continues using the same index.json.lock filename. A legacy non-SQLite file therefore
escapes the retry loop and fails the update.

server/io/fileLock.ts[34-53]
server/phases/manualQa/storage.ts[442-459]

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

## Issue description
Existing JSON lock files are incompatible with the new SQLite-backed lock implementation, so upgrades can permanently block evidence-index updates.

## Fix Focus Areas
- server/io/fileLock.ts[40-53]
- server/phases/manualQa/storage.ts[442-459]

## Recommended Fix
Before opening a lock path as SQLite, detect the legacy JSON lock format and safely remove or migrate it only when it is confirmed to be an old abandoned lock. Preserve normal SQLite corruption failures rather than treating arbitrary malformed files as removable.

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


2. A coding session escapes cleanup 🐞 Bug ☼ Reliability
Description
rememberPendingSessionOwnership performs an unlocked read-append-write of the complete
pending-session marker file. When two processes persist fallback ownership for the same ticket, the
later write can overwrite the earlier record, so ticket cleanup and restart recovery cannot find
that remote session.
Code

server/opencode/sessionManager.ts[R173-176]

+  const current = readPendingSessionOwnership(ticketId)
+  if (!current.readable) return false
+  if (current.records.some(candidate => candidate.sessionId === record.sessionId)) return true
+  return writePendingSessionOwnership(ticketId, [...current.records, record])
Relevance

●● Moderate

Concurrent fallback ownership loss is a credible cleanup race, but no close session-marker precedent
was found.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new marker writer replaces the whole file, and the new fallback path invokes it after the remote
session has already been created. Cleanup only enumerates durable rows and the marker snapshot, so
an overwritten record is not aborted or recovered.

server/opencode/sessionManager.ts[156-184]
server/opencode/sessionManager.ts[405-500]
server/opencode/sessionManager.ts[756-769]
server/opencode/sessionManager.ts[842-892]

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

## Issue description
Concurrent fallback ownership writes can overwrite one another, losing a live remote session from durable cleanup and restart recovery.

## Fix Focus Areas
- server/opencode/sessionManager.ts[156-184]
- server/opencode/sessionManager.ts[405-500]
- server/opencode/sessionManager.ts[748-892]

## Recommended Fix
Protect reads and writes of the pending-session ownership artifact with a cross-process lock or an atomic compare-and-retry merge. Apply the same serialization to removal so an older cleanup cannot overwrite a concurrent addition.

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



Remediation recommended

3. Native models disappear from filters 🐞 Bug ≡ Correctness
Description
queryDebugPage builds modelIds exclusively from execution_log_projection even though the page
and totals also include native OpenCode rows. A model represented only in native history
consequently appears in the debug log but cannot be selected through the frontend model filter.
Code

server/log/projection.ts[R1330-1333]

+    const modelSql = `SELECT DISTINCT model_id
+      FROM execution_log_projection AS p
+      WHERE ${clauses.join(' AND ')} AND ${DEBUG_VISIBLE_ROWS} AND model_id IS NOT NULL
+      ORDER BY model_id`
Relevance

●●● Strong

Recent log-history precedent accepted fixes preserving rows and model visibility across query paths.

PR-#158

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Native rows are fetched for the debug page and included in totals, but the model catalog SQL reads
only the persisted projection table. The frontend takes page.modelIds from that response as the
selectable catalog.

server/log/projection.ts[1326-1339]
server/log/projection.ts[1353-1375]
server/log/projection.ts[816-817]
server/log/projection.ts[1146-1149]
src/hooks/useTicketHistoricalLogs.ts[345-355]

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

### Issue description
The debug model catalog excludes model identifiers stored only in the native-log index, so the UI cannot offer filters for all displayed rows.

### Fix Focus Areas
- server/log/projection.ts[1326-1339]
- server/log/projection.ts[1353-1375]
- src/hooks/useTicketHistoricalLogs.ts[345-355]

### Recommended Fix
Query distinct model identifiers from the active native snapshot using the same ticket and scope filters, merge them with projection model identifiers, deduplicate them, and return a deterministically sorted catalog on the first page.

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


4. Other resolved questions remain visible 🐞 Bug ≡ Correctness
Description
applySnapshot marks an entire successful snapshot non-authoritative when it contains even one
tombstoned request, suppressing pruning for every other request on that ticket. If stale resolved
request A remains in the server response while live request B has disappeared, B stays visible and
A's tombstone is not cleared until a later response finally omits A.
Code

src/context/AIQuestionContext.tsx[R442-445]

+    const authoritative = options.prune !== false && !containsResolvedRequest
+    if (authoritative) {
+      pruneTicketRequests(setRequests, ticketId, live)
+      applyTimer(ticketId, timer)
Relevance

●●● Strong

Recent question-state precedent explicitly accepts fixes ensuring authoritative snapshots prune
omitted requests correctly.

PR-#141

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The loop records all returned keys but skips tombstoned upserts, then containsResolvedRequest
disables pruning and tombstone cleanup globally. This contradicts the adjacent invariant that a
successful snapshot should remove requests it omits.

src/context/AIQuestionContext.tsx[420-446]
src/context/AIQuestionContext.tsx[157-168]
src/context/AIQuestionContext.tsx[437-446]

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

### Issue description
One tombstoned request globally disables authoritative processing of an otherwise successful ticket snapshot, retaining unrelated questions that the server omitted.

### Fix Focus Areas
- src/context/AIQuestionContext.tsx[420-446]
- src/context/AIQuestionContext.tsx[157-168]

### Recommended Fix
Continue suppressing individual tombstoned requests during upsert, but still prune locally displayed requests absent from a successful authoritative snapshot and clear only tombstones whose keys are absent. Do not make the whole snapshot non-authoritative merely because one returned key is tombstoned.

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


5. Canceled tickets retain stale state 🐞 Bug ☼ Reliability
Description
attachWorkflowRunner removes cancellationCleanupInFlight after an unconfirmed or failed cleanup
without retaining or scheduling another attempt. When recovery starts from an already canceled
ticket, a transient session-abort or window-clear failure therefore leaves its remote-session and
question bookkeeping indefinitely because later cancel requests reject terminal tickets.
Code

server/workflow/runner.ts[R254-256]

+          if (!sessionsStopped || !windowsCleared) {
+            console.warn(`[workflow] Could not confirm cancellation cleanup for ticket ${ticketId}; retaining remote-session state`)
+            return
Relevance

●●● Strong

Recent workflow precedent accepts fixes preventing cleanup races and preserving reliable rollback or
recovery state.

PR-#122

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runner returns on either unconfirmed cleanup result and always removes its only in-flight
marker. Terminal-state validation prevents a user from retriggering cancellation, while the state
cleanup deliberately preserves remote bookkeeping until confirmation.

server/workflow/runner.ts[247-265]
server/routes/ticketHandlers/lifecycleHandlers.ts[402-410]
server/opencode/sessionManager.ts[804-826]
server/workflow/questionWindows.ts[1038-1059]
server/workflow/phases/state.ts[103-113]

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

### Issue description
Cancellation recovery abandons cleanup after one transient failure, and an already canceled ticket cannot be canceled again to trigger another attempt.

### Fix Focus Areas
- server/workflow/runner.ts[247-265]
- server/routes/ticketHandlers/lifecycleHandlers.ts[402-410]
- server/workflow/phases/state.ts[103-113]

### Recommended Fix
Keep failed cancellation cleanup pending and retry it with bounded backoff until session abort and question-window cleanup are confirmed. Preserve the in-flight deduplication guard while a retry series is active, and only call `cleanupTicketState` and clear the pending record after confirmed success.

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


View medium (3)
6. OpenCode server survives shutdown 🐞 Bug ☼ Reliability
Description
spawnAndWait stores a managed child even when its one-time readProcessStartToken call returns
null. The new guarded termination methods refuse both graceful and forced termination for a null
token, so a live child whose initial identity lookup transiently fails remains running and can
retain the service port.
Code

server/opencode/supervisor.ts[R288-292]

+    const pid = child.pid
+    // Capture the identity at spawn time. A pid alone can be recycled while a
+    // health wait or shutdown is in progress, so every later termination check
+    // must compare against this original token rather than infer one late.
+    const startToken = pid === undefined ? null : readProcessStartToken(pid)
Relevance

●●● Strong

Matches the branch’s explicit process-identity hardening intent; null-token shutdown failure is a
concrete reliability bug.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed launch path records null identity values, while the changed termination implementation
treats a null expected token as unverifiable and does not signal. The termination caller
subsequently logs failure but leaves the child alive.

server/opencode/supervisor.ts[75-108]
server/opencode/supervisor.ts[288-311]
server/opencode/supervisor.ts[434-463]
server/cli/processControl.ts[56-63]

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

## Issue description
A managed OpenCode child with no captured process identity cannot be terminated by the new fail-closed shutdown path.

## Fix Focus Areas
- server/opencode/supervisor.ts[75-108]
- server/opencode/supervisor.ts[288-311]
- server/opencode/supervisor.ts[434-463]

## Recommended Fix
Retry identity capture before registering the child as managed, and fail the launch with safe owned-child cleanup if no token can be obtained. Do not retain a managed child whose shutdown path is guaranteed to refuse termination.

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


7. Expansion diffs compare wrong beads 🐞 Bug ≡ Correctness
Description
pairExpansionBeads pairs equal-length parsed arrays by index even though each artifact parser
independently drops malformed rows. If different source positions are dropped while the surviving
arrays retain equal lengths, the approval view compares unrelated beads and reports incorrect added
fields and identifiers.
Code

src/components/workspace/ArtifactContentViewer.tsx[R1695-1697]

+  if (planBeads.length === expandedBeads.length) {
+    return expandedBeads.map((expandedBead, index) => ({ planBead: planBeads[index], expandedBead }))
+  }
Relevance

●●● Strong

Recent bead-editor precedent accepts correctness fixes preventing silent loss or misrepresentation
of bead data.

PR-#149

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new helper switches to positional pairing solely from equal filtered lengths.
parseBeadsArtifact skips invalid entries independently, and the resulting pairs directly drive
both displayed identifiers and added-field counts.

src/components/workspace/ArtifactContentViewer.tsx[1694-1709]
src/components/workspace/ArtifactContentViewer.tsx[1761-1767]
src/lib/beadsDocument.ts[472-474]
src/lib/beadsDocument.ts[490-514]

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

### Issue description
Independent parser filtering can shift equal-length plan and expansion arrays, making positional pairing compare unrelated beads.

### Fix Focus Areas
- src/components/workspace/ArtifactContentViewer.tsx[1694-1703]
- src/lib/beadsDocument.ts[472-474]
- src/lib/beadsDocument.ts[490-514]

### Recommended Fix
Preserve each bead's original source-row position while parsing and pair renamed expansion beads using those positions, leaving gaps for malformed rows rather than compacting both arrays independently. Use exact identifier matches where available and do not infer positional alignment solely from equal filtered lengths.

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


8. Timeout can kill unrelated processes 🐞 Bug ☼ Reliability
Description
runAsyncRaw starts a detached process group but retains it across timeout, output-limit, and
delayed force-kill callbacks without capturing and passing the process start token that
terminateProcessTree needs to verify the leader’s identity. If Git exits and its PID or group is
reused before cleanup runs, the negative-PID signal can reach an unrelated replacement process or
process group.
Code

server/git/runCommand.ts[R466-470]

+        // `terminateProcessTree` signals the negative pid on POSIX. A detached
+        // child starts its own process group, so Git hooks, filters, and their
+        // descendants receive the same timeout signal instead of surviving
+        // after the runner has returned.
+        detached: process.platform !== 'win32',
Relevance

●●● Strong

Directly matches the PR’s cleanup-hardening intent; PID-reuse protection is an obvious reliability
fix.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed Git runner deliberately creates a detached process group and invokes tree termination
from asynchronous timeout and cleanup paths without an identity token. terminateProcessTree
validates the retained PID only when the optional expected start token is supplied; otherwise it
signals the negative PID directly, while the general command executor demonstrates the required
capture-and-pass pattern.

server/git/runCommand.ts[463-471]
server/git/runCommand.ts[499-502]
server/git/runCommand.ts[551-562]
server/lib/processTree.ts[102-149]
server/git/runCommand.ts[463-470]
server/lib/processTree.ts[101-117]
server/lib/processTree.ts[194-216]
server/lib/commandExecutor.ts[311-314]

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

## Issue description
Asynchronous Git termination retains only the detached child PID and does not confirm that it still identifies the spawned process, so delayed overrun, timeout, or force-kill cleanup can signal a recycled PID and an unrelated process or process group.

## Fix Focus Areas
- server/git/runCommand.ts[460-471]
- server/git/runCommand.ts[499-502]
- server/git/runCommand.ts[551-562]
- server/lib/processTree.ts[101-149]

## Recommended Fix
Capture the child process start token immediately after spawning Git and pass it through a shared, guarded process-tree escalation path for every output-limit overrun, timeout, and delayed force-kill. Skip destructive group signals and report the command as abandoned if identity capture fails or later verification shows that the leader identity changed, while retaining safe descendant cleanup when the original process group remains proven.

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


Grey Divider

Context sources
Review mode: 🧠 Deep: This is an unusually dense, cross-cutting audit spanning 360 files and 1,835 hunks across security, recovery, workflows, installers, server logic, and UI, making multiple independent subtle defects especially likely.

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread server/workflow/runner.ts
Comment on lines +254 to +256
if (!sessionsStopped || !windowsCleared) {
console.warn(`[workflow] Could not confirm cancellation cleanup for ticket ${ticketId}; retaining remote-session state`)
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.

Remediation recommended

3. Canceled tickets retain stale state 🐞 Bug ☼ Reliability

attachWorkflowRunner removes cancellationCleanupInFlight after an unconfirmed or failed cleanup
without retaining or scheduling another attempt. When recovery starts from an already canceled
ticket, a transient session-abort or window-clear failure therefore leaves its remote-session and
question bookkeeping indefinitely because later cancel requests reject terminal tickets.
Agent Prompt
### Issue description
Cancellation recovery abandons cleanup after one transient failure, and an already canceled ticket cannot be canceled again to trigger another attempt.

### Fix Focus Areas
- server/workflow/runner.ts[247-265]
- server/routes/ticketHandlers/lifecycleHandlers.ts[402-410]
- server/workflow/phases/state.ts[103-113]

### Recommended Fix
Keep failed cancellation cleanup pending and retry it with bounded backoff until session abort and question-window cleanup are confirmed. Preserve the in-flight deduplication guard while a retry series is active, and only call `cleanupTicketState` and clear the pending record after confirmed success.

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

Comment on lines +1695 to +1697
if (planBeads.length === expandedBeads.length) {
return expandedBeads.map((expandedBead, index) => ({ planBead: planBeads[index], expandedBead }))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. Expansion diffs compare wrong beads 🐞 Bug ≡ Correctness

pairExpansionBeads pairs equal-length parsed arrays by index even though each artifact parser
independently drops malformed rows. If different source positions are dropped while the surviving
arrays retain equal lengths, the approval view compares unrelated beads and reports incorrect added
fields and identifiers.
Agent Prompt
### Issue description
Independent parser filtering can shift equal-length plan and expansion arrays, making positional pairing compare unrelated beads.

### Fix Focus Areas
- src/components/workspace/ArtifactContentViewer.tsx[1694-1703]
- src/lib/beadsDocument.ts[472-474]
- src/lib/beadsDocument.ts[490-514]

### Recommended Fix
Preserve each bead's original source-row position while parsing and pair renamed expansion beads using those positions, leaving gaps for malformed rows rather than compacting both arrays independently. Use exact identifier matches where available and do not infer positional alignment solely from equal filtered lengths.

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

Comment thread server/log/projection.ts
Comment on lines +1330 to +1333
const modelSql = `SELECT DISTINCT model_id
FROM execution_log_projection AS p
WHERE ${clauses.join(' AND ')} AND ${DEBUG_VISIBLE_ROWS} AND model_id IS NOT NULL
ORDER BY model_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.

Remediation recommended

5. Native models disappear from filters 🐞 Bug ≡ Correctness

queryDebugPage builds modelIds exclusively from execution_log_projection even though the page
and totals also include native OpenCode rows. A model represented only in native history
consequently appears in the debug log but cannot be selected through the frontend model filter.
Agent Prompt
### Issue description
The debug model catalog excludes model identifiers stored only in the native-log index, so the UI cannot offer filters for all displayed rows.

### Fix Focus Areas
- server/log/projection.ts[1326-1339]
- server/log/projection.ts[1353-1375]
- src/hooks/useTicketHistoricalLogs.ts[345-355]

### Recommended Fix
Query distinct model identifiers from the active native snapshot using the same ticket and scope filters, merge them with projection model identifiers, deduplicate them, and return a deterministically sorted catalog on the first page.

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

Comment on lines +442 to +445
const authoritative = options.prune !== false && !containsResolvedRequest
if (authoritative) {
pruneTicketRequests(setRequests, ticketId, live)
applyTimer(ticketId, timer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

6. Other resolved questions remain visible 🐞 Bug ≡ Correctness

applySnapshot marks an entire successful snapshot non-authoritative when it contains even one
tombstoned request, suppressing pruning for every other request on that ticket. If stale resolved
request A remains in the server response while live request B has disappeared, B stays visible and
A's tombstone is not cleared until a later response finally omits A.
Agent Prompt
### Issue description
One tombstoned request globally disables authoritative processing of an otherwise successful ticket snapshot, retaining unrelated questions that the server omitted.

### Fix Focus Areas
- src/context/AIQuestionContext.tsx[420-446]
- src/context/AIQuestionContext.tsx[157-168]

### Recommended Fix
Continue suppressing individual tombstoned requests during upsert, but still prune locally displayed requests absent from a successful authoritative snapshot and clear only tombstones whose keys are absent. Do not make the whole snapshot non-authoritative merely because one returned key is tombstoned.

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

Comment thread server/io/fileLock.ts
rmSync(lockPath, { force: true })
} catch {
// Gone already, or unreadable; the next acquire attempt decides.
database = new Database(lockPath)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Evidence updates fail after upgrade 🐞 Bug ☼ Reliability

tryAcquire now opens the existing index.json.lock as a SQLite database and rethrows errors that
are not lock contention. Installations that retain the JSON lock file written by the previous
implementation therefore receive a “file is not a database” error whenever the manual-QA evidence
index reaches withFileLock.
Agent Prompt
## Issue description
Existing JSON lock files are incompatible with the new SQLite-backed lock implementation, so upgrades can permanently block evidence-index updates.

## Fix Focus Areas
- server/io/fileLock.ts[40-53]
- server/phases/manualQa/storage.ts[442-459]

## Recommended Fix
Before opening a lock path as SQLite, detect the legacy JSON lock format and safely remove or migrate it only when it is confirmed to be an old abandoned lock. Preserve normal SQLite corruption failures rather than treating arbitrary malformed files as removable.

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

Comment on lines +173 to +176
const current = readPendingSessionOwnership(ticketId)
if (!current.readable) return false
if (current.records.some(candidate => candidate.sessionId === record.sessionId)) return true
return writePendingSessionOwnership(ticketId, [...current.records, record])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. A coding session escapes cleanup 🐞 Bug ☼ Reliability

rememberPendingSessionOwnership performs an unlocked read-append-write of the complete
pending-session marker file. When two processes persist fallback ownership for the same ticket, the
later write can overwrite the earlier record, so ticket cleanup and restart recovery cannot find
that remote session.
Agent Prompt
## Issue description
Concurrent fallback ownership writes can overwrite one another, losing a live remote session from durable cleanup and restart recovery.

## Fix Focus Areas
- server/opencode/sessionManager.ts[156-184]
- server/opencode/sessionManager.ts[405-500]
- server/opencode/sessionManager.ts[748-892]

## Recommended Fix
Protect reads and writes of the pending-session ownership artifact with a cross-process lock or an atomic compare-and-retry merge. Apply the same serialization to removal so an older cleanup cannot overwrite a concurrent addition.

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

Comment thread server/git/runCommand.ts
Comment on lines +466 to +470
// `terminateProcessTree` signals the negative pid on POSIX. A detached
// child starts its own process group, so Git hooks, filters, and their
// descendants receive the same timeout signal instead of surviving
// after the runner has returned.
detached: process.platform !== 'win32',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

7. Timeout can kill unrelated processes 🐞 Bug ☼ Reliability

runAsyncRaw starts a detached process group but retains it across timeout, output-limit, and
delayed force-kill callbacks without capturing and passing the process start token that
terminateProcessTree needs to verify the leader’s identity. If Git exits and its PID or group is
reused before cleanup runs, the negative-PID signal can reach an unrelated replacement process or
process group.
Agent Prompt
## Issue description
Asynchronous Git termination retains only the detached child PID and does not confirm that it still identifies the spawned process, so delayed overrun, timeout, or force-kill cleanup can signal a recycled PID and an unrelated process or process group.

## Fix Focus Areas
- server/git/runCommand.ts[460-471]
- server/git/runCommand.ts[499-502]
- server/git/runCommand.ts[551-562]
- server/lib/processTree.ts[101-149]

## Recommended Fix
Capture the child process start token immediately after spawning Git and pass it through a shared, guarded process-tree escalation path for every output-limit overrun, timeout, and delayed force-kill. Skip destructive group signals and report the command as abandoned if identity capture fails or later verification shows that the leader identity changed, while retaining safe descendant cleanup when the original process group remains proven.

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

Comment on lines +288 to +292
const pid = child.pid
// Capture the identity at spawn time. A pid alone can be recycled while a
// health wait or shutdown is in progress, so every later termination check
// must compare against this original token rather than infer one late.
const startToken = pid === undefined ? null : readProcessStartToken(pid)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

8. Opencode server survives shutdown 🐞 Bug ☼ Reliability

spawnAndWait stores a managed child even when its one-time readProcessStartToken call returns
null. The new guarded termination methods refuse both graceful and forced termination for a null
token, so a live child whose initial identity lookup transiently fails remains running and can
retain the service port.
Agent Prompt
## Issue description
A managed OpenCode child with no captured process identity cannot be terminated by the new fail-closed shutdown path.

## Fix Focus Areas
- server/opencode/supervisor.ts[75-108]
- server/opencode/supervisor.ts[288-311]
- server/opencode/supervisor.ts[434-463]

## Recommended Fix
Retry identity capture before registering the child as managed, and fail the launch with safe owned-child cleanup if no token can be obtained. Do not retain a managed child whose shutdown path is guaranteed to refuse termination.

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

@looptroop-ai

Copy link
Copy Markdown
Owner Author

PR #170 currently has merge conflicts and several failing checks that stem from branch history:

  1. Branch base and merge conflict: The branch fix/consolidated-cleanup-audit was created off commit 83ae3243 before PRs fix: release, installer, and executable safety audit (part 1) #163 through fix: client recovery, unsaved drafts, and complete log history #169 were squash-merged into main. Because the branch still carries 11 pre-merge audit commits, GitHub marks the PR as conflicting (mergeable: CONFLICTING), and the diff touches 360 files (~16,000 deletions) that conflict with or revert commits already on main.

  2. Check failures:

    • CodeQL failed with two security alerts in files carried over from older commits (server/io/atomicWrite.ts and server/git/__tests__/runCommand.test.ts).
    • Codacy reported 41 new issues.
    • Socket Security skipped alerts because the pull request cannot merge cleanly.
      These issues are not present on current main, where CI and CodeQL are green.
  3. Branch resolution: The actual new change is commit 3037800e (fix(cli): accept help aliases for command help), which touches only server/cli/cli.ts, server/cli/__tests__/cliUpdate.test.ts, and CHANGELOG.md. Rebasing or cherry-picking 3037800e directly onto fresh origin/main (resolving the small CHANGELOG.md conflict) drops the 11 redundant audit commits, removes the 357 extra file diffs, and clears the CodeQL/Codacy failures.

  4. CLI alias behavior note: The implementation checks positionals[1] === 'help' || positionals[1] === '?', which supports looptroop <command> help and looptroop <command> ?. Note that looptroop help <command> and bare looptroop help are not handled by this check and exit with Unknown command "help". If supporting those forms is also intended, command === 'help' would need to be handled.

@looptroop-ai
looptroop-ai force-pushed the fix/consolidated-cleanup-audit branch 2 times, most recently from 3037800 to d0b4c2f Compare September 20, 2026 13:27
@gitar-bot

gitar-bot Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
CI failed: 5 test failures in server/io/__tests__/atomicIO.test.ts due to macOS symlink path resolution differences with `/var/folders`.

Overview

5 test failures were found in server/io/tests/atomicIO.test.ts across 2 jobs, all sharing the same root cause related to macOS symlink resolution for temporary directories.

Failures

recoverOrphanTmpFiles Path Resolution Failures (confidence: high)

  • Type: test
  • Affected jobs: 106083681131, 106085674486
  • Related to change: yes
  • Root cause: The macOS temporary directory path /var/folders/... is a symbolic link to /private/var/folders/.... The recoverOrphanTmpFiles implementation returns real/resolved canonical paths, while test expectations use unresolvably symlinked paths, causing array inclusion and deep equality assertions to fail.
  • Suggested fix: Normalize paths using fs.realpathSync or path.resolve inside the tests or in recoverOrphanTmpFiles to ensure consistent path comparison across operating systems.

Summary

  • Change-related failures: 5 test failures in atomicIO.test.ts due to unnormalized symlink paths on macOS.
  • Infrastructure/flaky failures: None.
  • Recommended action: Update the test suite or implementation to normalize paths using fs.realpathSync to handle macOS symlinks cleanly.
Code Review ✅ Approved

🔴 High risk

Completes consolidated cleanup, recovery, security, and delivery audit across multiple subsystems including CLI, workflow, client state, and filesystem operations. Adds help and ? as aliases for per-command CLI help. No issues found.

Review coverage

Rules No rules evaluated

Functional validation Not enabled · Set up

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Important

Your trial ends in 4 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more.

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
3.1% Duplication on New Code (required ≤ 3%)
D Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@looptroop-ai

Copy link
Copy Markdown
Owner Author

Superseded by the clean, main-based CLI-only PR #171.

@looptroop-ai
looptroop-ai deleted the fix/consolidated-cleanup-audit branch September 20, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants