Skip to content

[Epic] 1950-epic-cross-platform-dsk - #1970

Draft
propr-dev[bot] wants to merge 187 commits into
mainfrom
1950-epic-cross-platform-dsk
Draft

[Epic] 1950-epic-cross-platform-dsk#1970
propr-dev[bot] wants to merge 187 commits into
mainfrom
1950-epic-cross-platform-dsk

Conversation

@propr-dev

@propr-dev propr-dev Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Epic PR

This PR aggregates all changes from child PRs merged to the 1950-epic-cross-platform-dsk branch.


Created automatically by ProPR

propr-dev[bot] and others added 30 commits August 29, 2026 14:23
…gine for CLI

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
…tance connec

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
…nstance conn

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
…compatibilit

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
…untime and r

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
Implemented the follow-up fix without committing.

- [pr-build-check.yml](/tmp/git-processor/worktrees/integry/propr/pr-1963-followup-2026-08-29T14-25-06/.github/workflows/pr-build-check.yml:34) now builds `@propr/local-setup` before every affected CLI typecheck/test.
- [build-publish.mjs](/tmp/git-processor/worktrees/integry/propr/pr-1963-followup-2026-08-29T14-25-06/packages/cli/scripts/build-publish.mjs:77) now builds and vendors `@propr/local-setup`, rewriting private workspace imports for the standalone CLI package.

Verified successfully:

- Local-setup and CLI typechecks
- CLI lint
- Hosted-tunnel suite: 312 tests passed
- Init JSON suite: 12 passed
- Local-setup suite: 9 passed
- Agent Skill suite: 62 passed, 1 platform skip
- CLI package dry-run and installed-tarball smoke test
- YAML parsing and `git diff --check`

Docker was unavailable locally, so the exact containerized `actionlint` invocation could not run.

PR: #1963
Comment by: @github-actions[bot] (ID: 5462947943)
Model: gpt-5.6-sol
…s](/tmp/git-processor/worktrees/integry/propr/pr-1963-followup-2026-08-29T14-34-00/packages/cli/src/commands/taskInspectCommands.test.ts:107).

Fixed the full-suite failure in [taskInspectCommands.test.ts](/tmp/git-processor/worktrees/integry/propr/pr-1963-followup-2026-08-29T14-34-00/packages/cli/src/commands/taskInspectCommands.test.ts:107).

The test now validates concurrent state requests without assuming nondeterministic request order. Canonical output ordering remains separately verified.

Validation:

- Focused test passed 20 consecutive runs
- CLI typecheck passed
- `git diff --check` passed
- No commit created

PR: #1963
Comment by: @github-actions[bot] (ID: 5462991038)
Model: gpt-5.6-sol
…p-shaped-ui-20260829-1408-e9w

[1959 by GPT-5.6 Sol] Add the desktop-shaped UI mode and instance connection experience
…d-propr-api-20260829-1408-n3k

[1954 by GPT-5.6 Sol] Create a shared ProPR API client and instance connection model
…anging Electron security configuration.

Implemented the packaging supply-chain follow-up without changing Electron security configuration.

Changes:

- Upgraded all Electron Forge packages to `8.0.0-alpha.10`.
- Pinned safe overrides:
  - `@electron/packager` 20.3.0
  - `@electron/rebuild` 4.2.0
- Regenerated [package-lock.json](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T14-44-22/package-lock.json).
- Added separate runtime and packaging audit scripts in [package.json](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T14-44-22/package.json).
- Added a lockfile-first [desktop release guard](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T14-44-22/.github/workflows/desktop-release-guard.yml) that fails:
  - Runtime advisories at low or higher.
  - Desktop packaging advisories at high or critical.
- Documented the audit policy in [apps/desktop/README.md](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T14-44-22/apps/desktop/README.md).

Verification passed:

- Clean `npm ci`
- Runtime audit: 0 vulnerabilities
- Desktop packaging audit: 0 vulnerabilities
- Full `npm audit`: 0 vulnerabilities
- Desktop/UI typecheck
- 15 desktop tests
- Linux desktop packaging
- Workflow YAML validation and `git diff --check`

The vulnerable `extract-zip`, Electron `node-gyp`, and `cacache` chains are absent. No advisory exception or constrained-exposure documentation was necessary. Changes remain uncommitted as requested.

PR: #1967
Comment by: @integry (ID: 5463039825)
Model: gpt-5.6-sol
…ktop-pairin-20260829-1408-o5i

[1955 by GPT-5.6 Sol] Add secure desktop pairing tokens and compatibility discovery to the API
Implemented the release-blocking packaging fix.

- Disabled only `LoadBrowserProcessSpecificV8Snapshot`; all hardened fuses remain enforced.
- Added a packaged Linux smoke test that:
  - Validates every fuse state.
  - Launches without `--no-sandbox` or `--disable-sandbox`.
  - Requires Electron’s `ready-to-show` renderer event.
  - Requires a clean exit.
- Added the smoke test to the desktop release guard using Xvfb and a correctly configured Chromium setuid sandbox helper.
- Added `desktop:smoke` and documented its usage.

Verification passed:

- Shared package build
- Desktop/UI typecheck
- All 15 desktop tests
- Forge Linux packaging
- Fuse inspection, including the snapshot fuse disabled
- Script syntax and `git diff --check`

The current execution container cannot complete the final launch because it prohibits user namespaces and provides no root/sudo or Xvfb; Electron correctly failed closed instead of disabling its sandbox. The release CI now supplies the required sandbox helper configuration and display server to execute that proof automatically.

PR: #1967
Comment by: @integry (ID: 5463056792)
Model: gpt-5.6-sol
Implemented the self-contained desktop preparation:

- Added `desktop:prepare` to build `@propr/shared`.
- Made `desktop:typecheck` and `desktop:package` invoke preparation first.
- Added `packages/shared/**` to the release-guard trigger.
- Documented the behavior.

Files changed: [package.json](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-02-01/package.json:75), [desktop-release-guard.yml](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-02-01/.github/workflows/desktop-release-guard.yml:10), and [README.md](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-02-01/apps/desktop/README.md:23).

Verification:

- Runtime audit: 0 vulnerabilities
- Packaging audit: 0 vulnerabilities
- `npm ci`: passed
- Typecheck from absent `packages/shared/dist`: passed and recreated output
- Desktop tests: 15/15 passed
- Forge Linux package: passed, independently rebuilding shared first
- JSON, script syntax, and `git diff --check`: passed

The packaged launch smoke was attempted but this execution host lacks both `sudo` and Xvfb and forbids unprivileged user namespaces. The harness verified the fuse configuration, then correctly failed closed because `chrome-sandbox` could not be made root-owned mode `4755`. The CI workflow retains the required sandbox-helper setup and Xvfb launch steps.

PR: #1967
Comment by: @integry (ID: 5463103357)
Model: gpt-5.6-sol
…tmp/git-processor/worktrees/integry/propr/pr-1963-followup-2026-08-29T14-56-46/.github/workflows/cli-node-compatibility.yml:6):

Implemented the follow-up in [cli-node-compatibility.yml](/tmp/git-processor/worktrees/integry/propr/pr-1963-followup-2026-08-29T14-56-46/.github/workflows/cli-node-compatibility.yml:6):

- Builds `@propr/shared`, then `@propr/local-setup`, before project-options tests.
- Triggers compatibility checks when `packages/local-setup/**` changes.
- Audited other clean-checkout CLI paths; they already prepare both dependencies via explicit builds, `test:prepare`, or self-contained `cli:pack`.

Validation passed:

- Node 22: 26/26 project-options tests
- Node 24: 26/26 project-options tests
- Full suite: all 309 test files plus UI workspace passed; UI 465/465 tests
- `npm run cli:pack`
- Actionlint 1.7.12
- Workflow YAML parsing and `git diff --check`

Only the compatibility workflow is modified. No commit was created.

PR: #1963
Comment by: @integry (ID: 5463097453)
Model: gpt-5.6-sol
…-agnostic-l-20260829-1408-o4c

[1958 by GPT-5.6 Sol] Extract the UI-agnostic local setup engine for CLI and desktop use
…ed release smoke:

Implemented the Electron entry-format repair and strengthened release smoke:

- Main/preload now emit explicit CommonJS `.cjs` bundles; packaged manifest and preload path match.
- Packaged renderer uses a restricted app-owned protocol, preserving the disabled file-protocol privilege fuse, as [Electron recommends](https://www.electronjs.org/docs/latest/tutorial/security).
- Renderer-ready is emitted only after verifying `window.proprDesktop`.
- Smoke rejects known main-process uncaught-exception markers.

Key changes: [package.json](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-14-42/apps/desktop/package.json:11), [main.ts](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-14-42/apps/desktop/src/main.ts:22), [smoke-packaged.mjs](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-14-42/apps/desktop/scripts/smoke-packaged.mjs:12).

Validation:

- Typecheck: passed
- Desktop tests: 15/15 passed
- Forge package: passed
- Packaged manifest/bundle inspection: passed
- Fuse validation: passed, including V8 snapshot fuse disabled
- Functional packaged launch: reached renderer-ready with `"preloadBridgeExposed":true`

The exact sandbox smoke was rerun but this container lacks `sudo` and cannot make `chrome-sandbox` root-owned mode `4755`; Chromium correctly refused to start rather than disabling sandboxing. The existing release workflow performs that ownership setup before running the unchanged smoke command.

PR: #1967
Comment by: @integry (ID: 5463184150)
Model: gpt-5.6-sol
…epic-desktop-experience-uxs

Automatically resolved merge conflicts after merging target branch into PR branch.
Resolved conflicts in:
- propr-ui/src/api/apiClient.ts
- propr-ui/src/api/compatibility.ts

PR: #1968
Model: gpt-5.6-sol
…worktrees/integry/propr/pr-1968-followup-2026-08-29T15-39-39/propr-ui/src/App.tsx:458). The merged file exceeded ESLint’s 400-line limit by one effective line; the default wrapper is now a compact named function with unchanged behavior.

Fixed the PR build failure in [App.tsx](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T15-39-39/propr-ui/src/App.tsx:458). The merged file exceeded ESLint’s 400-line limit by one effective line; the default wrapper is now a compact named function with unchanged behavior.

Validation passed:

- UI lint with zero warnings
- UI typecheck
- UI production build
- Focused App and desktop-pairing tests: 9/9
- `git diff --check`

Only `propr-ui/src/App.tsx` was modified. No commit was created.

PR: #1968
Comment by: @github-actions[bot] (ID: 5463307288)
Model: gpt-5.6-sol
…ing the user-facing product name and all security settings.

Implemented the Linux space-free package path while preserving the user-facing product name and all security settings.

Changes:

- Forge now emits `apps/desktop/out/propr-desktop-linux-x64` via [forge.config.ts](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-42-24/apps/desktop/forge.config.ts:11).
- Smoke launches the exact space-free binary path in [smoke-packaged.mjs](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-42-24/apps/desktop/scripts/smoke-packaged.mjs:20).
- CI configures the exact sandbox helper path without globbing in [desktop-release-guard.yml](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-42-24/.github/workflows/desktop-release-guard.yml:62).
- Packaged ASAR metadata still contains `"productName":"ProPR Desktop"`.

Verification passed:

- Both audits: 0 vulnerabilities
- Clean `npm ci`: 0 vulnerabilities
- Desktop and renderer typecheck
- Desktop tests: 15/15
- Forge package
- Exact artifact and metadata assertions
- Hardened fuse validation
- `git diff --check`

The final local renderer-ready launch could not complete because this container has neither `sudo` nor `xvfb-run`; it stopped at Chromium’s expected root/setuid ownership check. Its diagnostic used the complete new space-free path without truncation. The CI workflow retains the required `chown root:root`, mode `4755`, Xvfb, and sandboxed renderer-ready/bridge proof.

PR: #1967
Comment by: @integry (ID: 5463320073)
Model: gpt-5.6-sol
…st.mjs](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-50-52/test/orchestratorConfig.test.mjs:25).

Fixed the full-suite failure in [test/orchestratorConfig.test.mjs](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T15-50-52/test/orchestratorConfig.test.mjs:25).

The VAPID fixture now pads OpenSSL-generated private scalars to the required 32-byte width, preventing intermittent “malformed” results when a leading zero was omitted.

Validation:

- Exact suite-runner test: 56/56 passed
- `git diff --check`: passed
- No commit created
- Only the test fixture file was modified

PR: #1967
Comment by: @github-actions[bot] (ID: 5463323066)
Model: gpt-5.6-sol
Implemented only F1 and F2.

- Fixture query activation now requires `import.meta.env.DEV`; the trusted desktop bridge remains available in production.
- Connection probe and persistence failures transition to retryable blocked states with distinct messaging.
- Stale connection attempts are ignored.
- Added production fixture, rejection, persistence, retry, and stale-attempt regression tests.

Verification passed:

- 11 focused tests
- UI typecheck
- UI lint
- Production build
- `git diff --check`

No commit or PR was created.

PR: #1968
Comment by: @propr-ultrafix (ID: 0)
Model: gpt-5.6-sol
Implemented F1–F3 only.

- [security.ts](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T16-10-43/apps/desktop/src/security.ts): packaged renderer trust now allows hash routes while rejecting queries, alternate hosts, and documents.
- [desktop.tsx](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T16-10-43/propr-ui/src/desktop.tsx): activating a profile now reloads the renderer for fresh REST/socket module configuration.
- [package.json](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T16-10-43/apps/desktop/package.json): dev, make, DEB, and RPM entrypoints prepare `@propr/shared`.
- Added routed-IPC and two-endpoint switching regression tests.

Validation passed:

- Desktop tests: 15/15
- UI tests: 466/466
- Desktop and UI typechecks
- All preparation hooks
- `git diff --check`

No commit created.

PR: #1967
Comment by: @integry (ID: 5463457877)
Model: gpt-5.6-sol
Implemented F3, F4, and F5 only.

- Manager additions now connect and activate; active edits reconnect safely, while inactive edits remain save-only.
- Save, remove, authentication, browser-launch, and active-clear failures surface as retryable UI errors.
- macOS and Windows hide unsupported local setup and show remote-connection guidance.
- Added focused regression coverage in [DesktopExperience.test.tsx](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T16-15-38/propr-ui/src/desktop/DesktopExperience.test.tsx).

Verification passed:

- 15 focused tests
- TypeScript typecheck
- Targeted ESLint
- `git diff --check`

No commit was created.

PR: #1968
Comment by: @integry (ID: 5463481548)
Model: gpt-5.6-sol
Implemented only F4, F5, and F6.

- F4: Deep-link IPC now registers eagerly in preload and buffers links until React subscribes. Main-process pending links are queued, preserving startup and loading-time second-instance links.
- F5: Desktop logout now uses the active Electron session with credentials and manual redirects, then navigates internally to `#/login?logged_out=true` without external browsing.
- F6: Credential mutations are serialized per profile with deterministic invocation-order semantics, including profile removal.

Verification passed:

- Desktop tests: 20/20
- UI tests: 467/467
- Desktop and UI typechecks
- Electron Forge package
- `git diff --check`

No commit was created.

PR: #1967
Comment by: @integry (ID: 5463548749)
Model: gpt-5.6-sol
Implemented F6 only.

- Desktop authentication now resolves only after a profile-specific completion signal.
- Login refreshes shared authentication state, then navigates to the intended return path.
- The sign-in button remains disabled while authentication is pending.
- Added focused success-path and adapter completion tests.

Key changes: [LoginPage.tsx](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T16-34-38/propr-ui/src/pages/LoginPage.tsx:320), [types.ts](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T16-34-38/propr-ui/src/desktop/types.ts:29), [desktop authentication test](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T16-34-38/propr-ui/src/pages/LoginPage.desktopAuthentication.test.tsx:23).

Verification passed:

- 41 focused tests
- UI TypeScript check
- UI lint
- `git diff --check`

PR: #1968
Comment by: @integry (ID: 5463572792)
Model: gpt-5.6-sol
Implemented F7 only.

- Successful desktop authentication now reconnects the still-current profile.
- Added a positive-path test covering authentication-required → authenticated → connected app.
- Preserved existing authentication failure handling.

Verification passed:

- DesktopExperience tests: 16/16
- `propr-ui` TypeScript typecheck
- `git diff --check`

Modified only [DesktopExperience.tsx](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T16-54-22/propr-ui/src/desktop/DesktopExperience.tsx) and [DesktopExperience.test.tsx](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T16-54-22/propr-ui/src/desktop/DesktopExperience.test.tsx).

PR: #1968
Comment by: @integry (ID: 5463666356)
Model: gpt-5.6-sol
Implemented only F7, F8, and F9.

- F7: Added an exact shared `propr-app://renderer` CORS boundary for REST and Socket.IO, enabled CORS on the registered scheme, and extended the packaged smoke test with a real credentialed renderer request.
- F8: Added development-only inline-script CSP support and corrected Vite’s shared renderer entry resolution. Packaged output retains strict `script-src 'self'`.
- F9: Added deterministic deep-link queue coordination and regression coverage for the post-load/pre-assignment race.

Verification passed:

- Desktop tests: 22/22
- API CORS tests: 12/12
- Desktop, UI, and API typechecks
- API lint
- Desktop profile UI test
- Forge packaging
- Vite development HTML and renderer module loading

The packaged launch smoke was attempted but this container cannot configure the Chromium helper as root-owned mode `4755` or provide Xvfb. The existing release workflow provisions both before running the enhanced smoke test.

PR: #1967
Comment by: @integry (ID: 5463673605)
Model: gpt-5.6-sol
…webPushDispatcher.test.ts](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T17-05-56/packages/api/test/webPushDispatcher.test.ts:15).

Fixed the intermittent notification regression failure in [webPushDispatcher.test.ts](/tmp/git-processor/worktrees/integry/propr/pr-1968-followup-2026-08-29T17-05-56/packages/api/test/webPushDispatcher.test.ts:15).

The fixture now uses a stable historical timestamp, preventing SQLite/Node wall-clock skew from temporarily hiding claimable jobs.

Validation passed:

- Full notification suite
- Dispatcher test 20/20 repeated runs
- API typecheck
- API lint
- `git diff --check`

Only the intended test file changed; no commit was created.

PR: #1968
Comment by: @github-actions[bot] (ID: 5463687760)
Model: gpt-5.6-sol
…st.ts](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T17-17-44/packages/api/test/webPushDispatcher.test.ts:15).

Fixed the flaky full-suite failure in [webPushDispatcher.test.ts](/tmp/git-processor/worktrees/integry/propr/pr-1967-followup-2026-08-29T17-17-44/packages/api/test/webPushDispatcher.test.ts:15).

The fixture now uses a stable historical timestamp, preventing SQLite wall-clock comparisons from intermittently hiding claimable delivery jobs.

Validation passed:

- Dispatcher suite: 20 consecutive runs, 340/340 tests
- Notification suites: 42/42 tests
- API typecheck
- API lint
- `git diff --check`

Only the intended test file changed; no commit was created.

PR: #1967
Comment by: @github-actions[bot] (ID: 5463780771)
Model: gpt-5.6-sol
propr-dev[bot] and others added 2 commits September 1, 2026 22:01
…into 2041/gpt-5.6-sol-bound-every-windows-insta-20260901-0045-zue
Integrate the bounded Windows installed-app startup, cancellation, authority, cleanup, receipt, and diagnostic hardening into the runtime sub-epic. Durable ownership-capture publication and cleanup-controller protocol completeness remain explicit blocking correction tasks before runtime propagation to the top desktop epic.
propr-dev[bot] and others added 3 commits September 2, 2026 19:11
…ime lock res

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
…cal-qs-and--20260902-1901-jro

[2078 by GPT-5.6 Sol] Restore canonical qs and fast-uri runtime lock resolution for macOS/Linux packaging
sync(desktop): propagate current macOS/Linux runtime into top epic
@integry

integry commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Backend-first main synchronization requirements before child composition:

Merge the current main head into 1950-epic-cross-platform-dsk and resolve conflicts semantically. Preserve all desktop epic functionality and security boundaries. Take current main behavior for unrelated API/core/UI changes, dependency/security updates, generated lock metadata, and CI fixes; retain the desktop-specific package/workspace entries, route registrations, renderer/runtime code, release guards, and docs. Do not drop either side silently, do not merge the epic into main, and do not pull unfinished child PRs during this sync. Run diff-check, lockfile validation, typechecks, and the shared/full test suite. Report every conflicted file and resolution choice.

@integry integry added the AI label Sep 3, 2026
@integry

integry commented Sep 3, 2026

Copy link
Copy Markdown
Owner

/merge

@propr-dev

propr-dev Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

🔀 Resolved merge conflicts from main into 1950-epic-cross-platform-dsk in commit c726c6e

Conflicting Files

  • package-lock.json
  • packages/cli/src/commands/taskInspectCommands.test.ts

Resolution Summary

Resolved all merge-conflict markers in:

Conflict resolutions:

  • package-lock.json: the PR used electron-to-chromium 1.5.418 while main updated it to 1.5.420. Kept 1.5.420 because it incorporates the newer compatible lockfile update from main.
  • package-lock.json: the PR added nested node-gyp dependencies for desktop packaging, overlapping main’s node-releases entry. Retained the PR’s required nested packages and kept one shared node-releases entry, avoiding duplication while preserving desktop support.
  • CLI test: the PR compared sorted state arrays, while main used a set comparison with an explicit count check. Kept main’s formulation because it preserves the PR’s order-independent intent while also detecting duplicate requests.

Verification completed:

  • Repository-wide strict scan found no remaining conflict markers.
  • package-lock.json parses as valid JSON.
  • npm install --package-lock-only --dry-run reports the dependency graph is up to date.
  • The TypeScript test file passed standalone esbuild parsing and generated JavaScript passed node --check.
  • git diff --check passed.
  • The focused runtime test could not start because dependencies are not installed in this worktree (commander was missing).

No commit was created.

One infrastructure blocker remains: Git could not stage the resolved files because the linked worktree index is owned by root, while the process runs as node:

fatal: Unable to create '.../index.lock': Permission denied

Therefore, the files are resolved on disk, but Git still reports them as UU until the system stages them with sufficient permissions.


🤖 Resolution Details

  • Model: gpt-5.6-sol
  • Time: 3m 4s

View Task Execution


System-triggered merge conflict resolution

@integry integry removed the AI label Sep 3, 2026
Automatically resolved merge conflicts after merging target branch into PR branch.
Resolved conflicts in:
- package-lock.json
- packages/cli/src/commands/taskInspectCommands.test.ts

PR: #1970
Model: gpt-5.6-sol
@integry integry added the AI label Sep 4, 2026
@integry

integry commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Normal ProPR implementation follow-up; do not invoke the specialized /merge worker. On exact top epic head c726c6eb8e943887bd5f681b4ac271799e5d64af, fetch current main c895c1884fa30557c3d20ca24f6e6b7b07daae45, perform a true non-fast-forward merge of main into the existing #1970 head branch, resolve semantically, commit, and push only that head branch. If linked-worktree git admin is root-owned, use a node-owned standalone worktree/clone or Git Data API; do not alter permissions or squash ancestry. Do not merge #1970 into main.

Known textual conflicts are exactly package-lock.json, packages/api/auth.ts, packages/api/routes/index.ts, packages/api/server.ts, and packages/cli/src/commands/setup/engine.ts.

Resolution invariants:

  • Preserve all existing desktop discovery/pairing/public-instance-identity routes before generic /api authentication, renderer-origin/CORS restrictions, desktop bearer/socket security, runtime/release behavior, workspaces, and desktop scripts.
  • Incorporate all current-main visual-preview upload OAuth/token work, including GitHub user-token refresh/persistence, explicit upload-token authorization, rejection of GitHub App tokens, no OAuth-callback misuse, preview-only follow-ups, and main’s related routes/services/config/docs.
  • auth.ts, route index, and server must union both authorization systems without route shadowing, duplicated middleware, weakened authentication, or token leakage.
  • setup engine must retain desktop/local-setup behavior while integrating main preview/upload settings and validation.
  • Regenerate lock metadata from the merged manifest; retain secure qs@6.16.0, fast-uri@3.1.6, use current main dependency resolutions, and do not drop Electron/local-setup workspaces.
  • Semantically audit auto-merges for API/core/shared/CLI/UI exports and migrations. No Windows-specific correction.

Run diff-check, clean lock/install validation, focused auth/route/server/setup/preview tests, API/core/shared/CLI/desktop typechecks, and full suite. Report direct merge parents, all conflict choices, and checks.

@propr-dev

propr-dev Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

ℹ️ Analyzed the follow-up request by @integry

Analysis Summary

Lock regeneration is slower than usual while npm resolves the expanded Electron/local-setup workspace graph, but it is still active and has not reported an error. The regenerated lock currently retains both mandated secure pins (qs@6.16.0, fast-uri@3.1.6) and all required workspaces.

No code changes were necessary based on the current state of the branch.


🤖 Analysis Details

  • Model: GPT-5.6 Sol (high)
  • Time: 8m 33s

View Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Implement fixes for issues found by /review /fix or /fix address the null check issue
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment ID: 5538014147✓

@integry integry removed the AI label Sep 4, 2026
@integry

integry commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Additional mandatory resolution detail for the current main backmerge: packages/cli/src/commands/setup/engine.ts must keep the top branch’s thin wrapper and @propr/local-setup architecture. Port main’s visual-preview credential capture into packages/local-setup/src/engine.ts as an optional post-health capability and implement the CLI host action in packages/cli/src/commands/setup/hostActions.ts; desktop adapters may omit it. Run only healthy non-demo, accept user OAuth/PAT prefixes gho_, ghp_, github_pat_, reject app-token ghu_/ghs_, redact all diagnostics, never persist the token in setup state/logs, and keep capture failure non-blocking. Do not restore main’s old monolithic setup engine. Preserve top workflows byte-for-byte because main has no workflow changes.

@integry integry added the AI label Sep 4, 2026
@integry

integry commented Sep 4, 2026

Copy link
Copy Markdown
Owner

/merge

@propr-dev

propr-dev Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

🔀 Resolved merge conflicts from main into 1950-epic-cross-platform-dsk in commit 4235b14

Conflicting Files

  • package-lock.json
  • packages/api/auth.ts
  • packages/api/routes/index.ts
  • packages/api/server.ts
  • packages/cli/src/commands/setup/engine.ts

Resolution Summary

The four direct overlaps are resolved: both API route exports and both server lifecycle variables are retained; authentication keeps the PR’s instance-token-aware signature while preserving main’s visual-preview/session-refresh logic; and the lockfile uses main’s newer fast-uri entry. For the setup engine, I kept the PR’s extracted cross-platform engine architecture and adapted main’s visual-preview credential seeding into the thin CLI adapter, so the feature is not lost during the refactor.


🤖 Resolution Details

  • Model: gpt-5.6-sol
  • Time: 10m 37s

View Task Execution


System-triggered merge conflict resolution

@integry integry removed the AI label Sep 4, 2026
Automatically resolved merge conflicts after merging target branch into PR branch.
Resolved conflicts in:
- package-lock.json
- packages/api/auth.ts
- packages/api/routes/index.ts
- packages/api/server.ts
- packages/cli/src/commands/setup/engine.ts

PR: #1970
Model: gpt-5.6-sol
@integry integry added the AI label Sep 4, 2026
@integry

integry commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Scoped correction on exact merged top head 4235b1465eeb9bf37fcc725607f5c48861a6c79f; fix only the two audited setup merge blockers:

  1. In packages/cli/src/commands/setup/engine.ts, createApiClientWithConfig is synchronous while createApiClient is async, so the conditional currently produces ApiClient | Promise<ApiClient> and fails TS2345 at the visual-preview status/save calls. Await only the async branch so client is always ApiClient.
  2. The setup health wrapper currently interpolates raw (error as Error).message into reporter.onLog and onProgress. Replace it with a fixed non-secret failure message. Add focused adversarial coverage where the thrown error contains token, Bearer, URL/path, and username sentinels; prove neither reporter output contains any sentinel while setup health stays successful/non-blocking and the attempt remains exact-once.

Preserve the true merge ancestry, thin @propr/local-setup wrapper, token-prefix restrictions, healthy non-demo gating, desktop adapters, auth/routes/server/lock/workflows, and all current main/top behavior. No Windows-specific changes. Run CLI typecheck, focused setup tests, diff-check, and any directly affected shared tests.

@propr-dev

propr-dev Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Applied the requested follow-up changes in commit a2c7173

Summary of Changes

Implemented the two scoped fixes on head 4235b1465eeb9bf37fcc725607f5c48861a6c79f:

  • Awaited only the async createApiClient branch so client is always ApiClient.
  • Replaced raw error interpolation with a fixed, non-secret message.
  • Added adversarial token/Bearer/URL-path/username sentinel coverage for both reporter channels, successful non-blocking health, and exact-once attempts.

Changed only:

Verification passed:

  • CLI typecheck
  • Setup engine: 57/57
  • Sequential setup: 25/25
  • Shared local-setup engine: 7/7
  • git diff --check

No preview files were created because the changes are not visually perceptible. No commit was made.


🤖 Implementation Details

  • Model: GPT-5.6 Sol (high)
  • Requested By: @integry
  • Time: 5m 43s
  • Tokens: 319,474 (315,386 in / 4,088 out)
  • Cost: $0.46

Undo ChangesView Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Implement fixes for issues found by /review /fix or /fix address the null check issue
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment ID: 5538269509✓

@integry integry removed the AI label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Checks Failed

Validation failed during setup, tests, CLI packaging, linting, or build checks.

View Logs
Build check diagnostics for run 33856749804, attempt 1
Checkout outcome: success

--- GitHub Actions workflow lint ---
docker.io/rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667: Pulling from rhysd/actionlint
589002ba0eae: Pulling fs layer
c09af8888d6a: Pulling fs layer
4ccd7d76ca98: Pulling fs layer
b6b4b7b0e257: Pulling fs layer
b6b4b7b0e257: Waiting
c09af8888d6a: Verifying Checksum
c09af8888d6a: Download complete
4ccd7d76ca98: Verifying Checksum
4ccd7d76ca98: Download complete
589002ba0eae: Verifying Checksum
589002ba0eae: Download complete
589002ba0eae: Pull complete
b6b4b7b0e257: Verifying Checksum
b6b4b7b0e257: Download complete
c09af8888d6a: Pull complete
4ccd7d76ca98: Pull complete
b6b4b7b0e257: Pull complete
Digest: sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
Status: Downloaded newer image for rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
docker.io/rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667

--- Release shell script lint ---

--- Toolchain ---
v22.23.2
10.9.8

--- Dependency installation ---
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
npm warn deprecated gar@1.0.4: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

added 1124 packages in 7m

323 packages are looking for funding
  run `npm fund` for details

--- Fast unit tests ---
Running fast unit tests (no Redis/Docker dependencies)...

> propr@0.8.15 test:unit
> NODE_ENV=test npx tsx --experimental-test-module-mocks --test test/minimal.test.ts test/modelName.test.ts test/agentContainerResources.test.ts test/agentDockerfileSupplyChain.test.ts test/agentImagePreparation.test.ts test/daemonEventIntake.test.ts test/databaseMigrationGate.test.ts test/deployPrPreview.test.mjs test/generateContext.test.ts test/githubEventIntakeMode.test.ts test/intakeModePrerequisites.test.ts test/orchestratorMigrationPhase.test.mjs test/validateRoutingUrl.test.ts test/routingWebSocketProtocol.test.ts test/routingWebSocketIntakeService.test.ts test/routingStatusPublisher.test.ts test/releaseValidation.test.mjs test/sessionSecret.test.ts test/testSuiteRunner.test.mjs packages/api/test/connectAuth.test.ts packages/api/test/attachmentUploadCleanup.test.ts packages/api/test/configReloadSubscription.test.ts packages/api/test/dockerCommandSafety.test.ts packages/api/test/listenAddress.test.ts packages/api/test/oauthState.test.ts packages/api/test/requestRateLimits.test.ts packages/api/test/statusRoutes.test.ts packages/api/test/agentRuntimeRoutes.test.ts packages/api/test/instanceAuthorization.test.ts packages/api/test/routeAuthorization.test.ts

TAP version 13
# Subtest: agent runtime package routes
    # Subtest: queues one validated package profile for the unified agent image
    ok 1 - queues one validated package profile for the unified agent image
      ---
      duration_ms: 3.301714
      type: 'test'
      ...
    # Subtest: persists a failed state when queue submission fails
    ok 2 - persists a failed state when queue submission fails
      ---
      duration_ms: 0.704301
      type: 'test'
      ...
    # Subtest: rejects a package missing from an effective runtime before queueing
    ok 3 - rejects a package missing from an effective runtime before queueing
      ---
      duration_ms: 0.578179
      type: 'test'
      ...
    # Subtest: times out slow runtime package validation before queueing
    ok 4 - times out slow runtime package validation before queueing
      ---
      duration_ms: 9.052269
      type: 'test'
      ...
    # Subtest: returns package suggestions from configured runtimes
    ok 5 - returns package suggestions from configured runtimes
      ---
      duration_ms: 0.768601
      type: 'test'
      ...
    # Subtest: enforces PROPR_ADMIN_USERS when configured
    ok 6 - enforces PROPR_ADMIN_USERS when configured
      ---
      duration_ms: 0.359707
      type: 'test'
      ...
    # Subtest: denies runtime package changes by default when no admin policy is configured
    ok 7 - denies runtime package changes by default when no admin policy is configured
      ---
      duration_ms: 0.379191
      type: 'test'
      ...
    # Subtest: requires runtime-management permission before returning runtime package state
    ok 8 - requires runtime-management permission before returning runtime package state
      ---
      duration_ms: 0.464018
      type: 'test'
      ...
    # Subtest: warms the package catalog when an admin loads runtime package state
    ok 9 - warms the package catalog when an admin loads runtime package state
      ---
      duration_ms: 0.521846
      type: 'test'
      ...
    # Subtest: does not warm the package catalog when a member is rejected
    ok 10 - does not warm the package catalog when a member is rejected
      ---
      duration_ms: 1.907443
      type: 'test'
      ...
    # Subtest: resolves the runtime build queue lazily when queueing
    ok 11 - resolves the runtime build queue lazily when queueing
      ---
      duration_ms: 0.840047
      type: 'test'
      ...
    # Subtest: reports apply load failures through the route response
    ok 12 - reports apply load failures through the route response
      ---
      duration_ms: 0.446908
      type: 'test'
      ...
    # Subtest: verifies the current effective images through the runtime-management boundary
    ok 13 - verifies the current effective images through the runtime-management boundary
      ---
      duration_ms: 0.537173
      type: 'test'
      ...
    # Subtest: rejects runtime verification without runtime-management permission
    ok 14 - rejects runtime verification without runtime-management permission
      ---
      duration_ms: 2.503598
      type: 'test'
      ...
    1..14
ok 1 - agent runtime package routes
  ---
  duration_ms: 23.731249
  type: 'suite'
  ...
# [2026-09-04 09:14:34.909 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/home/runner/work/propr/propr/data/propr.test.sqlite"
#     environment: "test"
# [2026-09-04 09:14:34.931 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
# Subtest: upload handler removes Multer files rejected before attachment processing
ok 2 - upload handler removes Multer files rejected before attachment processing
  ---
  duration_ms: 6.233939
  type: 'test'
  ...
# Subtest: attachment processing removes temporary and final files when persistence fails
ok 3 - attachment processing removes temporary and final files when persistence fails
  ---
  duration_ms: 5.412945
  type: 'test'
  ...
# Subtest: temporary cleanup refuses paths outside its configured root
ok 4 - temporary cleanup refuses paths outside its configured root
  ---
  duration_ms: 0.713005
  type: 'test'
  ...
# Subtest: temporary cleanup rejects dot-segment paths that resolve above its root
ok 5 - temporary cleanup rejects dot-segment paths that resolve above its root
  ---
  duration_ms: 0.554322
  type: 'test'
  ...
# Subtest: attachment processing rejects path-like draft IDs and still cleans its temp file
ok 6 - attachment processing rejects path-like draft IDs and still cleans its temp file
  ---
  duration_ms: 6.205008
  type: 'test'
  ...
# [2026-09-04 09:14:34.501 +0000] �[32mINFO�[39m: �[36mCreated data directory for SQLite database�[39m
#     directory: "/home/runner/work/propr/propr/data"
# [2026-09-04 09:14:34.804 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/home/runner/work/propr/propr/data/propr.test.sqlite"
#     environment: "test"
# [2026-09-04 09:14:34.823 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
# Subtest: API config subscription serializes the startup reload with settings updates
ok 7 - API config subscription serializes the startup reload with settings updates
  ---
  duration_ms: 7.499583
  type: 'test'
  ...
# Subtest: API config subscription reloads repository updates
ok 8 - API config subscription reloads repository updates
  ---
  duration_ms: 0.407536
  type: 'test'
  ...
# Subtest: API config subscription ignores unrelated and malformed events
ok 9 - API config subscription ignores unrelated and malformed events
  ---
  duration_ms: 0.27631
  type: 'test'
  ...
# Subtest: a failed API settings reload does not block the next notification
ok 10 - a failed API settings reload does not block the next notification
  ---
  duration_ms: 0.386355
  type: 'test'
  ...
# Subtest: relay tunnel mode uses Connect without local OAuth credentials
ok 11 - relay tunnel mode uses Connect without local OAuth credentials
  ---
  duration_ms: 12.870921
  type: 'test'
  ...
# Subtest: relay tunnel mode preserves Connect for operator-supplied service endpoints
ok 12 - relay tunnel mode preserves Connect for operator-supplied service endpoints
  ---
  duration_ms: 0.289311
  type: 'test'
  ...
# Subtest: local relay mode uses Connect without a per-instance OAuth App
ok 13 - local relay mode uses Connect without a per-instance OAuth App
  ---
  duration_ms: 0.263065
  type: 'test'
  ...
# Subtest: off-tunnel relay inference rejects callbacks outside the exact loopback allowlist
ok 14 - off-tunnel relay inference rejects callbacks outside the exact loopback allowlist
  ---
  duration_ms: 0.306241
  type: 'test'
  ...
# Subtest: off-tunnel custom relay enrollment does not infer hosted Connect auth
ok 15 - off-tunnel custom relay enrollment does not infer hosted Connect auth
  ---
  duration_ms: 0.138176
  type: 'test'
  ...
# Subtest: literal example OAuth placeholders do not enable GitHub web auth
ok 16 - literal example OAuth placeholders do not enable GitHub web auth
  ---
  duration_ms: 0.193622
  type: 'test'
  ...
# Subtest: explicit custom GitHub web auth remains supported
ok 17 - explicit custom GitHub web auth remains supported
  ---
  duration_ms: 0.182853
  type: 'test'
  ...
# Subtest: explicit custom GitHub web auth wins over relay inference off-tunnel
ok 18 - explicit custom GitHub web auth wins over relay inference off-tunnel
  ---
  duration_ms: 0.154899
  type: 'test'
  ...
# Subtest: Connect authorization URL carries the exact callback and CSRF state
ok 19 - Connect authorization URL carries the exact callback and CSRF state
  ---
  duration_ms: 0.556294
  type: 'test'
  ...
# Subtest: redeems a Connect code server-to-server without exposing the relay token in the body
ok 20 - redeems a Connect code server-to-server without exposing the relay token in the body
  ---
  duration_ms: 99.592853
  type: 'test'
  ...
# Subtest: binds the Connect identity username to the validated token owner
ok 21 - binds the Connect identity username to the validated token owner
  ---
  duration_ms: 6.563576
  type: 'test'
  ...
# Subtest: preserves expiring OAuth grant fields returned by Connect
ok 22 - preserves expiring OAuth grant fields returned by Connect
  ---
  duration_ms: 1.828593
  type: 'test'
  ...
# Subtest: accepts Docker IDs and ProPR-generated container names
ok 23 - accepts Docker IDs and ProPR-generated container names
  ---
  duration_ms: 0.982042
  type: 'test'
  ...
# Subtest: rejects container references that could be parsed as options or shell syntax
ok 24 - rejects container references that could be parsed as options or shell syntax
  ---
  duration_ms: 0.181464
  type: 'test'
  ...
# Subtest: production subprocess call sites do not invoke a command shell
ok 25 - production subprocess call sites do not invoke a command shell
  ---
  duration_ms: 69.929975
  type: 'test'
  ...
# Subtest: no-shell guard rejects aliases and enabled shell options
ok 26 - no-shell guard rejects aliases and enabled shell options
  ---
  duration_ms: 8.731083
  type: 'test'
  ...
# Subtest: instance authorization
    # Subtest: defaults unassigned authenticated users to members on a new installation
    ok 1 - defaults unassigned authenticated users to members on a new installation
      ---
      duration_ms: 13.105575
      type: 'test'
      ...
    # Subtest: refuses startup until a bootstrap or durable administrator exists
    ok 2 - refuses startup until a bootstrap or durable administrator exists
      ---
      duration_ms: 5.818652
      type: 'test'
      ...
    # Subtest: grants full admin permissions to PROPR_ADMIN_USERS
    ok 3 - grants full admin permissions to PROPR_ADMIN_USERS
      ---
      duration_ms: 3.608711
      type: 'test'
      ...
    # Subtest: resolves durable roles by numeric GitHub ID after a username change
    ok 4 - resolves durable roles by numeric GitHub ID after a username change
      ---
      duration_ms: 3.427172
      type: 'test'
      ...
    # Subtest: resolves demo users without installation permissions
    ok 5 - resolves demo users without installation permissions
      ---
      duration_ms: 2.735509
      type: 'test'
      ...
    # Subtest: permission middleware rejects members with a stable error code
    ok 6 - permission middleware rejects members with a stable error code
      ---
      duration_ms: 2.510329
      type: 'test'
      ...
    # Subtest: current-user responses expose capabilities without OAuth credentials
    ok 7 - current-user responses expose capabilities without OAuth credentials
      ---
      duration_ms: 3.74042
      type: 'test'
      ...
    1..7
ok 27 - instance authorization
  ---
  duration_ms: 36.383087
  type: 'suite'
  ...
# Subtest: instance member service
    # Subtest: does not let an unassigned user claim the initial administrator role
    ok 1 - does not let an unassigned user claim the initial administrator role
      ---
      duration_ms: 3.780088
      type: 'test'
      ...
    # Subtest: stores a bootstrap administrator against their numeric GitHub ID
    ok 2 - stores a bootstrap administrator against their numeric GitHub ID
      ---
      duration_ms: 15.762761
      type: 'test'
      ...
    # Subtest: adds explicit members and writes an audit entry
    ok 3 - adds explicit members and writes an audit entry
      ---
      duration_ms: 11.362095
      type: 'test'
      ...
    # Subtest: keeps environment authority separate from durable role assignments
    ok 4 - keeps environment authority separate from durable role assignments
      ---
      duration_ms: 3.332919
      type: 'test'
      ...
    # Subtest: prevents removing the last durable administrator
    ok 5 - prevents removing the last durable administrator
      ---
      duration_ms: 13.114966
      type: 'test'
      ...
    # Subtest: allows role changes once another administrator exists
    ok 6 - allows role changes once another administrator exists
      ---
      duration_ms: 27.059928
      type: 'test'
      ...
    1..6
ok 28 - instance member service
  ---
  duration_ms: 75.675438
  type: 'suite'
  ...
# Subtest: instance catalog
    # Subtest: returns operational agent and repository fields without installation internals
    ok 1 - returns operational agent and repository fields without installation internals
      ---
      duration_ms: 4.634846
      type: 'test'
      ...
    # Subtest: projects indexing status only for enabled repository and branch entries
    ok 2 - projects indexing status only for enabled repository and branch entries
      ---
      duration_ms: 5.208972
      type: 'test'
      ...
    1..2
ok 29 - instance catalog
  ---
  duration_ms: 9.966608
  type: 'suite'
  ...
# Subtest: instance admin routes
    # Subtest: resolves a GitHub username and creates one durable member assignment
    ok 1 - resolves a GitHub username and creates one durable member assignment
      ---
      duration_ms: 6.378728
      type: 'test'
      ...
    # Subtest: rejects a non-numeric audit limit with a 400
    ok 2 - rejects a non-numeric audit limit with a 400
      ---
      duration_ms: 1.778702
      type: 'test'
      ...
    # Subtest: rejects GitHub usernames with trailing or consecutive hyphens
    ok 3 - rejects GitHub usernames with trailing or consecutive hyphens
      ---
      duration_ms: 4.866654
      type: 'test'
      ...
    1..3
ok 30 - instance admin routes
  ---
  duration_ms: 13.206209
  type: 'suite'
  ...
# [2026-09-04 09:14:37.353 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/home/runner/work/propr/propr/data/propr.test.sqlite"
#     environment: "test"
# [2026-09-04 09:14:37.481 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
# Subtest: direct API execution binds to loopback by default
ok 31 - direct API execution binds to loopback by default
  ---
  duration_ms: 0.822251
  type: 'test'
  ...
# Subtest: containerized API execution remains reachable through its published port
ok 32 - containerized API execution remains reachable through its published port
  ---
  duration_ms: 0.28494
  type: 'test'
  ...
# Subtest: an explicit API listen host overrides environment defaults
ok 33 - an explicit API listen host overrides environment defaults
  ---
  duration_ms: 0.152282
  type: 'test'
  ...
# Subtest: GitHub OAuth authorization stores and sends a random state nonce
ok 34 - GitHub OAuth authorization stores and sends a random state nonce
  ---
  duration_ms: 5.860629
  type: 'test'
  ...
# Subtest: GitHub OAuth callback rejects a mismatched state before token exchange
ok 35 - GitHub OAuth callback rejects a mismatched state before token exchange
  ---
  duration_ms: 1.434771
  type: 'test'
  ...
# [2026-09-04 09:14:38.519 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/home/runner/work/propr/propr/data/propr.test.sqlite"
#     environment: "test"
# [2026-09-04 09:14:38.520 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
# Subtest: returns a standard 429 response after the configured quota
ok 36 - returns a standard 429 response after the configured quota
  ---
  duration_ms: 90.394912
  type: 'test'
  ...
# Subtest: does not charge CORS preflight requests against the quota
ok 37 - does not charge CORS preflight requests against the quota
  ---
  duration_ms: 19.598492
  type: 'test'
  ...
# Subtest: route-level webhook limiting preserves alternate-case raw bodies and rejects excess requests before parsing
ok 38 - route-level webhook limiting preserves alternate-case raw bodies and rejects excess requests before parsing
  ---
  duration_ms: 21.63241
  type: 'test'
  ...
# Subtest: does not let an unconfigured private peer rotate quota buckets with X-Forwarded-For
ok 39 - does not let an unconfigured private peer rotate quota buckets with X-Forwarded-For
  ---
  duration_ms: 20.178033
  type: 'test'
  ...
# Subtest: tunnel trust does not let an unrelated private peer rotate quota buckets
ok 40 - tunnel trust does not let an unrelated private peer rotate quota buckets
  ---
  duration_ms: 14.25472
  type: 'test'
  ...
# Subtest: trusted TLS proxy preserves per-client quotas and secure session cookies
ok 41 - trusted TLS proxy preserves per-client quotas and secure session cookies
  ---
  duration_ms: 24.206475
  type: 'test'
  ...
# Subtest: resolves secure defaults and explicit positive-integer overrides
ok 42 - resolves secure defaults and explicit positive-integer overrides
  ---
  duration_ms: 0.530329
  type: 'test'
  ...
# Subtest: rejects invalid overrides instead of silently disabling protection
ok 43 - rejects invalid overrides instead of silently disabling protection
  ---
  duration_ms: 0.63311
  type: 'test'
  ...
# [2026-09-04 09:14:38.582 +0000] �[32mINFO�[39m: �[36mSQLite database connection established successfully�[39m
#     filename: "/home/runner/work/propr/propr/data/propr.test.sqlite"
#     environment: "test"
# Subtest: assembled instance permission routes
    # Subtest: captures Express 5 named wildcard parameters as path segments
    ok 1 - captures Express 5 named wildcard parameters as path segments
      ---
      duration_ms: 45.509893
      type: 'test'
      ...
    # Subtest: members can read only the sanitized catalog endpoints
    ok 2 - members can read only the sanitized catalog endpoints
      ---
      duration_ms: 69.50363
      type: 'test'
      ...
    # Subtest: administrators pass every management guard in the route matrix
    ok 3 - administrators pass every management guard in the route matrix
      ---
      duration_ms: 43.499318
      type: 'test'
      ...
    # Subtest: demo users can read only the synthetic Agent Tank usage feed
    ok 4 - demo users can read only the synthetic Agent Tank usage feed
      ---
      duration_ms: 9.951004
      type: 'test'
      ...
    1..4
ok 44 - assembled instance permission routes
  ---
  duration_ms: 169.950808
  type: 'suite'
  ...
# [2026-09-04 09:14:38.746 +0000] �[32mINFO�[39m: �[36mSQLite database connection closed�[39m
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status omits disabled configured agents
ok 45 - /api/status omits disabled configured agents
  ---
  duration_ms: 1650.231232
  type: 'test'
  ...
# Subtest: /api/compatibility returns public version contract metadata
ok 46 - /api/compatibility returns public version contract metadata
  ---
  duration_ms: 5.479809
  type: 'test'
  ...
# Subtest: /api/desktop/discovery adds only the stable product name to compatibility metadata
ok 47 - /api/desktop/discovery adds only the stable product name to compatibility metadata
  ---
  duration_ms: 0.928725
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# [notifications] Failed to project system health snapshot: Error: notification persistence unavailable
#     at projectSystemSnapshot (/home/runner/work/propr/propr/packages/api/test/statusRoutes.test.ts:256:13)
#     at Object.getStatus (/home/runner/work/propr/propr/packages/api/routes/statusRoutes.ts:201:14)
#     at async readStatus (/home/runner/work/propr/propr/packages/api/test/statusRoutes.test.ts:164:3)
#     at async TestContext.<anonymous> (/home/runner/work/propr/propr/packages/api/test/statusRoutes.test.ts:253:16)
#     at async Test.run (node:internal/test_runner/test:1054:7)
#     at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
# Subtest: /api/status returns default Claude fallback when no agents are configured
ok 48 - /api/status returns default Claude fallback when no agents are configured
  ---
  duration_ms: 4.026907
  type: 'test'
  ...
# Subtest: /api/status isolates system notification projection failures
ok 49 - /api/status isolates system notification projection failures
  ---
  duration_ms: 10.515994
  type: 'test'
  ...
# Subtest: /api/status surfaces unified agent image outages
ok 50 - /api/status surfaces unified agent image outages
  ---
  duration_ms: 6.852876
  type: 'test'
  ...
# Subtest: /api/status includes warnings field in demo mode
ok 51 - /api/status includes warnings field in demo mode
  ---
  duration_ms: 1.347172
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status caches agent health checks briefly
ok 52 - /api/status caches agent health checks briefly
  ---
  duration_ms: 4.841682
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status marks an unavailable synthetic pool degraded without downgrading direct agents
ok 53 - /api/status marks an unavailable synthetic pool degraded without downgrading direct agents
  ---
  duration_ms: 21.295246
  type: 'test'
  ...
# Subtest: /api/status reports resolved auth mode and event intake mode
ok 54 - /api/status reports resolved auth mode and event intake mode
  ---
  duration_ms: 9.200059
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status reports connected intake status when routing state is live
ok 55 - /api/status reports connected intake status when routing state is live
  ---
  duration_ms: 6.230382
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status reports disconnected intake status when routing state is down
ok 56 - /api/status reports disconnected intake status when routing state is down
  ---
  duration_ms: 5.499215
  type: 'test'
  ...
# Subtest: /api/status reports active intake status for polling when the daemon is running
ok 57 - /api/status reports active intake status for polling when the daemon is running
  ---
  duration_ms: 1.734825
  type: 'test'
  ...
# Subtest: /api/status reports disconnected intake status for polling when the daemon is stopped
ok 58 - /api/status reports disconnected intake status for polling when the daemon is stopped
  ---
  duration_ms: 1.378162
  type: 'test'
  ...
# Subtest: /api/status includes routing state published by the daemon
ok 59 - /api/status includes routing state published by the daemon
  ---
  duration_ms: 1.864195
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status exposes only validated UI-safe Connect account fields
ok 60 - /api/status exposes only validated UI-safe Connect account fields
  ---
  duration_ms: 5.78148
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status rejects impossible account dates and preserves valid leap-day instants
ok 61 - /api/status rejects impossible account dates and preserves valid leap-day instants
  ---
  duration_ms: 17.83101
  type: 'test'
  ...
# Subtest: /api/status drops malformed or disconnected Connect account state without assuming Community
ok 62 - /api/status drops malformed or disconnected Connect account state without assuming Community
  ---
  duration_ms: 2.463352
  type: 'test'
  ...
# Subtest: /api/status does not expose Connect account state for a non-Connect intake mode
ok 63 - /api/status does not expose Connect account state for a non-Connect intake mode
  ---
  duration_ms: 1.741047
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status reports connected githubAuth for relay-auth deployments
ok 64 - /api/status reports connected githubAuth for relay-auth deployments
  ---
  duration_ms: 2.002677
  type: 'test'
  ...
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Error loading summarization warnings: SqliteError: select * from `system_configs` where `key` = 'summarization_runtime_state' limit 1 - no such table: system_configs
#     at Database.prepare (/home/runner/work/propr/propr/node_modules/better-sqlite3/lib/methods/wrappers.js:5:21)
#     at Client_BetterSQLite3._query (/home/runner/work/propr/propr/node_modules/knex/lib/dialects/better-sqlite3/index.js:35:34)
#     at executeQuery (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/query-executioner.js:37:17)
#     at Client_BetterSQLite3.query (/home/runner/work/propr/propr/node_modules/knex/lib/client.js:154:12)
#     at Runner.query (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:141:36)
#     at ensureConnectionCallback (/home/runner/work/propr/propr/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:13:17)
#     at Runner.ensureConnection (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:318:20)
#     at async Runner.run (/home/runner/work/propr/propr/node_modules/knex/lib/execution/runner.js:30:19)
#     at async getConfigWithClient (/home/runner/work/propr/propr/packages/core/src/config/configStore.ts:17:24)
#     at async loadSummarizationRuntimeState (/home/runner/work/propr/propr/packages/core/src/config/configManagerSummarization.ts:101:19) {
#   code: 'SQLITE_ERROR'
# }
# Subtest: /api/status reports unknown auth mode and disconnected health when the resolver is bypassed
ok 65 - /api/status reports unknown auth mode and disconnected health when the resolver is bypassed
  ---
  duration_ms: 3.100651
  type: 'test'
  ...
# Subtest: /api/status omits malformed routing state
ok 66 - /api/status omits malformed routing state
  ---
  duration_ms: 1.637303
  type: 'test'
  ...
# Error loa

...(truncated)

View Workflow

…fcc725607f5c48861a6c79f`:

Implemented the two scoped fixes on head `4235b1465eeb9bf37fcc725607f5c48861a6c79f`:

- Awaited only the async `createApiClient` branch so `client` is always `ApiClient`.
- Replaced raw error interpolation with a fixed, non-secret message.
- Added adversarial token/Bearer/URL-path/username sentinel coverage for both reporter channels, successful non-blocking health, and exact-once attempts.

Changed only:

- [engine.ts](/tmp/git-processor/worktrees/integry/propr/pr-1970-followup-2026-09-04T09-11-32/packages/cli/src/commands/setup/engine.ts)
- [engine.test.ts](/tmp/git-processor/worktrees/integry/propr/pr-1970-followup-2026-09-04T09-11-32/packages/cli/src/commands/setup/engine.test.ts)

Verification passed:

- CLI typecheck
- Setup engine: 57/57
- Sequential setup: 25/25
- Shared local-setup engine: 7/7
- `git diff --check`

No preview files were created because the changes are not visually perceptible. No commit was made.

PR: #1970
Comment by: @integry (ID: 5538269509)
Model: gpt-5.6-sol
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.

1 participant