mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 19:28:46 +01:00
merge: reconcile published native prerequisite and current master
Preserve canonical startup ownership, scoped evidence, current Storybook IDs, and the Codex form controls while carrying Claude effort and immutable source bindings. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
commit
48ffca9438
415 files changed
+22501
-15340
No files matched your search
@@ -701,6 +701,18 @@ this non-secret binding for this namespace; Slack bot installation does not use
|
||||
PKCE. Removal and manual recovery invalidate outstanding attempts under the same
|
||||
credential-mutation lease used by configuration.
|
||||
|
||||
### Slack manager workspace grants
|
||||
|
||||
`chat_slack_manager_grants` stores a personal workspace authorization, scoped by
|
||||
company, Paperclip user, Slack user, workspace and manager app. Access/refresh
|
||||
credentials are references to user-scoped vault entries, never plaintext columns.
|
||||
Revision fencing protects reauthorization from concurrent revocation. Per-method
|
||||
rate-limit deadlines retain Slack's Retry-After across setup retries.
|
||||
|
||||
`chat_slack_registrations.manager_grant_id` is optional, with a composite company
|
||||
foreign key. Existing registrations remain customer owned with a null reference.
|
||||
Deleting one endpoint removes its registration credentials and attempts, but does
|
||||
not revoke grants used by other bots. See [Slack setup](connections/slack-setup.md).
|
||||
|
||||
## Transaction-aware delivery work signals
|
||||
|
||||
|
||||
@@ -35,6 +35,28 @@ New workflow versions merged into master then receive runner access without a
|
||||
separate SHA allowlist update. Dependabot leaves this first-party reference on
|
||||
master.
|
||||
|
||||
Runner selection calls `ci-routing.yml@master` on the dedicated
|
||||
`paperclip-ci-routing-x64` AWS Fleet. The `paperclip-ci-routing` runner group
|
||||
admits only `paperclipai/paperclip/.github/workflows/ci-routing.yml@refs/heads/master`
|
||||
and repository ID `1170821064`. GitHub evaluates the canonical repository, author, and sender checks before
|
||||
allocating reserved capacity. The validated admission snapshot (`AWS_CI_ROUTING_USER_IDS_SOURCE` and
|
||||
`AWS_CI_ROUTING_USER_IDS`) must match `AWS_CI_TRUSTED_USER_IDS`. Refresh it through
|
||||
the runner-group configuration helper when the roster changes. Missing, stale,
|
||||
or malformed settings keep hosted routing available without evaluating JSON
|
||||
in the job's placement expression. Unapproved PRs use hosted metadata routing;
|
||||
approved manual canaries on master can use the reserved pool. The routing
|
||||
workflow reads GitHub metadata without checking out or executing PR code. Its author, sender, rerun actor,
|
||||
repository, head, and merge validation still decide whether tests can use AWS.
|
||||
Unapproved test workloads continue to use GitHub-hosted runners.
|
||||
|
||||
The routing Fleet has two warm On-Demand runners and a four-runner ceiling.
|
||||
Test fleets cannot consume its runner slots. Hosted test queues therefore do
|
||||
not block AWS runner selection. A manual dispatch of `ci-routing.yml` on master
|
||||
checks placement without launching the test matrix; its non-PR event returns
|
||||
the hosted test-runner output. Configure and verify the group and Fleet before
|
||||
merging this caller. To roll back, restore the hosted gate and retain the routing
|
||||
workflow authorization until assigned jobs finish.
|
||||
|
||||
Keep the `.github/**` rule in `.github/CODEOWNERS` and the active master ruleset's
|
||||
code-owner review requirement enabled. This covers the caller, the trusted
|
||||
workflow, and CODEOWNERS itself. Existing administrator pull-request bypasses
|
||||
@@ -102,6 +124,20 @@ API responses and MCP transports keep their existing compression behavior.
|
||||
|
||||
The board UI Storybook keeps stories and Storybook config under `ui/storybook/` so component review files stay out of the app source routes.
|
||||
|
||||
Stories are grouped in `ui/storybook/stories/<feature-area>/` and the sidebar follows
|
||||
the feature map's sections and feature names. Shared fixtures live in
|
||||
`ui/storybook/support/`. Keep each suite's explicit meta `id` and catalog `stableId`
|
||||
when changing titles or locations so existing review links remain valid.
|
||||
|
||||
Start from the downstream [Storybook feature index](../maps/storybook-map/INDEX.md)
|
||||
to find existing stories by capability. Its [contract](../maps/storybook-map/README.md)
|
||||
separates production subjects, prototype implementations, simulated data, and
|
||||
source-review status. Use `maintain-storybook` to reconcile stories/fixtures with
|
||||
the feature map, and `review-storybook` to exercise them with existing tools.
|
||||
Run `node scripts/storybook-catalog.mjs` after affected story or review-source
|
||||
changes; review drift before updating fingerprints, then regenerate with `--write`.
|
||||
The feature map remains an upstream input and needs no Storybook-specific fields.
|
||||
|
||||
**Chat & Comments → Human identity** covers other-human names and avatars on
|
||||
left-aligned task messages alongside agents; only the viewer’s own messages are blue/right-aligned. Its review guide explains the data flow; the task journey uses representative
|
||||
fixtures in the production shell and thread with an agent and two humans, both
|
||||
@@ -2239,3 +2275,12 @@ Chromium. The test starts its own loopback Vite server and mocks API responses;
|
||||
it needs no running Paperclip instance or provider credentials. The same spec lives
|
||||
in the default `test:e2e` discovery tree, so the existing Chrome CI shards run it
|
||||
on pull requests.
|
||||
|
||||
### Slack provisioning paths
|
||||
|
||||
Self-hosted development continues to use independent Slack app setup. Managed
|
||||
Slack installation is a disabled-by-default Cloud feature that also requires the
|
||||
companion broker profile and Slack approval. Do not add manager client credentials
|
||||
to a local `.env` or an open-source deployment. See
|
||||
[Slack setup and Cloud qualification](connections/slack-setup.md) for the gates,
|
||||
recovery behavior, and production-component stories.
|
||||
@@ -77,4 +77,4 @@ Task setup defaults to personal identity when supported and the requesting agent
|
||||
|
||||
Service and native-authority tests cover discovery, current identity, company boundaries, cross-run deduplication, additive grants and installs, permission denial, resolution atomicity, restart delivery and stale assignment. `tests/e2e/in-feed-native/playwright.config.ts` starts source `test-drive` instances with fresh data directories and a deterministic fake Codex provider plus MCP server. It exercises the real native runner and gateway; it is fixture proof, not live Notion or GitHub proof. Run with `pnpm exec playwright test -c tests/e2e/in-feed-native/playwright.config.ts`.
|
||||
|
||||
Offline Storybook examples live in `ui/storybook/stories/in-feed-connections.stories.tsx`. Build with `pnpm --filter @paperclipai/ui build-storybook`, then run `pnpm exec playwright test -c tests/storybook-visual/in-feed-connections.config.ts`. The suite checks every independently addressable story in both themes, catches play-function failures, and saves screenshots. Live provider acceptance additionally requires a model credential and a test workspace/account; do not describe fixture results or local-trusted testing as authenticated/cloud acceptance.
|
||||
Offline Storybook examples live in `ui/storybook/stories/connection-setup/in-feed-connections.stories.tsx`. Build with `pnpm --filter @paperclipai/ui build-storybook`, then run `pnpm exec playwright test -c tests/storybook-visual/in-feed-connections.config.ts`. The suite checks every independently addressable story in both themes, catches play-function failures, and saves screenshots. Live provider acceptance additionally requires a model credential and a test workspace/account; do not describe fixture results or local-trusted testing as authenticated/cloud acceptance.
|
||||
@@ -0,0 +1,162 @@
|
||||
# Slack app ownership and setup
|
||||
|
||||
Slack has one chat runtime and two provisioning paths. A saved connection's
|
||||
`slackSetupMethod` selects provisioning; it does not change tools, scopes,
|
||||
conversation routing, people permissions, or channel access.
|
||||
|
||||
| Method | App creation and installation | Default |
|
||||
| --- | --- | --- |
|
||||
| `managed` | A personal Slack manager grant creates a child app; managed installation supplies its bot token. Slack consent/admin approval remains a fallback. | New drafts on qualified Cloud deployments only |
|
||||
| `automatic` | A temporary app configuration access token creates a customer-owned app; the user approves its OAuth installation. | New self-hosted drafts and Cloud without managed availability |
|
||||
| `manual` | User creates an app from the canonical manifest and enters credentials. | Legacy drafts with no saved method |
|
||||
| `existing` | User supplies credentials for an existing app. | Explicit selection |
|
||||
|
||||
Existing drafts and active bots retain their method. Enabling managed setup never
|
||||
adopts existing apps. Choose agent offers **Use your own app** under **Advanced**, below Slash command,
|
||||
when the instance supports managed setup and creation has not started. The own-app flow retains **Create manually** and **Use an existing
|
||||
app** under Advanced. After creation dispatch, a managed draft cannot switch paths.
|
||||
|
||||
Managed setup has two visible stops: Choose agent and Connect. **Continue** starts
|
||||
manager authorization or installation in the saved workspace automatically. Multiple
|
||||
workspaces still require a selection. Recovery actions remain explicit; opening
|
||||
a failed or uncertain registration never retries creation automatically.
|
||||
Creation, installation, message waiting, and success use the same production
|
||||
components and server evidence as the own-app flow. A click or OAuth return does
|
||||
not constitute successful configuration.
|
||||
|
||||
## Cloud deployment prerequisites
|
||||
|
||||
Managed setup is disabled by default. Qualification requires all of:
|
||||
|
||||
- The instance chat-connector rollout gate and connection-management permission.
|
||||
- Verified Cloud runtime identity, connector broker signing/sealing configuration,
|
||||
and valid independently configured public board and webhook HTTPS origins.
|
||||
- `PAPERCLIP_SLACK_MANAGED_SETUP_ENABLED=true` on the approved tenant deployment.
|
||||
- The companion Cloud broker deployment with the explicitly enabled `slack.manager`
|
||||
profile, approved Slack manager app, token rotation, and its client secret in
|
||||
the broker's secret store. No manager client secret belongs in the tenant.
|
||||
|
||||
The broker must advertise its manager app identity as well as the enabled profile.
|
||||
Previously saved grants from a different manager app are not reused. A broker
|
||||
without this capability leaves managed setup unavailable. Do not enable the tenant
|
||||
gate until real Slack qualification has passed; fixture coverage does not prove
|
||||
Marketplace eligibility or a workspace's approval policy.
|
||||
|
||||
Self-hosted instances do not need a Paperclip account, broker enrollment, manager
|
||||
credentials, or hosted-service calls. They continue using the own-app flow.
|
||||
|
||||
## Personal workspace authorization
|
||||
|
||||
Manager grants belong to a company **and one Paperclip user**, and bind a verified
|
||||
Slack user, workspace, and manager app. Another company member must authorize their
|
||||
own account, even for the same workspace. Access and rotating refresh tokens are
|
||||
user-scoped vault entries. Refreshes serialize across connections, persist the new
|
||||
refresh token, and require fresh authorization after an ambiguous exchange.
|
||||
|
||||
Revoking a grant requests provider revocation, removes its local credentials, invalidates pending manager
|
||||
authorization, and prevents future provisioning with it. The local activity records whether provider revocation succeeded. Provider errors never restore local access. It does not uninstall
|
||||
apps or disable already-installed bots. Removing a bot deletes endpoint-specific
|
||||
secrets and pending setup attempts; a reusable personal manager grant survives.
|
||||
Provider-side app removal remains explicit through the saved Slack management URL.
|
||||
|
||||
## Recovery
|
||||
|
||||
- A dispatched creation with an unknown result is **uncertain**. Never automatically
|
||||
create again. The user must inspect Slack and explicitly confirm that no app was
|
||||
created before a new request identity is accepted.
|
||||
- Denied or pending installation retains the app. Resume with the same grant or
|
||||
complete the child app's state-bound OAuth approval; the installer must match the
|
||||
grant's Slack identity before personal linking.
|
||||
- Returned bot credentials are vaulted before inventory or runtime configuration.
|
||||
Retry connecting reuses those credentials after network or inventory failures.
|
||||
Rejected or under-scoped bot credentials instead reinstall the saved app; they
|
||||
never trigger another app creation.
|
||||
- Manifest updates finish before managed installation. Changes requiring updated
|
||||
permissions therefore pass through installation again before activation.
|
||||
- Expired or revoked manager grants require reconnection. Losing managed
|
||||
availability pauses setup; it never changes the saved ownership method.
|
||||
- Slack rate limits are grouped by manager/workspace/method. Provider `Retry-After`
|
||||
is persisted across matching grants in the company, survives restarts, and blocks
|
||||
early retries. Other tenant instances must observe Slack's limits independently;
|
||||
no background loop retries app creation.
|
||||
|
||||
All OAuth attempts bind company, actor/session, endpoint, registration revision,
|
||||
and configured origins, expire after ten minutes, and are claimed once before
|
||||
exchange. HTTP diagnostics redact manager tokens, refresh tokens, codes, and sealed
|
||||
handoffs. Local activity records contain only IDs and safe outcome codes. This adds
|
||||
no first-party telemetry.
|
||||
|
||||
## Code and verification
|
||||
|
||||
Server provisioning lives in `server/src/services/connectors/slack/setup/`;
|
||||
`chat-slack-registration.ts` remains the compatibility facade. Shared completion
|
||||
owns credential binding, personal linking, welcome messages, and verification.
|
||||
Removal cleanup stays independently callable. Slack wizard components and stage
|
||||
selection live in `ui/src/pages/apps/chat/slack/`.
|
||||
|
||||
Production Storybook journeys: **Connections / Slack / Managed setup** and
|
||||
**Connections / Slack / Automatic setup** (the persisted own-app automatic path).
|
||||
Server integration cases cover personal grants, duplicate requests, uncertain
|
||||
creation, approval fallback, refresh, revocation, removal, saved-credential recovery,
|
||||
rate limits, and secret canaries. Browser cases are in
|
||||
`tests/e2e/chat-adapters-ui-providers.spec.ts`; companion broker tests cover manager
|
||||
user OAuth and the authenticated tenant handoff.
|
||||
|
||||
Before enabling a deployment, create two test agents in the authorized workspace.
|
||||
The second must reuse the personal grant without another configuration token or
|
||||
manager authorization. Verify avatars, identity linking, signed inbound events,
|
||||
and same-thread replies. Record real approval behavior separately from fixtures.
|
||||
|
||||
### Managed setup during broker outages
|
||||
|
||||
Cloud deployments configured for managed Slack keep the managed default when the broker profile is temporarily unavailable. New drafts remain on **Connect** and offer **Retry**. **Use your own app** remains available under **Advanced** on Choose agent before creation. Discovery loading or failure never selects the configuration-token page. Self-hosted instances without managed configuration still use their independent own-app flow; saved draft methods do not change automatically. Provisioning continues to require current broker availability.
|
||||
|
||||
### Local managed-bot qualification
|
||||
|
||||
Maintainers with an approved Slack manager app can exercise the real managed
|
||||
journey from an authenticated local test drive exposed through HTTPS (including
|
||||
TryCloudflare). This development transport talks directly to Slack and reuses
|
||||
the production manager-grant vault, state claims, provisioning, completion, and
|
||||
runtime. It does not exercise the Cloud broker's sealed handoff; qualify that
|
||||
separately on staging afterward.
|
||||
|
||||
Set `NODE_ENV=development`, `PAPERCLIP_SLACK_MANAGED_SETUP_ENABLED=true`, and
|
||||
`PAPERCLIP_SLACK_MANAGER_DEVELOPMENT_CONFIG` to an absolute path outside the
|
||||
checkout containing a mode-0600 JSON file with `appId`, `clientId`, and
|
||||
`clientSecret`. Use only an authorized qualification manager app. No credentials
|
||||
are shipped with Paperclip. Production ignores this development configuration,
|
||||
and Cloud runtime identity continues to select the Cloud broker.
|
||||
|
||||
Configure the local instance for authenticated public access, with its public
|
||||
URL and chat webhook URL pointing to the HTTPS tunnel. Add the exact public URL
|
||||
plus `/api/chat-slack/managed/oauth/callback` to the manager app's OAuth redirect
|
||||
URLs, preserving any existing redirects. Start a **new** Slack setup: saved
|
||||
own-app drafts retain their selected method. Authorize the manager app normally;
|
||||
do not copy user grants from another instance. The second bot should reuse the
|
||||
same local user's vaulted grant. A changed tunnel requires updating public
|
||||
origins and the manager redirect before starting fresh authorization.
|
||||
|
||||
Remove the temporary redirect when retiring the test drive and securely remove
|
||||
its development credential file. Removing a bot does not revoke a manager grant
|
||||
used by other bots.
|
||||
|
||||
### Test messages from Settings
|
||||
|
||||
**Send me a test message** sends a DM to the signed-in connection manager,
|
||||
using their linked identity in this workspace. If this bot is not linked yet,
|
||||
Paperclip can reuse that user's verified manager grant or another bot's linked
|
||||
identity in the same company and workspace. Otherwise, the user selects their
|
||||
Slack account and receives a private connection invitation in Slack. They must
|
||||
open that invitation, sign in, and confirm before Paperclip links the account and
|
||||
sends the test DM. The account picker loads further workspace pages on request. Existing revoked or conflicting identity links are not overwritten.
|
||||
Direct messages must be enabled, and the user must be an active company operator.
|
||||
|
||||
The action records a durable request before sending. Repeating the same request
|
||||
returns its saved result; an uncertain delivery is never automatically resent.
|
||||
**Open Slack configuration** opens the saved app's OAuth & Permissions page.
|
||||
Legacy connections without an app ID open Slack's app list instead.
|
||||
|
||||
An explicit managed reconnect reinstalls the saved app and verifies the replacement
|
||||
bot credentials. Its request ID is saved before dispatch, so a duplicate completed
|
||||
request does not reinstall again. Credential-configuration recovery still resumes
|
||||
the saved token after a downstream failure. No reconnect creates another Slack app.
|
||||
@@ -2,10 +2,90 @@
|
||||
|
||||
Updated 2026-10-12.
|
||||
|
||||
## Production readiness: owned startup correction
|
||||
|
||||
The human requests production readiness; preparation and normal sequential
|
||||
merges remain authorized. Production deployment and provisioning-default
|
||||
promotion remain separate actions. Nothing in this checkpoint is merged or
|
||||
deployed, and the stack is not production-ready.
|
||||
|
||||
Runtime prerequisite behavior is `ce23716503a2c9158b5a7ab74ab61571ff4ee7a3`
|
||||
on `codex/runner-native-platform-prerequisites`, in
|
||||
[#16028](https://github.com/paperclipai/paperclip/pull/16028). Final qualification
|
||||
reproduced close returning before credential preparation drained, followed by
|
||||
registration and launch. Both direct close and real driver cancellation failed
|
||||
on literal `5a9ce11`. The initial shared repair from Claude commit `463ebb` is
|
||||
reused, with independently identified duplicate-admission, shutdown-readiness and
|
||||
resume ordering corrections. All five source findings are closed in matching
|
||||
source review. Absolute cleanup deadlines, primary cancellation errors,
|
||||
unauthenticated-process protection and existing agents' runner choices remain.
|
||||
|
||||
The existing suites pass 32 credential-free controls across three files; both
|
||||
canonical runner TypeScript no-emit checks pass. No new suite, local Rust/Docker
|
||||
build, provider call or credential-content read was used. Actual daemon
|
||||
readiness/recovery controls remain **hosted-CI required**: local worktrees lack
|
||||
the existing fake-Codex/fake-harness executables. The failed local native attempt
|
||||
never reached the readiness assertion and is not qualification. Receipts are
|
||||
`/private/tmp/pr2-463ebb-owned-startup-review-closure-receipt.json` and
|
||||
`/private/tmp/ci-final-owned-startup-five-gap-closure-review.json`.
|
||||
|
||||
Normal automatic merge is disabled and the prerequisite is draft while this
|
||||
correction receives fresh full CI, package qualification and 5/5 review.
|
||||
Earlier green checks at `5a9ce11` remain historical. Actual code-owner approval
|
||||
is still required; no protection is bypassed. The updated runs/adapters map pair
|
||||
records source-only scope, bringing the prerequisite review to 63 files after the required Storybook
|
||||
catalog review below.
|
||||
|
||||
Codex remains `1a0ca66242121e39d88455aa2b52a07acc4a07d9` in
|
||||
[#15683](https://github.com/paperclipai/paperclip/pull/15683), based on the previous
|
||||
prerequisite. The Claude owner retains its branches, cached guided-setup fix,
|
||||
verification and separate $50 allowance. Coordinate reconciliation of the common
|
||||
repair before rewriting those branches; don't duplicate it in a leaf slice.
|
||||
|
||||
The idle [local preview](http://127.0.0.1:3125/COD/agents/all) still serves literal
|
||||
behavior `fe1ecf1c34`, recovery ready and zero active runs. Its four saved
|
||||
legacy/native configurations and two historical native records remain preserved;
|
||||
it has not been refreshed to this new runtime. Final local/managed acceptance
|
||||
must use the tested source, independent file checks and follow-up continuity.
|
||||
|
||||
The prepared private execution checklist reuses existing evals, installation,
|
||||
Cloud composition and campaign paths. Required holds are final source/image/
|
||||
migrator, the actual verified-master private distribution, pinned QA onboarding,
|
||||
warm/cold signup, production baseline and previous-image compatibility. Production
|
||||
Fleet Admin sign-in is pending. Current paid holds remain $248.179254104 of $250;
|
||||
unknown/cleanup holds stay reserved, and the unstarted managed envelope is $2.50.
|
||||
No new image, paid resource, rollout or default promotion was dispatched.
|
||||
|
||||
Master reconciliation uses `4b958ecbd8f33a7782fe6f29ec825f80f636b833`.
|
||||
The new contribution rules are satisfied: 157 added comment annotations were
|
||||
removed from 35 files, with identical executable JavaScript/TypeScript emission,
|
||||
parsed workflow values, 77 action pins and shell commands. No code file crosses
|
||||
from below 1,000 lines to above that limit. Final focused checks pass 248 tests
|
||||
(107 workflow/package, 54 runner, 42 server, 45 E2E support). Both runner no-emit
|
||||
checks and the canonical server/E2E no-emit checks pass with isolated matching
|
||||
workspace dependencies. Only JavaScript/TypeScript preparation ran locally;
|
||||
root preview links and data stayed unchanged. The earlier linked-source failures
|
||||
remain recorded and are superseded only by the new canonical check receipt.
|
||||
|
||||
The existing Storybook catalog has 21 source-review fingerprint updates because
|
||||
its declared runs/adapters map input changed. All affected stories, subjects,
|
||||
wrappers and fixtures remain byte-identical to master. Review classifications
|
||||
stay unchanged. The catalog check passes 223 files/2,210 stories; this is
|
||||
structural/source evidence, not visual or live proof. Source receipts are
|
||||
`/private/tmp/pr2-9f59-comments-cleanup-receipt.json`,
|
||||
`/private/tmp/pr2-storybook-owned-final-receipt.json` and
|
||||
`/private/tmp/pr2-frozen-canonical-noemit-receipt.json`.
|
||||
|
||||
Next action: publish this reviewed prerequisite correction, require fresh hosted
|
||||
gates, reconcile Codex and Claude with its actual source, then resume the existing
|
||||
remote package/immutable preview and dedicated staging qualification. Merge ready
|
||||
slices normally in the agreed order; actual production readiness requires the
|
||||
private distribution and rollback/forward-recovery evidence afterward.
|
||||
|
||||
## CI fixture, network policy and map synchronization checkpoint
|
||||
|
||||
Runtime prerequisite source is `5a9ce11c49db31440863d633426ebe30bcc850ca`
|
||||
with 60 changed files. The hosted static check on literal Codex source `eee0534`
|
||||
with 59 changed files. The hosted static check on literal Codex source `eee0534`
|
||||
passed 133 cases and failed one: its isolated assembly fixture omitted the new
|
||||
target JSON, so the helper failed before its existing Cursor-identity assertion.
|
||||
The fixture now copies that exact inert JSON; all negative assertions remain.
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# Chat channel callback and delivery boundaries, batch four
|
||||
|
||||
Base: 4b766b872993045a2e787404f0475503683e5ded. Batch three (#15995, #15996, #15999, #16001, #16002)
|
||||
is merged. The service starts at 26,461 lines / 1,046,711 bytes.
|
||||
This batch may create up to ten stacked PRs. Merging the new batch is separate work.
|
||||
|
||||
| Order / boundary | Destination | Approx. moved / net lines | Contract and state | Risks and existing verification |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1. Slack callback verification | `slack/callback-verification.ts` | 250 / 230 | Pure signature/workspace/URL inspection plus signed URL verification; explicit vault lookup, URL getter, scheduling and registration callbacks | Preserve signing-secret-only setup, original request, TLS/proxy evidence and workspace checks. Signed verification and callback health cases before/after. |
|
||||
| 2. Discord Gateway events | `discord/gateway-events.ts` | 200 / 185 | Runtime fence and lease-owner predicates, endpoint lookup and lifecycle callback; original per-runtime event queue and sequence | Preserve stale-owner fencing, event order, transient guild recovery and terminal revocation. Gateway lifecycle cases before/after. |
|
||||
| 3. Discord root threads | `discord/root-threads.ts` | 500 / 460 | Credential lease, current principal authority, runtime, message admission and conversation drain callbacks | Preserve uncertain thread creation, restart reconciliation, no duplicate starter and pause/credential serialization. Root-thread public-service cases. |
|
||||
| 4. Receipt reactions | `receipt-reactions.ts` and Slack error classifier beside Slack messages | 545 / 500 | Durable reaction claim/transport/settlement with runtime and credential fences; no scheduling owner moves | Preserve retries, legacy GitHub receipts, terminal-removal supersession and same-attempt settlement. Receipt recovery cases before/after. |
|
||||
| 5. Inbound reactions | `reactions.ts` | 800 / 740 | Conversation lookup/locks, reaction admission and deferred replay together; current principal/runtime callbacks | Preserve exact event dedupe, completed generation links, bounded replay age and no task wakeup. Reaction race/restart/authorization cases. |
|
||||
| 6. Inbound attachments | `inbound-attachments.ts` | 600 / 550 | Existing storage and issue service, retained source authorization and live options; return same attachment results | Preserve size limits, source authority around I/O, omissions and text delivery. Provider attachment/restart/stale-authority cases. |
|
||||
| 7. Outbound attachments | `outbound-attachments.ts`; provider Markdown wrappers beside provider messages | 245 / 220 | Metadata validation and bounded integrity-checked hydration; existing storage object. Keep public hydration export compatible | Preserve stream cleanup, deadlines, byte/digest checks and retry classification. Hydration and publication attachment cases. |
|
||||
| 8. Provider effects | `provider-effects.ts` | 950 / 850 | Durable reply claim, authorization, transport and settlement; endpoint/runtime/credential/principal callbacks | Preserve uncertain-delivery quarantine, credential fence and transaction ordering. Native callback, task-control and reply recovery cases. Put Telegram-only authority under `telegram/` if its contract is narrow. |
|
||||
| 9. Conversation and activity reads | `activity.ts` | 540 / 520 | Endpoint lookup and read-only Teams conflict projection; return existing API models | Preserve company/endpoint joins, mixed-source cursor ties, replay eligibility and read-only GETs. Activity, file receipt projection and conversation-state cases. |
|
||||
| 10. Setup probes | `setup-probes.ts` | 280 / 250 | Credential lease, current identity/principal authority, provider fetch, endpoint projection and live activation hook | Preserve real-message requirement, generation and linked-user activation. Setup-test, reconnect and authorization cases. |
|
||||
|
||||
Each slice must earn its place after reading its complete path and callers.
|
||||
Reassess before implementation; stop short of ten if the remaining contracts are
|
||||
not cohesive. Keep provider-specific code in channel folders and common durable
|
||||
workflows in the shared chat-channels directory.
|
||||
|
||||
Receiver lease ownership stays shared: the existing Discord-named owner is also
|
||||
used by Photon. Shared lifecycle/application admission, queue-drain ownership,
|
||||
worker scheduling, and the largest action/message handlers remain in the service.
|
||||
Do not hide their dependencies in a mutable context object. Preserve live option
|
||||
hooks, runtime-map identity, partial-failure cleanup, and initialization order.
|
||||
|
||||
Run relevant existing public-service tests before and after each mechanical move.
|
||||
Compare moved declarations and remaining statements with normalized syntax, then
|
||||
run server types, module boundaries and whitespace checks. Finish local verification and a fresh
|
||||
5/5 review before opening the next draft PR. GitHub runner-selection jobs remained
|
||||
queued without steps for over 25 minutes in this batch. To continue the authorized
|
||||
stack, publish drafts in review order while tracking CI as pending; CI remains a
|
||||
merge gate. Run cumulative repository gates at handoff.
|
||||
Retain failures and skipped/unrun coverage even when an isolated retry passes.
|
||||
Use fixture-backed assembled service/database tests; do not claim live provider
|
||||
execution. Remap LOC/bytes and the remaining orchestration after the batch.
|
||||
|
||||
## Slice 1: Slack callback verification
|
||||
|
||||
- Service: 26,461 lines / 1,046,711 bytes → 26,201 lines / 1,035,260 bytes.
|
||||
- Destination: 299 lines / 13,038 bytes. Eight declarations move without body
|
||||
changes. Three existing setup types move unchanged into `runtime-types.ts`.
|
||||
- The verification factory initializes after Slack registration. It receives the
|
||||
same registration object, credential resolver, live URL getter and scheduler.
|
||||
Signature/workspace/URL helpers remain callable by shared webhook orchestration.
|
||||
- Nine public-service cases passed before and after on the updated master base.
|
||||
Server typecheck, module boundaries, whitespace and normalized syntax parity
|
||||
passed. Coverage includes signed URL verification, account notification,
|
||||
workspace rejection, callback surfaces, TLS termination and Cloud host evidence.
|
||||
- Next: Discord Gateway event sequencing and health transitions. Keep shared
|
||||
receiver lease ownership and runtime-map lifetime in the service.
|
||||
|
||||
## Batch outcome
|
||||
|
||||
All ten candidates produced cohesive boundaries. Shared receiver ownership, queue
|
||||
management and worker scheduling remain in the service. The only intentional
|
||||
control-wiring change is deferred access to `stageProviderEffect` from identity
|
||||
link construction; typecheck and integration tests caught the initial early read.
|
||||
|
||||
| Slice | Service lines after | Primary module lines | Before/after cases |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| 1. Slack signature, workspace and callback url verification | 26,233 | 300 | 9 |
|
||||
| 2. Discord gateway event sequencing and endpoint health transitions | 26,029 | 253 | 7 |
|
||||
| 3. Discord root-thread admission, provider creation and durable recovery | 25,527 | 570 | 4 |
|
||||
| 4. Durable receipt reaction claims, transport, retries and settlement | 24,975 | 586 | 7 |
|
||||
| 5. Inbound reaction conversation lookup, admission and deferred replay | 24,160 | 891 | 21 |
|
||||
| 6. Inbound attachment authorization, bounded ingestion, registration and omissions | 23,565 | 674 | 39 |
|
||||
| 7. Outbound attachment metadata validation and bounded integrity-checked hydration | 23,298 | 294 | 22 |
|
||||
| 8. Durable provider reply staging, authorization, transport and recovery | 22,331 | 957 | 24 |
|
||||
| 9. Conversation summaries and paginated activity projections | 21,741 | 616 | 16 |
|
||||
| 10. Setup message detection and credential-fenced round-trip qualification | 21,460 | 353 | 7 |
|
||||
|
||||
After rebasing on master `8e7b5db822`, the service shrank from
|
||||
**26,493 lines / 1,048,769 bytes** to **21,460 lines /
|
||||
862,284 bytes** (5,033 fewer lines, about 19%). Normalized syntax comparison
|
||||
checks all 69 moved declarations/types and every remaining original statement.
|
||||
Server types, targeted tests, module boundaries and whitespace checks are the
|
||||
per-slice gates. Cumulative repository gates and remote reviews are recorded in
|
||||
the PR descriptions as they complete.
|
||||
|
||||
Orchestration measurement: the service function has 150 nested functions
|
||||
(19,399 lines) and 67 state/wiring statements (459 lines), versus 191 functions
|
||||
(23,829 lines) and 54 statements (425 lines) at the start. Imports take 400 lines.
|
||||
The remaining large paths are `processMessage` (2,166), `handleAction` (1,074),
|
||||
`configureWithCredentialLease` (868), `processSelectedPublication` (729),
|
||||
`handleModalSubmit` (708), `handleWebhook` (685), and lifecycle processing (657).
|
||||
|
||||
A future pass should inspect publication admission/transport/settlement as one
|
||||
workflow, then inbound delivery authorization and drain ownership. Those cuts
|
||||
need explicit ownership contracts; avoid separating individual checks from their
|
||||
transactions merely to reduce the remaining line count.
|
||||
|
||||
The rebase preserves the merged managed Slack setup flow, including its shared
|
||||
`isProvisionedSlackSetup` predicate in the extracted callback verification
|
||||
module. A fresh syntax audit compares all moved declarations and retained
|
||||
statement ordering with this updated master.
|
||||
@@ -0,0 +1,539 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"policy": "Each mutation changes one actual production guard or outcome. Only the selected case runs. Every changed source is restored to its exact SHA-256 in finally. Complete unmutated owner and sibling controls run separately.",
|
||||
"controls": [
|
||||
{
|
||||
"id": "api-rejection-eviction",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/api/client.ts",
|
||||
"sourceSha256": "1e1b3f03e3269a5943f55d294f1c7aa9f5c3eca569858d9fdc7c5d976de88bba",
|
||||
"case": "tenant-session recovery preserves ApiError handling for an unrelated 401",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "Error: promise rejected \"ApiError: unauthorized { \u2026(2) }\" instead of resolving\n at Assertion.__VITEST_RESOLVES__ (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/index.C4tKZ0yW.js:2434:33)\n at Assertion.propertyGetter (file://<workspace>/node_modules/.pnpm/chai@6.3.0/node_modules/chai/index.js:1607:27)\n at Reflect.get (<anonymous>)\n at Object.proxyGetter [as get] (file:///Users/dotta/.codex/worktrees/tes"
|
||||
},
|
||||
{
|
||||
"id": "api-all-abort-eviction",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/api/client.ts",
|
||||
"sourceSha256": "1e1b3f03e3269a5943f55d294f1c7aa9f5c3eca569858d9fdc7c5d976de88bba",
|
||||
"case": "per-caller abort semantics aborts the shared fetch after all callers cancel and permits a fresh request",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected \"vi.fn()\" to be called 2 times, but got 1 times\n at <workspace>/ui/src/api/client.test.ts:210:23\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
},
|
||||
{
|
||||
"id": "ticker-one-interval",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/hooks/useSecondTick.ts",
|
||||
"sourceSha256": "fd51875adf5f30295d847df58af19f75dcbb59c810b4f02919427cbc6ea4d3b3",
|
||||
"case": "useSecondTick shares a single timer across multiple active subscribers and stops when idle",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected 2 to be 1 // Object.is equality\n at <workspace>/ui/src/hooks/useSecondTick.test.tsx:26:32\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:1628:35\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules"
|
||||
},
|
||||
{
|
||||
"id": "ticker-delivery",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/hooks/useSecondTick.ts",
|
||||
"sourceSha256": "fd51875adf5f30295d847df58af19f75dcbb59c810b4f02919427cbc6ea4d3b3",
|
||||
"case": "useSecondTick shares a single timer across multiple active subscribers and stops when idle",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected '0' to be '1' // Object.is equality\n at <workspace>/ui/src/hooks/useSecondTick.test.tsx:28:37\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:1628:35\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_mod"
|
||||
},
|
||||
{
|
||||
"id": "ticker-idle-cleanup",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/hooks/useSecondTick.ts",
|
||||
"sourceSha256": "fd51875adf5f30295d847df58af19f75dcbb59c810b4f02919427cbc6ea4d3b3",
|
||||
"case": "useSecondTick shares a single timer across multiple active subscribers and stops when idle",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected 1 to be +0 // Object.is equality\n at <workspace>/ui/src/hooks/useSecondTick.test.tsx:37:32\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:1628:35\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_module"
|
||||
},
|
||||
{
|
||||
"id": "ticker-inactive-peer",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/hooks/useSecondTick.ts",
|
||||
"sourceSha256": "fd51875adf5f30295d847df58af19f75dcbb59c810b4f02919427cbc6ea4d3b3",
|
||||
"case": "useSecondTick does not subscribe or start a timer when inactive",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected '1' to be '0' // Object.is equality\n at <workspace>/ui/src/hooks/useSecondTick.test.tsx:48:37\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:1628:35\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_mod"
|
||||
},
|
||||
{
|
||||
"id": "ui-bound-caption",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/components/AgentConfigForm.tsx",
|
||||
"sourceSha256": "bf999102f39bfc762747ce5d598e1e6ec2f926ac5fb28de55fa1baf5493f28b1",
|
||||
"case": "AgentConfigForm environment selector reports the account-binding claim upward exactly once when the session authenticates",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected 'Sign in to OpenAISign inAuthenticated\u2026' to contain 'Agent bound to the signed-in account'\n at <workspace>/ui/src/components/AgentConfigForm.render.test.tsx:1773:35\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
},
|
||||
{
|
||||
"id": "ui-onboarding-saved-login",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/components/AgentConfigForm.tsx",
|
||||
"sourceSha256": "bf999102f39bfc762747ce5d598e1e6ec2f926ac5fb28de55fa1baf5493f28b1",
|
||||
"case": "OnboardingWizard restore-gate (stale localStorage across accounts) the adapter step login panel (cheap auth signal, no adapter test) renders no 'Use saved login' control",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected 'Step 2 of 3Ada Connect a modelPapercl\u2026' not to contain 'Use saved login'\n at <workspace>/ui/src/components/OnboardingWizard.test.tsx:2931:45\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
},
|
||||
{
|
||||
"id": "ui-agent-footer",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/components/IssueThreadInteractionCard.tsx",
|
||||
"sourceSha256": "fb9beb27481258354942003e6a5c319a23257ef07f4ce811eb9ccbd605e0a585",
|
||||
"case": "IssueThreadInteractionCard tool-action card marks agent resolution with an audit chip in the resolved footer",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string\n at Proxy.<anonymous> (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/index.C4tKZ0yW.js:2077:15)\n at Proxy.<anonymous> (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_j"
|
||||
},
|
||||
{
|
||||
"id": "ui-markdown-anchor",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "ui/src/components/MarkdownBody.tsx",
|
||||
"sourceSha256": "003b7da23b5ebd0e8cd4de91e0d1dafe697f6602d4d99551b04d0abad699d193",
|
||||
"case": "MarkdownBody opens external links in a new tab with safe rel attributes",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected '<div class=\"paperclip-markdown prose \u2026' to contain '<a href=\"https://example.com/docs\"'\n at <workspace>/ui/src/components/MarkdownBody.test.tsx:587:18\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:1628:35\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_"
|
||||
},
|
||||
{
|
||||
"id": "server-cancelled-reopen",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "server/src/routes/issues.ts",
|
||||
"sourceSha256": "641b3d9cb5e744671527f16129dd78518376dca31616b845ec6b8da99d636d8c",
|
||||
"case": "issue comment reopen routes rejects bare agent reopen requests on cancelled issues before writing a comment",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected 201 to be 409 // Object.is equality\n at <workspace>/server/src/__tests__/issue-comment-reopen-routes.test.ts:1040:24\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
},
|
||||
{
|
||||
"id": "wiki-genuine-run-id",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "packages/plugins/plugin-llm-wiki/src/wiki/core.ts",
|
||||
"sourceSha256": "35d8543f67ab80479c624f527d0b94fbb0f3b309d40b1276a07518872212ea06",
|
||||
"case": "LLM Wiki plugin scaffold starts query sessions, records run ids, and forwards session events to plugin streams",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected [ \u2026(4) ] to deeply equal [ \u2026(4) ]\n at <workspace>/packages/plugins/plugin-llm-wiki/tests/plugin.spec.ts:3610:44\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
},
|
||||
{
|
||||
"id": "wiki-positive-source-writes",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "packages/plugins/plugin-llm-wiki/src/wiki/core.ts",
|
||||
"sourceSha256": "35d8543f67ab80479c624f527d0b94fbb0f3b309d40b1276a07518872212ea06",
|
||||
"case": "LLM Wiki plugin scaffold keeps default-space files at the root and isolates managed spaces under slug prefixes",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected [] to have a length of 2 but got +0\n at Proxy.<anonymous> (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/index.C4tKZ0yW.js:2147:20)\n at Proxy.<anonymous> (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/index.C4tKZ0yW.js:1944:14)\n at Proxy."
|
||||
},
|
||||
{
|
||||
"id": "wiki-positive-page-writes",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "packages/plugins/plugin-llm-wiki/src/wiki/core.ts",
|
||||
"sourceSha256": "35d8543f67ab80479c624f527d0b94fbb0f3b309d40b1276a07518872212ea06",
|
||||
"case": "LLM Wiki plugin scaffold keeps default-space files at the root and isolates managed spaces under slug prefixes",
|
||||
"expected": "one intended assertion failure",
|
||||
"actualFailedCases": 1,
|
||||
"intendedAssertionFailed": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected [ { \u2026(2) }, { \u2026(2) } ] to have a length of 4 but got 2\n at Proxy.<anonymous> (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/index.C4tKZ0yW.js:2147:20)\n at Proxy.<anonymous> (file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/index.C4tKZ0yW.js:194"
|
||||
},
|
||||
{
|
||||
"id": "aws-create-must-wait-before",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "server/src/services/secrets.ts",
|
||||
"sourceSha256": "2b7cac8d903802ea47c71033fa2d5dffb4d01a9ccde80837445235b0208b8e97",
|
||||
"case": "secretService serializes an aws_secrets_manager secret create against a concurrent account-home mutation lock holder",
|
||||
"expected": "old weak control passes",
|
||||
"actual": "passed",
|
||||
"intendedResult": true,
|
||||
"sourceRestored": true
|
||||
},
|
||||
{
|
||||
"id": "aws-rotate-must-wait-before",
|
||||
"codeHead": "dfdc39b3a71c74c40e267010c6d8428af523bb65",
|
||||
"owner": "server/src/services/secrets.ts",
|
||||
"sourceSha256": "2b7cac8d903802ea47c71033fa2d5dffb4d01a9ccde80837445235b0208b8e97",
|
||||
"case": "secretService serializes an aws_secrets_manager secret rotate against a concurrent account-home mutation lock holder",
|
||||
"expected": "old weak control passes",
|
||||
"actual": "passed",
|
||||
"intendedResult": true,
|
||||
"sourceRestored": true
|
||||
},
|
||||
{
|
||||
"id": "aws-create-must-wait-after",
|
||||
"codeHead": "445d568ca4e903fc998819cae31d421403514684",
|
||||
"owner": "server/src/services/secrets.ts",
|
||||
"sourceSha256": "2b7cac8d903802ea47c71033fa2d5dffb4d01a9ccde80837445235b0208b8e97",
|
||||
"case": "secretService serializes an aws_secrets_manager secret create against a concurrent account-home mutation lock holder",
|
||||
"expected": "repaired control fails on provider entry before lock release",
|
||||
"actual": "failed",
|
||||
"intendedResult": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected [ 'cleanup-enter', \u2026(1) ] to deeply equal [ 'cleanup-enter' ]\n at <workspace>/server/src/__tests__/secrets-service.test.ts:1013:22\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
},
|
||||
{
|
||||
"id": "aws-rotate-must-wait-after",
|
||||
"codeHead": "445d568ca4e903fc998819cae31d421403514684",
|
||||
"owner": "server/src/services/secrets.ts",
|
||||
"sourceSha256": "2b7cac8d903802ea47c71033fa2d5dffb4d01a9ccde80837445235b0208b8e97",
|
||||
"case": "secretService serializes an aws_secrets_manager secret rotate against a concurrent account-home mutation lock holder",
|
||||
"expected": "repaired control fails on provider entry before lock release",
|
||||
"actual": "failed",
|
||||
"intendedResult": true,
|
||||
"sourceRestored": true,
|
||||
"failure": "AssertionError: expected [ 'cleanup-enter', \u2026(1) ] to deeply equal [ 'cleanup-enter' ]\n at <workspace>/server/src/__tests__/secrets-service.test.ts:1081:22\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at file://<workspace>/node_modules/.pnpm/vitest@5.0.3_@opentelemetry+api@1.9.1_@types+node@24.13.3_jsdom@30.0.1_@noble+hashes@2.4.0__v_wr5mxfuu6kgge6st623q4v5egm/node_modules/vitest/dist/chunks/run.BTlFXlnv.js:2783:20"
|
||||
}
|
||||
],
|
||||
"unmutatedControls": [
|
||||
{
|
||||
"batch": "round4 owners and keepers",
|
||||
"files": 58,
|
||||
"passed": 1455,
|
||||
"failed": 0,
|
||||
"pending": 0
|
||||
},
|
||||
{
|
||||
"batch": "tool-access owners and state keepers",
|
||||
"passed": 623,
|
||||
"failed": 0,
|
||||
"pending": 0
|
||||
},
|
||||
{
|
||||
"batch": "final state-service owners and keepers",
|
||||
"files": 8,
|
||||
"passed": 329,
|
||||
"failed": 0,
|
||||
"pending": 0
|
||||
}
|
||||
],
|
||||
"preservationReviews": [
|
||||
{
|
||||
"batch": "round4-ui",
|
||||
"baseline": "2633dbbba95e853e3cb0de165bdf5116e544e411",
|
||||
"method": "Independent whole-runtime AST comparison after actual new helper expansion and individually reviewed semantic edits. Type-only syntax and source metadata normalized; compiler is a separate gate.",
|
||||
"files": [
|
||||
{
|
||||
"file": "ui/src/components/IssueProperties.test.tsx",
|
||||
"sourceSha256": "6c0a2420fdffeb3ccf6c9f4b43b61b62c3bd0e107276a91402a25ae08ad54bd2",
|
||||
"proposalSha256": "8d604724e4c9c423b560d13dae6e939113f248b050905542970ee0660dfeab98",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"createRelation": 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "ui/src/components/AgentConfigForm.render.test.tsx",
|
||||
"sourceSha256": "dd3703a491b43ee5b7cd57c48798e8a4cec4dbabc075f222cea412383eca49d7",
|
||||
"proposalSha256": "57282ae3afe8c55ac118f3a658152d8df500a87b15383c8f6b0530a7fdcfb8a0",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"createFormQueryClient": 17,
|
||||
"renderFormView": 18,
|
||||
"daytonaEnvironments": 12,
|
||||
"e2bEnvironments": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "ui/src/components/OnboardingWizard.test.tsx",
|
||||
"sourceSha256": "c17e65d7e0604b58d398cdf8a2a8588e7bc388ffe6e2612cee8e567e01a30f20",
|
||||
"proposalSha256": "6215ee2f034686deaf2d6091590030dcdeccff1697422574e45e0351eaf5a7fe",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"renderWizardView": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "ui/src/components/IssueThreadInteractionCard.test.tsx",
|
||||
"sourceSha256": "3e3ebbe3da7ad7edd9386760bcf90a83c987956fc4f65b74bb761bd0160ce746",
|
||||
"proposalSha256": "2e8aefda409a2faa7e3a3bc4d3f292a17086c61eac1e34291002b62c7415a184",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {}
|
||||
},
|
||||
{
|
||||
"file": "ui/src/components/MarkdownBody.test.tsx",
|
||||
"sourceSha256": "1be4fe615ed6d9e1b8b49749f291475c12848beb5664758c512f368103121608",
|
||||
"proposalSha256": "7432e047a21ca0a75dc58ca0fd645c7cb0b59edc1719557e4e0cb0aafc8a642a",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"batch": "round4-server",
|
||||
"baseline": "2633dbbba95e853e3cb0de165bdf5116e544e411",
|
||||
"method": "Independent whole-runtime AST comparison after actual new helper expansion and individually reviewed semantic edits. Type-only syntax and source metadata normalized; compiler is a separate gate.",
|
||||
"files": [
|
||||
{
|
||||
"file": "server/src/__tests__/issue-comment-reopen-routes.test.ts",
|
||||
"sourceSha256": "214aaa47ce1a862e4d06f41a440d0dba2a2f9f2efa63259c635209a3f660c33e",
|
||||
"proposalSha256": "2dc9167f66f379cb5a1fe024faf78a79c7009d570c4ca4acc72448d0a00423c7",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"createScheduledRetry": 4,
|
||||
"createAgentReviewPolicy": 12,
|
||||
"createReviewIssue": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "server/src/__tests__/environment-routes.test.ts",
|
||||
"sourceSha256": "8993233f12a3b646f7a9755b817bac68916fda31753c2ffb30c4eba9fbcc9fe8",
|
||||
"proposalSha256": "ef2dd81154c25791d2020362b6a3cd508ae215d60b075e1496ea9c7aa38ee6bd",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"localBoardActor": 39,
|
||||
"createSecurePluginDriver": 6,
|
||||
"createSshConfig": 4,
|
||||
"createSecretBackedSshEnvironment": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "server/src/__tests__/instance-settings-routes.test.ts",
|
||||
"sourceSha256": "f007e394234f82d0014a1f2d83831942d0c3a2b123e026f4c22edd4d6491754f",
|
||||
"proposalSha256": "85f0ddf9afb42cfc3e243e107b47290d9f8c8e5879eb3932805466019c937dc4",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"localAdminActor": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "server/src/__tests__/agent-skills-routes.test.ts",
|
||||
"sourceSha256": "e9c67d26d49c51862cefdde9388893d0e11b32f7d29ee95c664741cd48bc7468",
|
||||
"proposalSha256": "175b4b5f274141a817c2135830c1b73ecdfb9597e1d0579af1d0207c6faf551e",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"skillSnapshot": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "server/src/__tests__/company-skills-routes.test.ts",
|
||||
"sourceSha256": "9fdfa5790bd33b9824e3aeed28daa01065eab248712d2f9482f633f7c33165a9",
|
||||
"proposalSha256": "7037feadb73f235f81afeb9499b5bc9b988e2057b43add48c7546f6558085a03",
|
||||
"fullProgramAstEqualAfterActualHelperExpansionAndEnumeratedBehaviorEdits": true,
|
||||
"helperCalls": {
|
||||
"createCatalogSkill": 3,
|
||||
"createSkillTestRunDetails": 5,
|
||||
"boardActor": 25,
|
||||
"assignedAgentActor": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"batch": "round4-cli-api-ticker",
|
||||
"method": "Actual proposed helper bodies expanded. Source metadata/comments/types and object shorthand normalized; object fields, array rows, JSX props, all values/callbacks/promises/awaits, action/write/Git order and cleanup remain strict. Statement-helper parameters are checked to be stable Identifier bindings. Only enumerated reviewed retirement/migration deltas are permitted.",
|
||||
"checks": [
|
||||
{
|
||||
"file": "cli/src/__tests__/company.test.ts",
|
||||
"sourceSha256": "d957294d6113f3b546e15e36289f5085852fc5ab1350529bc025a192fc05d378",
|
||||
"proposalSha256": "1cd0c0445ab57a8c74416a63da6acb4ddde36e8c09aa5b3c74db589792445be1",
|
||||
"actualHelperExpansionWholeRuntimeAstEqual": true,
|
||||
"expandedCalls": {
|
||||
"allImportEntities": 6,
|
||||
"sourceCompanyManifest": 2,
|
||||
"ceoManifest": 2,
|
||||
"alphaProjectManifest": 2,
|
||||
"kickoffIssueManifest": 2,
|
||||
"openAiEnvInput": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "packages/shared/src/app-definitions.test.ts",
|
||||
"sourceSha256": "cf1aec35f1f4c65dd7059f594e04030c339c2a2f329f6e8216a431280d3865c3",
|
||||
"proposalSha256": "d6aa2d7ba801b049358e89f48d39f3602ac936d1c28e7cd5b3313a2227fd1a95",
|
||||
"actualHelperExpansionWholeRuntimeAstEqual": true,
|
||||
"expandedCalls": {}
|
||||
},
|
||||
{
|
||||
"file": "packages/plugins/plugin-llm-wiki/tests/plugin.spec.ts",
|
||||
"sourceSha256": "21ae3eef99bb450f2cc0cac8cb7d781f0dbb043ad4fdf8c1d09b528021114242",
|
||||
"proposalSha256": "bcb816d66be0b0176d599bbb705f79724abeebe8f52f28ed1fc31787b06f9985",
|
||||
"actualHelperExpansionWholeRuntimeAstEqual": true,
|
||||
"expandedCalls": {
|
||||
"renderWikiPage": 22,
|
||||
"captureWikiWrites": 9,
|
||||
"managedSpaceRow": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "cli/src/__tests__/worktree.test.ts",
|
||||
"sourceSha256": "90162a4d544e80d7314649f2d0da5ca34c6968fbd4a63e491c57f5fdf7077db7",
|
||||
"proposalSha256": "4dd193538aaf9bdd0cab522a8647ea5fb6a573e26199561e65c725c8bcb51ce1",
|
||||
"actualHelperExpansionWholeRuntimeAstEqual": true,
|
||||
"expandedCalls": {
|
||||
"writeSeedConfigFiles": 6,
|
||||
"initializeTestRepo": 5
|
||||
}
|
||||
}
|
||||
],
|
||||
"canonicalChecks": [
|
||||
{
|
||||
"file": "cli/src/__tests__/worktree.test.ts",
|
||||
"baselineSha256": "47c51bafca401b39bd976c12ddabef00be8ff6d3c2bc79822c49d11a3f79bc85",
|
||||
"repairedSha256": "90162a4d544e80d7314649f2d0da5ca34c6968fbd4a63e491c57f5fdf7077db7",
|
||||
"wholeRuntimeAstEqualApartFromParentCanonicalization": true,
|
||||
"canonicalTempRootWrappers": 35
|
||||
},
|
||||
{
|
||||
"file": "packages/shared/src/worktree-seed-source.test.ts",
|
||||
"baselineSha256": "bd8708bab463280939f0aa8aa18341b028343fe98626d9be2154c87ab191c1a5",
|
||||
"repairedSha256": "b9d021050cced44bcee00fd3209c225c4e26117693b7491a50ef9d3bd0a67d17",
|
||||
"wholeRuntimeAstEqualApartFromParentCanonicalization": true,
|
||||
"canonicalTempRootWrappers": 3
|
||||
}
|
||||
],
|
||||
"coreChecks": [
|
||||
{
|
||||
"file": "ui/src/api/client.ts",
|
||||
"sourceSha256": "cac548df1d20c87a0ea8eede850cfe5081874262eb8c26c78058923db6947f69",
|
||||
"proposalSha256": "1e1b3f03e3269a5943f55d294f1c7aa9f5c3eca569858d9fdc7c5d976de88bba",
|
||||
"onlyDeletedPrivateGetterExport": "__inflightGetCount"
|
||||
},
|
||||
{
|
||||
"file": "ui/src/hooks/useSecondTick.ts",
|
||||
"sourceSha256": "e108dee2647be4f8f5472a70220d1019b18cce9a842e7bc25b863e298654ab07",
|
||||
"proposalSha256": "fd51875adf5f30295d847df58af19f75dcbb59c810b4f02919427cbc6ea4d3b3",
|
||||
"onlyDeletedPrivateGetterExport": "__secondTickInternals"
|
||||
}
|
||||
],
|
||||
"seamTestChecks": [
|
||||
{
|
||||
"file": "ui/src/api/client.test.ts",
|
||||
"sourceSha256": "b056adfc0a935cdabcc1c05b4473f76bc1f46fc6f280a671404c2735211ebe01",
|
||||
"proposalSha256": "1b3666404821ae4550b1fdf48fe27568077f8074dbdff8afc5f2966e79341ffd",
|
||||
"apiWholeRuntimeAstEqualApartFromReviewedPrivateRemovalAndErrorAbortRetry": true,
|
||||
"oldDeclarations": 12,
|
||||
"newDeclarations": 12
|
||||
},
|
||||
{
|
||||
"file": "ui/src/hooks/useSecondTick.test.tsx",
|
||||
"sourceSha256": "29d8f37a65070f28ddb43bec69e74477cdfb1e563b348aff03b6b5ca17902e95",
|
||||
"proposalSha256": "b59f9bab5e41bc611165577d8e095184094dd5b84b6d436d32656fd33fb5e459",
|
||||
"oldDeclarations": 2,
|
||||
"newDeclarations": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"batch": "round5-tools",
|
||||
"baseline": "3e7ee04591fd82f3effb89370f47aa90dcadd6eb",
|
||||
"method": "Only source metadata/comments and object shorthand differ. Actual candidate helper bodies expanded, removing only their new declarations and type-only IdRef aliases. Object-field, nested object, array, table, JSX-free input, promise, await, callback, actor/company/credential/expected value and statement order remain exact. Newly introduced literal spreads are allowed only when there are no overwritten keys or effectful helper arguments. All helper object bodies are fresh literals without external closure state.",
|
||||
"files": [
|
||||
{
|
||||
"path": "server/src/__tests__/tool-access-service.test.ts",
|
||||
"sourceSha256": "4cd7d6d02710eac514f14d87c316d15391028ae36c477d868f6b5a499a29f406",
|
||||
"proposalSha256": "dc3664a18f9fc6c45b3b5555376ae03def2708129ff5c3dc4f4623ea2f994c15",
|
||||
"completeRuntimeAndTypeAstEqualAfterActualHelperExpansionAndOneDeclarationRemoval": true,
|
||||
"helperOccurrences": 78,
|
||||
"allRemainingMatcherCallsEqual": true,
|
||||
"allAwaitExpressionsEqual": true,
|
||||
"allSupertestCallsEqual": true,
|
||||
"remainingMatcherCalls": 1346,
|
||||
"awaitExpressions": 1930,
|
||||
"beforeDeclarations": 266,
|
||||
"afterDeclarations": 265
|
||||
},
|
||||
{
|
||||
"path": "server/src/__tests__/tool-access-policy-service.test.ts",
|
||||
"sourceSha256": "484408a4eb3481e98d89863943b0fac64cf40e3794c06d0b4326a4b0d0f7625f",
|
||||
"proposalSha256": "6982ad8f42fceeb6428117f22db28a589f9b6d5f1b2465ca87ddd29420e06413",
|
||||
"completeRuntimeAndTypeAstEqualAfterActualHelperExpansionAndOneDeclarationRemoval": true,
|
||||
"helperOccurrences": 31,
|
||||
"allRemainingMatcherCallsEqual": true,
|
||||
"allAwaitExpressionsEqual": true,
|
||||
"allSupertestCallsEqual": true,
|
||||
"remainingMatcherCalls": 80,
|
||||
"awaitExpressions": 284,
|
||||
"beforeDeclarations": 35,
|
||||
"afterDeclarations": 35
|
||||
},
|
||||
{
|
||||
"path": "server/src/__tests__/tool-gateway-service.test.ts",
|
||||
"sourceSha256": "29c9b9739a5f928c49cd2982858a1323c242663450277f45fc9e3aea407cbe98",
|
||||
"proposalSha256": "67d8dfb12ef2215296af87be5c573f40175d71a2917b01113aa82c550fe4b6d6",
|
||||
"completeRuntimeAndTypeAstEqualAfterActualHelperExpansionAndOneDeclarationRemoval": true,
|
||||
"helperOccurrences": 58,
|
||||
"allRemainingMatcherCallsEqual": true,
|
||||
"allAwaitExpressionsEqual": true,
|
||||
"allSupertestCallsEqual": true,
|
||||
"remainingMatcherCalls": 231,
|
||||
"awaitExpressions": 431,
|
||||
"beforeDeclarations": 36,
|
||||
"afterDeclarations": 36
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"batch": "round5-state",
|
||||
"baseline": "3e7ee04591fd82f3effb89370f47aa90dcadd6eb",
|
||||
"method": "Independent full runtime AST expansion outside two individually reviewed AWS lock repairs",
|
||||
"files": [
|
||||
{
|
||||
"file": "server/src/__tests__/issue-thread-interactions-service.test.ts",
|
||||
"beforeSha256": "ddfad204b976a8218b6376007c36048154c4a10e25ef4d891531b87477931c10",
|
||||
"afterSha256": "6c70d8af0815de3d3ed9f87de94d20e7a161aa2db5fe938e80204a100ee418e9",
|
||||
"equivalent": true,
|
||||
"expandedBeforeSha256": "0a7affd96c9e84850e2540edea63bbc6eabf24f124468e2526fa3095f2ddd7af",
|
||||
"expandedAfterSha256": "0a7affd96c9e84850e2540edea63bbc6eabf24f124468e2526fa3095f2ddd7af",
|
||||
"allHelperCalls": {
|
||||
"interactionCompanyRow": 14,
|
||||
"parentIssueRow": 7,
|
||||
"activeCodexAgentRow": 19,
|
||||
"acceptIssueScope": 31
|
||||
},
|
||||
"allHelperArgumentsEffectFree": true,
|
||||
"beforeDeclarations": 89,
|
||||
"afterDeclarations": 89
|
||||
},
|
||||
{
|
||||
"file": "server/src/__tests__/secrets-service.test.ts",
|
||||
"beforeSha256": "ab9c9536ee144d9211bb8a205dd2e57ff928360de6ea695af74afd749e9652be",
|
||||
"afterSha256": "95708c40da78768c43c26a56c73cf9479a4a39bf2173561d9501a1ab6d13dfb1",
|
||||
"equivalent": true,
|
||||
"expandedBeforeSha256": "fb5da5592c1de24b62a44e476554924e0854cd2822767e46132ce63431c11475",
|
||||
"expandedAfterSha256": "fb5da5592c1de24b62a44e476554924e0854cd2822767e46132ce63431c11475",
|
||||
"allHelperCalls": {
|
||||
"awsVaultInput": 29,
|
||||
"preparedAwsVersion": 16,
|
||||
"managedAwsVersionRow": 4
|
||||
},
|
||||
"allHelperArgumentsEffectFree": true,
|
||||
"beforeDeclarations": 91,
|
||||
"afterDeclarations": 91
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
# Test audit: consolidate repeated owner fixtures and rendering
|
||||
|
||||
Date: 2026-10-12
|
||||
Branch: `codex/test-audit-next`
|
||||
Discovery baseline: `b4aee6ea18905690686fb318fa9cc6d4cc71a7e1`
|
||||
Integration base: `1e0cfcb4fc4ed78d10f46cd60990935af4ac9973` (merged master)
|
||||
Verified code commit: `4261a7fc1b964e54059c68246a0a4b7ea74bdcea`
|
||||
Parent cleanup: [PR #15978](https://github.com/paperclipai/paperclip/pull/15978)
|
||||
|
||||
This follow-up removes **2,041 net test lines across five files**. Every
|
||||
registered case and assertion remains. It changes no application source.
|
||||
The seven complete owner/sibling files pass all **990 cases** before and after.
|
||||
Workspace typecheck, build, token gates and diff checks pass. The change
|
||||
consolidates fixture setup while preserving execution count.
|
||||
|
||||
The parent PR merged on 2026-10-12 after all remote checks passed and a
|
||||
fresh Greptile 5/5 review. This branch used a separate managed checkout and
|
||||
dependency installation. Only its new follow-up commit was replayed onto
|
||||
the parent merge, with no conflicts or duplicated cleanup commits. All five
|
||||
test files still exactly match the independently reviewed candidates, and
|
||||
all 990 owner/sibling cases pass again on the merged base. The follow-up remains
|
||||
committed locally on its own branch. Earlier cleanup evidence, including its
|
||||
disclosed local timeout and passing owner reproduction, lives in
|
||||
`2026-10-12-test-audit.md`.
|
||||
|
||||
## Measured change
|
||||
|
||||
| File | Before lines | After lines | Net removed | Cases retained |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| server/src/__tests__/environment-runtime.test.ts | 8,110 | 7,223 | 887 | 162 |
|
||||
| server/src/__tests__/execution-workspaces-service.test.ts | 4,751 | 4,638 | 113 | 67 |
|
||||
| server/src/__tests__/company-portability.test.ts | 6,194 | 6,100 | 94 | 94 |
|
||||
| ui/src/pages/IssueDetail.test.tsx | 6,652 | 6,338 | 314 | 141 |
|
||||
| ui/src/components/IssueChatThread.test.tsx | 5,032 | 4,399 | 633 | 100 |
|
||||
| **Changed owners** | **30,739** | **28,698** | **2,041** | **564** |
|
||||
|
||||
The remaining 426 validation cases are unchanged TaskChatThread (225) and
|
||||
AppsConnect (201) siblings. Figures exclude this report. No case, timeout,
|
||||
skip condition, filename, CI route or production seam is removed.
|
||||
|
||||
## Owner and keeper decisions
|
||||
|
||||
All nominated cases are retained. Each original case remains the primary
|
||||
keeper of its regression assertions; helpers own only repeated inputs.
|
||||
|
||||
- Environment runtime: 71 repeated plugin/lease/worker/foreign-company
|
||||
expressions become synchronous file-local fixture builders. Complete
|
||||
identity, author, schema, readiness, capability, install-order, stale lease,
|
||||
fingerprint and RPC-budget variants remain defaults or explicit overrides.
|
||||
Preserve real persisted rows and the actual foreign-company rejection,
|
||||
orphan teardown/spool recovery and lease-reuse paths. Dynamic/spread rows
|
||||
and the named-constant secret provider stay inline.
|
||||
- Execution workspaces: 19 repeated task/recovery/branch/runtime/agent inputs
|
||||
become synchronous builders. Real Git operations, active claimant/runtime
|
||||
rows, locked races, clean/dirty divergence and durable recovery assertions
|
||||
remain in their original cases.
|
||||
- Company portability: 15 identical export invocations use one local helper;
|
||||
their distinct fixture data, redaction, permission, import, selected-file,
|
||||
logo and membership expectations remain explicit.
|
||||
- IssueDetail: 98 identical root/provider render frames share one synchronous
|
||||
helper. It retains the same QueryClient and root. Four nondefault children
|
||||
remain explicit JSX; unsafe undefined/key/ref/spread shapes stay inline.
|
||||
- IssueChatThread: 70 MemoryRouter/component frames share one synchronous
|
||||
helper with fresh original defaults. Supplied callback references, props,
|
||||
dynamic expression order, root identity and rerender/remount behavior remain.
|
||||
|
||||
TaskChatThread and AppsConnect already have useful fixtures or distinct
|
||||
transport/identity behavior. A TaskChatThread prototype saved only ten lines
|
||||
after helper overhead and was rejected. No further layer retirement was
|
||||
supported in these owners; separate provider, authentication, lifecycle and
|
||||
storage proof remains valuable.
|
||||
|
||||
## Preservation evidence
|
||||
|
||||
Original/candidate SHA-256 guards were validated before any checkout edit.
|
||||
Proposals were prepared outside the checkout during baseline execution.
|
||||
Independent reviewers checked both groups against the committed baseline.
|
||||
|
||||
Server: expand all 105 calls through the 16 actual helper bodies/defaults and
|
||||
compare all three complete programs. Field order, nested schemas/capabilities,
|
||||
types/casts, table rows, callbacks, hooks, 1,347 awaits and 1,201 expectation
|
||||
calls are unchanged. Helpers add no Promise boundary, transaction, UUID,
|
||||
clock read, receipt, assertion, RPC or reset. Objects and mocks remain fresh.
|
||||
|
||||
UI: independently expand all 98 + 70 actual render calls. The complete program
|
||||
outside those checked expressions is unchanged, including types, callbacks,
|
||||
actions, waits, timers, teardown and budgets. All 778 expectation calls and
|
||||
200 declarations remain. Check every thread root identity and dynamic prop
|
||||
evaluation order; check IssueDetail root/client bindings for shadowing.
|
||||
Only unique JSX attribute order is normalized; key/ref/spread shapes are
|
||||
excluded. No React component wrapper or hook is introduced.
|
||||
|
||||
Both independent reviews found no preservation blocker. No assertion was
|
||||
moved or repaired, so no additional production mutation was needed. The
|
||||
earlier parent PR's mutation proof is recorded in its report.
|
||||
|
||||
## Runtime verification and limits
|
||||
|
||||
- Complete baseline: seven files, 990 passed, zero failed/skipped.
|
||||
- Complete candidate: the same seven files, 990 passed, zero failed/skipped.
|
||||
- Rebased candidate: the same seven files, 990 passed, zero failed/skipped.
|
||||
- `pnpm --filter @paperclipai/ui typecheck`: pass before integration.
|
||||
- `pnpm -r typecheck`: pass before integration and at the verified code commit.
|
||||
- `pnpm build`: pass at the verified code commit.
|
||||
- Token gates, palette synchronization and character synchronization: pass.
|
||||
- `git diff --check`: pass.
|
||||
- The new checkout used its own workspace-linked dependencies and built its
|
||||
own TypeScript runner/shared/plugin SDK prerequisites. No dependencies or
|
||||
source files were linked to the concurrently changing PR checkout.
|
||||
- A complete default `pnpm test:run` has not been repeated for this follow-up.
|
||||
Its test-only fixture changes have complete affected-owner/sibling proof.
|
||||
Browser suites were not run; none of those suites changed. The parent PR
|
||||
has its own full CI evidence. No wall-time speedup is attributed to this work.
|
||||
|
||||
## Additional retirement search
|
||||
|
||||
A bounded independent search found no further defensible retirement of
|
||||
200 or more lines. Provider-specific behavior, separately implemented
|
||||
parsers, CSS contrast/theme/layout contracts and runtime/SDK wiring retain
|
||||
independent proof. Similar source guards or DOM class assertions did not
|
||||
provide complete behavioral keepers, so those layers remain.
|
||||
@@ -0,0 +1,92 @@
|
||||
# Test audit: repeated setup, duplicate cases and false proof
|
||||
|
||||
Date: 2026-10-12. Audit branch: `codex/test-audit-next`. Delivery branch: `codex/test-audit-followup`. Verified code revision: `64370831ebe191e5ce092f85f79b6fb661df7e16`, including master `cc88b61c0918f45f6d3215f5d2d2368c88297046`.
|
||||
|
||||
This follow-up removes **5,027 net test lines across 27 test files** and **15 redundant registered executions**. It separately removes **11 unused application lines** from two private test-inspection exports. Most savings come from sharing repeated setup while retaining every distinct case. No wall-time improvement is inferred from line counts.
|
||||
|
||||
The earlier merged [PR #15978](https://github.com/paperclipai/paperclip/pull/15978) removed 11,976 net test/support lines and 1,073 redundant executions. The two changes together save **17,003 test/support lines**. These counts exclude audit reports, upstream changes and the fixture portability repair.
|
||||
|
||||
## Savings and scope
|
||||
|
||||
| Batch | Net test lines removed | Registered executions removed | Preservation |
|
||||
| --- | ---: | ---: | --- |
|
||||
| Earlier local runtime/workspace/portability and IssueDetail/IssueChatThread | 2,041 | 0 | All original cases and assertions retained; 990 owner/sibling cases passed. See [the earlier follow-up report](2026-10-12-test-audit-next.md). |
|
||||
| Route fixtures and duplicate proof | 970 | 5 | Three redundant cases and two identical table executions removed; cancelled-reopen observation repaired. |
|
||||
| UI fixtures and duplicate proof | 521 | 6 | Exact assertions move into named stronger keepers; two weak observations repaired. |
|
||||
| CLI, shared catalog and wiki plugin | 238 | 3 | Exact keepers and fixture expansion; genuine run-receipt and positive-write witnesses added. |
|
||||
| Public API and ticker observations | -10 | 0 | Tests grow by ten lines to replace private-state inspections with observable results. |
|
||||
| Tool access, policy and gateway | 656 | 1 | One exact omitted-scope duplicate removed; all other matcher and await order retained. |
|
||||
| Interactions and secrets state services | 611 | 0 | All 180 declarations / 197 cases retained; two AWS lock observations repaired. |
|
||||
| **Total follow-up** | **5,027** | **15** | **No independent security or lifecycle contract retired.** |
|
||||
|
||||
Line savings include all newly added local helper code. The application reduction is five lines of `__inflightGetCount` and six lines of `__secondTickInternals`. Repository-wide caller searches found only their tests. Both module cores otherwise remain byte-identical. Their tests retain sharing, cancellation, stale-account isolation, rendered ticks and timer lifecycle.
|
||||
|
||||
The final intended diff has 27 test files, those two application files and audit evidence. No schema, telemetry, runtime service, package manifest, lockfile or CI routing change is part of this cleanup. Incoming master changes were merged, so absent upstream files cannot inflate the savings.
|
||||
|
||||
## Removed execution to keeper map
|
||||
|
||||
Each retained declaration is its own keeper for setup-only consolidation. The following is the complete map for the 15 removed executions; the three-row influence table accounts for two of them.
|
||||
|
||||
| Removed proof | Retained keeper and boundary |
|
||||
| --- | --- |
|
||||
| Managed-sandbox duplicate DELETE rejection | Same owner/admin, platform row, DELETE, 403 and code; stronger keeper also forbids blast-radius/removal calls. |
|
||||
| Agent-skills duplicate GET/POST secret-context check | Mandatory resolver callbacks in both successful route keepers check the same actor/user/source/responsible literal context, adapter type, skip-user-secrets and filtered environment. |
|
||||
| Company-skills open-default legacy-consent duplicate | Same actor/company/run, deny-missing-consent decision and POST input; successful write keeper checks no consent-gate invocation and the actual write. |
|
||||
| Two extra missing/wrong-run influence table rows | All three ran the identical zero-argument callback. One retains both POST/PATCH errors, details, two propagation calls and no writes. The identity-variant service sibling and real PostgreSQL race sibling remain. |
|
||||
| Onboarding missing-auth/no-stored-login duplicate | Warning text moves into `blocks the hire on a warn result that holds adapter_auth_missing, and shows the returned checks`. |
|
||||
| Interaction connection controls for another viewer | `shows another viewer only who it is waiting for` retains waiting copy, zero buttons, no actions/auth URL and absence of Not now. |
|
||||
| Legitimate question-card rendering duplicate | `exposes pending question options as selectable radio and checkbox controls` gains positive child count and retains stronger exact radio counts. |
|
||||
| Addressed-user Connect/Not-now duplicate | `opens the shared connection setup for the addressed user` gains the exact copy and absence checks before executing the real setup action. |
|
||||
| Non-GitHub-link icon duplicate | `opens external links in a new tab with safe rel attributes` uses the same docs input and retains exact anchor, no GitHub icon, target and rel. |
|
||||
| External-link trailing-icon duplicate | The same docs-link keeper retains the icon glued to the final character and the original glyph matcher. |
|
||||
| Hugging Face scope duplicate | `requests Airtable record, schema and comment writes, and Hugging Face repository/job actions` retains the same independent `[read-mcp, read-repos, contribute-repos, jobs]` literal. |
|
||||
| Whole-catalog method/field invariants duplicate | Full-catalog `appDefinitionsSchema.parse` enforces nonempty ownership modes, required credential placeholders and API-key key placement for every definition; provider-specific permission literals remain. |
|
||||
| Worktree shutdown formatter duplicate | Real `ensure-seeded` failure retains restore error, safe diagnostic, failed manifest and lock release. The unique migrations fallback expectation moves unchanged into that keeper. |
|
||||
| Tool-access omitted-provider-scope duplicate | `marks a scope inferred from the request when the provider omits one` calls the identical `connectSlackWithTokenScope(null, ["channels:read"])`, retains all three persisted scope fields and also checks the outgoing authorization scope. Reported over-grants remain separately tested. |
|
||||
|
||||
The influence identity sibling uses a fake `counterDb` adapter for locked-row variants. The PostgreSQL sibling independently inserts real rows and races writes. Neither is removed, and fake SQL inputs are not described as durable persistence proof.
|
||||
|
||||
## Preservation review and repairs
|
||||
|
||||
Every nominated owner was read in full, including hooks, declarations, tables and cleanup, before classification as retain, fix false proof, consolidate or delete. Reviews checked actual owner/caller/history/CI boundaries rather than treating similar names as proof. Separate reviewers expanded the actual new helper bodies and arguments against complete original runtime ASTs. Types and source metadata are normalized separately from the compiler gate. Fields, nested values, fresh allocations, action/query/UUID/Date/callback/await order, tables, timeouts and teardown remain strict outside explicitly reviewed semantic edits.
|
||||
|
||||
The tool-access expansion covers 167 helper occurrences, 1,657 remaining matcher calls and 2,645 awaits. The state-service expansion covers 120 helper calls; no DB query is hidden in a new helper, and no new helper manufactures a tested service result. All 106 interaction and 91 secret cases remain. Two AWS repairs add two provider-call assertions while retaining the original durable results.
|
||||
|
||||
Review restored or strengthened these contracts before cutover:
|
||||
|
||||
- Restore the no-agentMap resolved footer/chip case byte-for-byte; a richer mapped-agent case cannot prove its fallback.
|
||||
- Match the exact external `<a href="https://example.com/docs"` prefix; href/target/rel alone could pass on a span.
|
||||
- Issue a fresh successful same-path GET after an unrelated 401 and after all callers abort, with exact two-fetch counts and independent values.
|
||||
- Keep an inactive ticker probe beside an active peer; only the active output may tick, and its unmount must clear the last timer.
|
||||
- Observe actual authenticated account-binding text after waiting, and mount the Claude login card positively before asserting absence of Use saved login.
|
||||
- Require cancelled bare-agent reopen to return the exact 409/error before writing a comment. The old broad status allowance accepted 201.
|
||||
- Capture and return the original wiki SDK `sendMessage` receipt unchanged, and compare its genuine run ID to the operation UPDATE bindings. Positive source/page write counts prevent empty `.every` predicates passing.
|
||||
- Confirm real account-home lock-holder entry, observe actual AWS create/version provider entry, assert exclusion while parked and exact eventual event order. A separate baseline secret preserves the tested rotation's original 1 → 2 result. Immediate rejection observers and `finally` release/all-settle preserve failure cleanup.
|
||||
|
||||
Wiki database witnesses inspect emitted SQL and bindings through the SDK's recorder. They do not claim that the recorder executed real SQL. Assertions guaranteed by its unconditional host-list markup were removed without retiring the real title/binding/configuration-link behavior.
|
||||
|
||||
## Falsification and complete positive controls
|
||||
|
||||
[The compact evidence record](2026-10-12-test-audit-controls.json) preserves actual source SHA guards, independent expansion results and mutation assertion receipts. It records 18 executions: 14 route/UI/wiki mutations, two original AWS weak controls and two repaired AWS controls. The original AWS cases pass their deliberate bypasses; the repaired cases fail on actual provider entry before lock release. All **16 repaired or retained keeper mutations** fail at the intended assertion, and every mutated source is restored byte-for-byte in `finally` before ordinary testing.
|
||||
|
||||
| Complete unmutated control | Result |
|
||||
| --- | --- |
|
||||
| Round 4 selected owners and siblings, including standalone wiki | 1,455 / 1,455 passed across 58 files; zero failed/pending. |
|
||||
| Tool-access owners and state-service keeper baselines | 623 / 623 passed: 491 tool cases plus 132 state siblings; zero failed/pending. |
|
||||
| Final state-service owners and siblings | 329 / 329 passed across eight files: 197 owners plus 132 siblings; zero failed/pending. |
|
||||
| Canonical worktree/shared seed-source control | 80 / 80 passed; zero failed/pending. |
|
||||
| Workspace `pnpm -r typecheck` | Passed at the verified code revision. |
|
||||
| UI `pnpm check:token-gates` | Passed at the verified code revision. |
|
||||
| Workspace `pnpm build` | Passed at the verified code revision. |
|
||||
| Full default `pnpm test:run` | Invoked at the verified code revision. The completed result is recorded in the follow-up PR’s Verification section. |
|
||||
| `git diff --check` | Passed before evidence publication; delivery also checks its final evidence diff. |
|
||||
|
||||
Rows overlap; they are separate receipts and must not be summed into a unique test count. Root Vitest excludes standalone wiki, so its three complete files were also run with its own existing configuration. Browser suites were not run: this change does not touch browser-suite sources or change a product journey. No deadline, retry, skip or shard was weakened for this audit.
|
||||
|
||||
## Portability and environment controls excluded from savings
|
||||
|
||||
The initial 1,157-case main baseline had 14 failures, all in CLI worktree fixtures using `/var` where the production guard correctly requires canonical `/private/var`. A separate shared seed-source baseline had the same alias failure in eight cases. A separate commit wraps only 38 fixture-allocation parents with `fs.realpathSync(os.tmpdir())` (35 CLI, three shared). It preserves every case/assertion and every explicit attacker-symlink negative. The complete 80-case repaired control passed; none of this is counted as pruning.
|
||||
|
||||
The standalone wiki package declares React as a peer, and this checkout disables automatic peer installation. Its baseline initially could not collect two files. An ignored node_modules link supplies the existing pinned React 19.2.8 from this same worktree. All 101 standalone baseline cases then passed. This setup changes no manifest or lockfile and links no dependencies across worktrees.
|
||||
|
||||
PR CI and exact-head review results belong on the follow-up PR. The report records local evidence at an immutable code revision; later evidence-only commits do not change the tested source. Full source ledgers and proposal staging files remain temporary, while the decisions, keeper map, actual preservation receipts and falsification outcomes above are preserved in the repository.
|
||||
Reference in new issue
Block a user