60706ed5e4fa979929e66ffa03f122cbca71ba22
2739 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
60706ed5e4 |
fix: demote high-frequency TUI log lines to debug
Session setup, track bookkeeping, intentional skill exclusions, token-cache metrics, zero-count recovery summaries, and expected-missing PROMPT seed reads were flooding the default log pane. Gate them behind FUSION_DEBUG so only state transitions and operator-actionable warnings remain visible. |
||
|
|
01d65805c3 |
FN-8693: refresh reused worktree bases before execution
Refresh reused execution worktrees against the current integration baseline. - Rebase or reset clean reused worktrees before coding sessions while preserving task commits. - Persist and audit refreshed base SHAs, and block unsafe refresh states before execution. - Cover executor, graph, and heartbeat refresh paths with regression tests. Files changed: .changeset/fn-8693-stale-worktree-base.md | 7 + docs/architecture.md | 1 + .../src/__tests__/agent-heartbeat-worktree.test.ts | 28 ++++ .../__tests__/ce-workflow-step-executor.test.ts | 44 ++++++ .../src/__tests__/worktree-base-refresh.test.ts | 90 ++++++++++++ packages/engine/src/agent-heartbeat.ts | 35 ++++- packages/engine/src/executor.ts | 67 ++++++++- packages/engine/src/merger.ts | 5 + packages/engine/src/run-audit.ts | 11 ++ packages/engine/src/workflow-graph-executor.ts | 32 ++++- packages/engine/src/worktree-acquisition.ts | 28 +++- packages/engine/src/worktree-base-refresh.ts | 158 +++++++++++++++++++++ 12 files changed, 498 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-8693 Fusion-Task-Lineage: e39a441f-39b5-4723-b503-753e921018f3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b8bde05ca6 |
FN-8703: render project overview before health telemetry
Render registered project cards immediately while optional health telemetry hydrates in the background. - Publish completed health batches progressively and prevent stale responses from overwriting current state. - Keep project controls usable while health metrics load and indicate per-card pending telemetry. - Add coverage and operator documentation for progressive overview hydration. Files changed: .changeset/fn-8703-project-overview-load.md | 7 ++ docs/dashboard-guide.md | 3 +- packages/dashboard/app/components/ProjectCard.tsx | 12 ++- .../dashboard/app/components/ProjectOverview.tsx | 15 +-- .../components/__tests__/ProjectOverview.test.tsx | 101 ++++++++++++++++++++ .../app/hooks/__tests__/useProjectHealth.test.ts | 98 ++++++++++++++++++++ packages/dashboard/app/hooks/useProjectHealth.ts | 102 ++++++++++----------- 7 files changed, 277 insertions(+), 61 deletions(-) Fusion-Task-Id: FN-8703 Fusion-Task-Lineage: eb816c9d-c808-4d52-a3f0-28bb9de5f149 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b8f7f9e75c |
FN-8701: standardize tool-call detail displays
Standardize expandable tool-call payloads across dashboard chat and log surfaces. - Add a shared formatter and detail renderer that preserves complete browser-available arguments and results. - Use compact previews with wrapped, scrollable expanded payloads in chat, activity, and agent logs. - Cover formatting and rendering behavior with dashboard tests and document the display contract. Files changed: .changeset/fn-8701-tool-call-display.md | 7 ++ docs/dashboard-guide.md | 4 +- .../dashboard/app/components/AgentLogViewer.tsx | 12 +++- packages/dashboard/app/components/ChatView.css | 37 ++--------- .../app/components/StandardChatSurface.tsx | 56 +++++++--------- packages/dashboard/app/components/TaskChatTab.css | 17 ----- packages/dashboard/app/components/TaskChatTab.tsx | 31 +++++---- .../dashboard/app/components/ToolCallDetails.css | 52 +++++++++++++++ .../dashboard/app/components/ToolCallDetails.tsx | 77 ++++++++++++++++++++++ .../__tests__/AgentLogViewer.rendering.test.tsx | 8 +++ .../components/__tests__/ChatView.core.test.tsx | 24 +++++++ .../app/components/__tests__/TaskChatTab.test.tsx | 33 +++++++--- .../__tests__/TaskPlannerChatTab.test.tsx | 19 ++++++ 13 files changed, 275 insertions(+), 102 deletions(-) Fusion-Task-Id: FN-8701 Fusion-Task-Lineage: 86513f9a-31d4-45fb-97fe-1f0c73d0e5b3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
e8ca86d5ee |
FN-8705: prioritize review and execution slot admission
Prioritize lifecycle-critical work whenever project capacity becomes available. - Rank admission candidates as review/merge, execution, then planning. - Coordinate scheduler handoffs with project and host capacity reservations. - Cover lane priority and document the updated operator behavior. Files changed: .changeset/fn-8705-slot-priority.md | 7 ++ docs/architecture.md | 2 +- docs/dashboard-guide.md | 2 +- packages/engine/src/__tests__/concurrency.test.ts | 95 +++++++++++----------- .../engine/src/__tests__/project-engine.test.ts | 4 +- .../starved-refinement-x-triage-poll.test.ts | 11 ++- .../__tests__/triage-refinement-routing.test.ts | 16 ++-- .../workflow-continuation-capacity.test.ts | 3 +- packages/engine/src/concurrency.ts | 37 +++++++-- packages/engine/src/project-engine.ts | 10 ++- packages/engine/src/runtimes/in-process-runtime.ts | 3 +- packages/engine/src/scheduler.ts | 40 ++++----- packages/engine/src/triage.ts | 7 +- 13 files changed, 133 insertions(+), 104 deletions(-) Fusion-Task-Id: FN-8705 Fusion-Task-Lineage: ef66360b-e504-4e3f-b25e-b032a719d8c0 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
1aa1516023 |
FN-8692: harden mission validator assertion matching
Make validator assertion identity handling explicit and fail closed for ambiguous legacy responses. - Include authoritative assertion IDs in validator prompts - Recover only unique exact-count legacy results positionally - Reject duplicate unknown and empty assertion IDs with regression coverage - Document the assertion identity contract and add a patch changeset Files changed: .changeset/fn-8692-validator-assertion-ids.md | 7 + docs/missions.md | 2 +- .../src/__tests__/mission-execution-loop.test.ts | 142 ++++++++++++++++++++- packages/engine/src/mission-execution-loop.ts | 70 ++++++++-- 4 files changed, 204 insertions(+), 17 deletions(-) Fusion-Task-Id: FN-8692 Fusion-Task-Lineage: 973c65e9-962f-472b-8d42-aef1de830d70 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ac8ce148d5 |
FN-8691: suppress repeated task wedge notifications
Prevent resolved-and-rewedged tasks from flooding operator notification channels. - Persist per-reason notification timestamps with a six-hour cooldown. - Apply cooldown claims consistently in durable storage and in-memory fallback paths. - Cover reason transitions, legacy state, invalid timestamps, and cooldown expiry. Files changed: .changeset/fn-8691-wedge-notification-cooldown.md | 7 ++ docs/architecture.md | 4 +- .../postgres/store-wedge-resolution.pg.test.ts | 67 +++++++++++- packages/core/src/index.ts | 1 + packages/core/src/store.ts | 21 +++- packages/core/src/task-store/task-mutation-ops.ts | 6 ++ packages/core/src/types.ts | 2 + packages/core/src/types/task-core.ts | 15 +++ .../__tests__/task-wedge-notification.test.ts | 117 ++++++++++++++++++++- .../src/notification/notification-service.ts | 30 +++++- 10 files changed, 261 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-8691 Fusion-Task-Lineage: b7460508-f9b0-488b-828c-a51e9477304d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
79d2a73a10 |
FN-8690: document Grok CLI provenance blocker
Document the unavailable Grok CLI source provenance and preserve the existing usage gate. - Record provenance investigation results and the BLOCKED-NO-SOURCE hand-off - Validate FN-8690 evidence sections and canonical verdicts - Explain why the API-supplied percentage gate remains unchanged Files changed: docs/solutions/integration-issues/grok-cli-usage-data-source.md | 64 ++++++++++++++++++++++ packages/dashboard/src/__tests__/grok-usage-finding-doc.test.ts | 21 +++++++ packages/dashboard/src/usage.ts | 3 + 3 files changed, 88 insertions(+) Fusion-Task-Id: FN-8690 Fusion-Task-Lineage: 4521063d-2a9a-4710-9609-35b7582a2f2d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
04c2bb4707 |
FN-8654: rotate credential instances after provider limits
Retry provider-limit failures with eligible credential instances before falling back to existing pauses and backoff. - Add a runtime-shared credential rotator with cooldown, exhaustion, and audit handling. - Wire credential rotation into executor and heartbeat retry lanes while preserving user pause controls. - Document the behavior and cover rotation, recovery, and retry paths. Files changed: .changeset/fn-8654-credential-instance-rotation.md | 7 + AGENTS.md | 1 + docs/architecture.md | 2 +- docs/settings-reference.md | 4 + .../__tests__/credential-instance-rotation.test.ts | 88 +++++++++++ .../__tests__/credential-rotation-lanes.test.ts | 20 +++ .../__tests__/credential-rotation-recovery.test.ts | 19 +++ .../__tests__/credential-rotation-wiring.test.ts | 15 ++ .../__tests__/rate-limit-retry-rotation.test.ts | 50 ++++++ .../src/__tests__/usage-limit-detector.test.ts | 14 ++ packages/engine/src/agent-heartbeat.ts | 102 +++++++++++- .../engine/src/credential-instance-rotation.ts | 175 +++++++++++++++++++++ packages/engine/src/executor.ts | 141 +++++++++++++++-- packages/engine/src/index.ts | 7 + packages/engine/src/project-engine.ts | 5 + packages/engine/src/rate-limit-retry.ts | 32 +++- packages/engine/src/runtimes/in-process-runtime.ts | 29 +++- packages/engine/src/usage-limit-detector.ts | 18 ++- 18 files changed, 699 insertions(+), 30 deletions(-) Fusion-Task-Id: FN-8654 Fusion-Task-Lineage: 44d63441-270c-4949-8c34-47ec4c9992e4 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
006cc40454 |
FN-8685: add durable cross-process task deletion consumers
Deliver durable, replay-safe cross-process task deletion observation. - Add PostgreSQL lifecycle consumer cursors, leases, acknowledgements, retention, and recovery. - Start named consumers in dashboard, serve, and engine runtime paths. - Preserve delete integration metadata while suppressing replayed GitHub and GitLab side effects. - Cover outbox identity, observed delivery, fencing, and reconciliation behavior. Files changed: ...fn-8685-cross-process-task-deleted-observers.md | 7 + .../fn-8685-task-deleted-outbox-consumers.md | 7 + docs/architecture.md | 8 +- ...tgres-cross-process-task-deleted-observation.md | 8 +- docs/storage.md | 10 +- packages/cli/src/commands/dashboard.ts | 9 +- packages/cli/src/commands/serve.ts | 9 +- packages/cli/src/project-context.ts | 9 +- .../task-deleted-outbox-consumer.pg.test.ts | 157 ++++++++ ...-deleted-observed-dispatch-side-effects.test.ts | 36 ++ .../task-lifecycle-consumer-identity.test.ts | 22 ++ packages/core/src/index.ts | 11 + .../0041_fn_8685_task_lifecycle_consumers.sql | 88 +++++ packages/core/src/postgres/schema-applier.ts | 16 +- packages/core/src/postgres/schema/project.ts | 45 +++ packages/core/src/postgres/startup-factory.ts | 4 + packages/core/src/store.ts | 54 ++- .../__tests__/lifecycle-outbox-writer.test.ts | 4 +- .../core/src/task-store/archive-lifecycle-2.ts | 1 + packages/core/src/task-store/lifecycle-ops.ts | 13 +- packages/core/src/task-store/lifecycle-outbox.ts | 2 + packages/core/src/task-store/project-store-ops.ts | 4 +- .../src/task-store/task-deleted-outbox-consumer.ts | 333 +++++++++++++++++ .../task-store/task-lifecycle-consumer-identity.ts | 32 ++ .../task-store/task-lifecycle-consumer-registry.ts | 396 +++++++++++++++++++++ .../task-store/task-lifecycle-event-retention.ts | 104 ++++++ packages/core/src/task-store/task-mutation-ops.ts | 1 + packages/dashboard/src/github-tracking-state.ts | 12 +- packages/dashboard/src/gitlab-delete-close.ts | 3 + packages/dashboard/src/gitlab-split-close.ts | 7 +- packages/dashboard/src/project-store-resolver.ts | 9 +- packages/engine/src/project-manager.ts | 4 +- packages/engine/src/project-runtime.ts | 2 +- packages/engine/src/runtimes/in-process-runtime.ts | 17 +- packages/engine/src/self-healing.ts | 27 ++ 35 files changed, 1439 insertions(+), 32 deletions(-) Fusion-Task-Id: FN-8685 Fusion-Task-Lineage: 63eca9ac-d2af-44b0-ba79-388a950148d3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
4b306f10bd |
FN-8689: document Grok CLI source provenance gap
Record the unrecoverable Grok CLI provenance chain and preserve the unmeterable usage state. - Document installed asset identity, attempted provenance retrievals, and the static-blocked verdict. - Clarify that the legacy billing request is not verified CLI /usage behavior. - Add a regression test for the provenance finding and credential-safe documentation. Files changed: docs/solutions/integration-issues/grok-cli-usage-data-source.md | 172 +++++++++++---------- packages/dashboard/src/__tests__/grok-usage-finding-doc.test.ts | 45 ++++++ packages/dashboard/src/usage.ts | 8 +- 3 files changed, 143 insertions(+), 82 deletions(-) Fusion-Task-Id: FN-8689 Fusion-Task-Lineage: 473fc008-2e08-47f6-8f53-152da5b2c31a Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
8c9346ee94 |
FN-8684: persist task deletion events transactionally
Persist task-deletion lifecycle events through a transactional PostgreSQL outbox. - Add the task lifecycle outbox schema, migration, and atomic writer. - Route deletion notice persistence through the transaction and preserve non-blocking cleanup. - Cover outbox behavior, schema installation, and caller attribution with tests. Files changed: .changeset/fn-8684-task-deleted-outbox-writer.md | 7 + docs/architecture.md | 6 + docs/storage.md | 6 + .../src/__tests__/postgres/schema-applier.test.ts | 82 ++++++++- .../task-delete-caller-attribution.test.ts | 12 +- .../task-delete-nonblocking-cleanup.test.ts | 13 +- .../core/src/__tests__/task-delete-notice.test.ts | 7 +- .../0040_fn_8684_task_lifecycle_outbox.sql | 44 +++++ packages/core/src/postgres/schema-applier.ts | 15 +- packages/core/src/postgres/schema/project.ts | 27 +++ .../__tests__/lifecycle-outbox-writer.test.ts | 201 +++++++++++++++++++++ .../core/src/task-store/archive-lifecycle-2.ts | 93 ++++++++-- packages/core/src/task-store/async-persistence.ts | 26 ++- packages/core/src/task-store/lifecycle-outbox.ts | 46 +++++ 14 files changed, 557 insertions(+), 28 deletions(-) Fusion-Task-Id: FN-8684 Fusion-Task-Lineage: 1869d221-2d8a-48fb-b245-9cd1af56bda0 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
a7591853eb |
FN-8688: document unverified Grok CLI usage source
Document the provenance gap that prevents deriving Grok CLI usage data safely. - Record version-skewed source and sanitized billing-replay evidence - Keep absent Grok usage fields authenticated but unmeterable pending source-backed confirmation - Link the usage-provider rationale to the investigation record Files changed: .../grok-cli-usage-data-source.md | 93 ++++++++++++++++++++++ packages/dashboard/src/usage.ts | 4 +- 2 files changed, 95 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-8688 Fusion-Task-Lineage: 5aafa505-968f-4f63-83db-35e623f84052 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c978cdbacf |
FN-8687: close imported GitLab issues on task deletion
Add GitLab close-on-delete behavior for imported source issues. - Close linked GitLab issues by default while honoring leave and delete action semantics. - Preserve split-close ownership, skip merge requests, and limit malformed tracking fallback to deletion. - Document the lifecycle contract and add dashboard coverage. Files changed: .changeset/fn-8687-gitlab-close-on-delete.md | 7 ++ docs/gitlab-parity-inventory.md | 20 +++- docs/settings-reference.md | 1 + docs/task-management.md | 5 +- .../src/__tests__/gitlab-delete-close.test.ts | 101 +++++++++++++++++++++ .../src/__tests__/gitlab-lifecycle.test.ts | 35 +++++++ .../gitlab-parity-inventory-documentation.test.ts | 7 +- .../__tests__/gitlab-source-issue-close.test.ts | 8 ++ .../src/__tests__/gitlab-split-close.test.ts | 12 +++ packages/dashboard/src/gitlab-delete-close.ts | 90 ++++++++++++++++++ packages/dashboard/src/gitlab-lifecycle.ts | 33 +++++-- packages/dashboard/src/gitlab-split-close.ts | 2 +- packages/dashboard/src/index.ts | 1 + .../dashboard/src/routes/register-git-github.ts | 7 ++ 14 files changed, 313 insertions(+), 16 deletions(-) Fusion-Task-Id: FN-8687 Fusion-Task-Lineage: 48bc9159-fc35-43cb-b72e-1b6260d9e3cb Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
0e8f6769ba |
FN-8666: add credential instance pickers
Add credential-instance selection across dashboard model configuration surfaces. - Expose provider credential instances in custom model dropdowns and task, workflow, and settings forms. - Persist per-role credential-instance overrides through dashboard APIs and effective model resolution. - Document credential-instance precedence and cover dropdown/settings behavior, including task state synchronization. Files changed: .changeset/fn-8666-credential-instance-picker.md | 7 ++ docs/settings-reference.md | 2 + docs/workflow-steps.md | 2 +- packages/dashboard/app/api.ts | 1 + packages/dashboard/app/api/models-usage.ts | 27 ++++- packages/dashboard/app/api/tasks.ts | 8 ++ .../app/components/CustomModelDropdown.css | 12 ++- .../app/components/CustomModelDropdown.tsx | 71 ++++++++++++- .../dashboard/app/components/InlineCreateCard.tsx | 23 +++- packages/dashboard/app/components/ListView.tsx | 29 +++++- .../app/components/ModelSelectionModal.tsx | 25 ++++- .../dashboard/app/components/ModelSelectorTab.tsx | 29 +++++- packages/dashboard/app/components/NewTaskModal.tsx | 23 +++- .../dashboard/app/components/QuickEntryBox.tsx | 28 +++++ .../dashboard/app/components/SettingsModal.tsx | 2 + .../dashboard/app/components/TaskDetailModal.tsx | 32 +++++- packages/dashboard/app/components/TaskForm.tsx | 18 ++++ .../app/components/WorkflowNodeEditor.tsx | 13 ++- .../app/components/WorkflowSettingsPanel.tsx | 38 ++++++- ...ustomModelDropdown.credential-instance.test.tsx | 111 ++++++++++++++++++++ .../__tests__/WorkflowSettingsPanel.test.tsx | 9 +- .../app/components/effective-model-resolution.ts | 8 +- .../settings/sections/GlobalModelsSection.tsx | 31 +++++- .../settings/sections/ProjectModelsSection.tsx | 116 ++++++++++++++++----- .../ProjectModelsSection.chatDefault.test.tsx | 33 +++++- packages/dashboard/app/hooks/useFavorites.ts | 6 +- packages/dashboard/app/hooks/useModelsCache.ts | 5 +- .../src/routes/register-task-workflow-routes.ts | 17 ++- 28 files changed, 655 insertions(+), 71 deletions(-) Fusion-Task-Id: FN-8666 Fusion-Task-Lineage: 6c3711b3-68b8-47a0-ac36-4b64846adf39 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
4f09758dc8 |
FN-8681: retarget executor step credential instances
Enable executor step sessions to use selected and rotated credential instances. - Pass task-selected credential instances into step-session execution. - Re-resolve live credential targets after usage-limit retries using the effective agent runtime configuration. - Retarget future sessions safely and cover retry behavior. - Document the runtime behavior and add a patch changeset. Files changed: .changeset/fn-8681-credential-instance-retarget.md | 7 + docs/settings-reference.md | 7 +- .../src/__tests__/step-session-executor.test.ts | 211 +++++++++++++++++++++ packages/engine/src/executor.ts | 21 ++ packages/engine/src/step-session-executor.ts | 94 ++++++++- 5 files changed, 332 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-8681 Fusion-Task-Lineage: 99724283-6f5d-4890-b7f8-65af1d88b12c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
4009eb34cb |
FN-8683: remove unreachable SQLite task polling replica
Document PostgreSQL task-deletion observation and remove the obsolete SQLite polling path. - Remove polling state, replica emissions, and activity-log suppression from TaskStore. - Retain backend-aware cache warming while documenting the transactional-outbox follow-up. - Add tombstone and soft-delete abort coverage across core and engine lanes. Files changed: docs/architecture.md | 3 +- ...tgres-cross-process-task-deleted-observation.md | 128 ++++++++++++++++ docs/storage.md | 3 +- .../task-delete-nonblocking-cleanup.test.ts | 54 +++++++ .../task-deleted-polling-replica-tombstone.test.ts | 57 +++++++ .../task-updated-lanes-emit-surfaces.test.ts | 26 ---- packages/core/src/store.ts | 13 +- packages/core/src/task-store/lifecycle-ops.ts | 168 ++------------------- packages/core/src/task-store/task-artifacts-ops.ts | 4 - .../__tests__/executor-soft-delete-abort.test.ts | 15 ++ .../src/__tests__/triage-soft-delete-abort.test.ts | 14 ++ 11 files changed, 284 insertions(+), 201 deletions(-) Fusion-Task-Id: FN-8683 Fusion-Task-Lineage: a052db0c-b6fc-4b05-b6b2-f8217b56ded0 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
23c9992e7b |
FN-8682: add GitLab split-close issue comments
GitLab source issues now receive an explanatory split handoff before closure. - Add a GitLab split-close service that posts normalized child-task notes before closing source issues. - Wire split-close handling across project stores while preserving merge-request and failure safeguards. - Document GitLab lifecycle parity and cover split-close behavior with tests. Files changed: .changeset/fn-8682-gitlab-split-close-comment.md | 7 ++ docs/gitlab-parity-inventory.md | 2 +- docs/task-management.md | 1 + .../gitlab-parity-inventory-documentation.test.ts | 2 + .../src/__tests__/gitlab-split-close.test.ts | 113 +++++++++++++++++++++ packages/dashboard/src/gitlab-lifecycle.ts | 6 +- packages/dashboard/src/gitlab-split-close.ts | 98 ++++++++++++++++++ packages/dashboard/src/gitlab-tracking-state.ts | 6 +- packages/dashboard/src/index.ts | 1 + .../dashboard/src/routes/register-git-github.ts | 6 ++ 10 files changed, 237 insertions(+), 5 deletions(-) Fusion-Task-Id: FN-8682 Fusion-Task-Lineage: 8eca9888-b10a-4ea9-b9d3-fc09a39022ab Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
3793b576d8 |
FN-8673: comment on split source issue closures
Explain GitHub source-issue closures when imported work is split into subtasks. - carry split closure context through task deletion and triage - post one explanatory comment before closing source and tracking GitHub issues - preserve exactly-one-comment behavior when close retries after transient failures - document split closure behavior and cover source/tracking scenarios Files changed: .changeset/fn-8673-split-close-issue-comment.md | 7 ++ docs/settings-reference.md | 2 +- docs/task-management.md | 1 + .../task-delete-caller-attribution.test.ts | 32 +++++++ packages/core/src/index.ts | 2 +- packages/core/src/store.ts | 10 +-- packages/core/src/task-delete-attribution.ts | 16 ++++ .../core/src/task-store/archive-lifecycle-2.ts | 14 ++-- packages/core/src/task-store/archive-lifecycle.ts | 6 +- packages/core/src/types.ts | 13 +++ .../src/__tests__/github-tracking-state.test.ts | 98 +++++++++++++++++++++- packages/dashboard/src/github-tracking-state.ts | 82 +++++++++++++++--- packages/engine/src/__tests__/triage.test.ts | 4 + packages/engine/src/triage.ts | 10 +++ 14 files changed, 268 insertions(+), 29 deletions(-) Fusion-Task-Id: FN-8673 Fusion-Task-Lineage: 904c2445-64d9-47b9-b706-f64b23c4e3a6 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
8a6949dd24 |
FN-8661: resolve selected credential instances for sessions
Resolve requested provider credential instances before creating agent sessions. - Thread lane credential instance selections through planning, validation, execution, review, and merge sessions. - Resolve selected instances into runtime credential stores while retaining provider-default fallback behavior. - Preserve selected credentials for mission validation, executor retries, and spawned child agents. Files changed: .../fn-8661-credential-instance-resolution.md | 7 ++ AGENTS.md | 1 + docs/architecture.md | 2 +- docs/secrets.md | 2 + docs/settings-reference.md | 1 + .../dashboard/src/__tests__/routes-auth.test.ts | 80 +++++++++++++++++++ .../dashboard/src/routes/register-model-routes.ts | 78 +++++++++++++++++++ .../src/__tests__/agent-session-helpers.test.ts | 16 ++++ .../credential-instance-resolution.test.ts | 49 ++++++++++++ packages/engine/src/agent-heartbeat.ts | 1 + packages/engine/src/agent-runtime.ts | 9 ++- packages/engine/src/agent-session-helpers.ts | 67 +++++++++++----- packages/engine/src/auth-storage.ts | 90 ++++++++++++++++++---- packages/engine/src/executor.ts | 29 ++++++- packages/engine/src/merger-ai.ts | 2 + packages/engine/src/merger.ts | 5 ++ packages/engine/src/mission-execution-loop.ts | 4 +- packages/engine/src/pi.ts | 7 +- packages/engine/src/pr-response-run-ops.ts | 1 + packages/engine/src/reviewer.ts | 7 ++ packages/engine/src/triage.ts | 2 + 21 files changed, 420 insertions(+), 40 deletions(-) Fusion-Task-Id: FN-8661 Fusion-Task-Lineage: 1e34a3ce-0857-4619-9746-ce0dc12dc2ba Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
13f7266b67 |
FN-8670: reuse model runtime fixtures in engine tests
Share a warmed Pi model runtime across engine catalog tests. - Add an isolated in-memory model registry fixture backed by a per-file shared runtime. - Warm the runtime before catalog tests and verify custom-provider registry isolation. - Document the required fixture pattern for real Pi SDK catalog tests. Files changed: docs/testing.md | 1 + .../engine/src/__tests__/_model-runtime-fixture.ts | 40 ++++++++++++++++++++++ .../custom-providers-openai-completions.test.ts | 15 +++----- .../custom-providers-openai-responses.test.ts | 15 +++----- .../src/__tests__/provider-registration.test.ts | 33 ++++++++++++------ 5 files changed, 73 insertions(+), 31 deletions(-) Fusion-Task-Id: FN-8670 Fusion-Task-Lineage: 7410d114-1853-44cc-a09b-a997fbc7f119 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ebe514c3e4 |
FN-8677: propagate task update lanes before conversion
Propagate cache-warmed workflow lanes through task updates so synchronous engine consumers support renamed boards. - Add task lane cache and attach resolved lanes to task:updated metadata. - Update scheduler, triage, and notification consumers to use carried lanes with bridge-safe fallbacks. - Cover lane propagation and renamed-lane event behavior with core and engine tests. Files changed: .changeset/fn-8677-manual-merge-hold-lanes.md | 7 ++ .changeset/task-updated-carries-lanes.md | 7 ++ ...orkflow-ir-readers-always-return-the-default.md | 22 +++++ .../sync-workflow-ir-second-blocker.test.ts | 43 +++----- .../core/src/__tests__/task-lane-cache.test.ts | 30 ++++++ .../task-updated-lanes-emit-surfaces.test.ts | 92 ++++++++++++++++++ .../__tests__/task-updated-lanes-payload.test.ts | 42 ++++++++ packages/core/src/index.ts | 1 + packages/core/src/store.ts | 36 ++++++- packages/core/src/task-lane-cache.ts | 63 ++++++++++++ .../core/src/task-store/archive-lifecycle-2.ts | 3 + packages/core/src/task-store/moves.ts | 1 + packages/core/src/task-store/task-artifacts-ops.ts | 1 + packages/core/src/task-store/task-update.ts | 1 + packages/core/src/task-store/update-task-deps.ts | 4 +- .../core/src/task-store/workflow-definitions.ts | 71 +++++--------- .../__tests__/scheduler-task-updated-lanes.test.ts | 108 +++++++++++++++++++++ .../task-updated-lanes-bridge-compat.test.ts | 94 ++++++++++++++++++ ...task-updated-lanes-engine-emit-surfaces.test.ts | 101 +++++++++++++++++++ .../src/__tests__/triage-pause-abort.test.ts | 22 +++++ .../src/__tests__/triage-planning-wake.test.ts | 25 +++++ .../notification-renamed-lifecycle-columns.test.ts | 84 +++++++++++++++- .../__tests__/task-wedge-notification.test.ts | 19 ++++ .../src/notification/notification-service.ts | 56 ++++------- packages/engine/src/scheduler.ts | 62 +++--------- packages/engine/src/triage.ts | 105 ++++++-------------- scripts/lib/inert-sync-lane-baseline.json | 5 +- 27 files changed, 858 insertions(+), 247 deletions(-) Fusion-Task-Id: FN-8677 Fusion-Task-Lineage: d8fef9db-0f88-4dfd-9813-be25e10e3588 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
5f12044168 |
FN-8652: add multiple provider credential instances
Enable operators to create, select, and remove named credentials for each supported provider. - Add provider-auth instance discovery and credential mutation endpoints. - Add dashboard authentication controls, status handling, and instance coverage. - Document instance behavior and add a release changeset. Files changed: .changeset/fn-8652-provider-credential-instances.md | 7 + docs/secrets.md | 2 + docs/settings-reference.md | 4 + packages/dashboard/app/api.ts | 1 + packages/dashboard/app/api/provider-status.ts | 94 +++++- .../dashboard/app/components/SettingsModal.tsx | 138 ++++----- .../AuthenticationSection.instances.test.tsx | 75 +++++ .../settings/sections/AuthenticationSection.css | 13 + .../settings/sections/AuthenticationSection.tsx | 199 +++++++----- .../dashboard/src/__tests__/routes-auth.test.ts | 27 +- packages/dashboard/src/routes.ts | 12 +- .../dashboard/src/routes/register-auth-routes.ts | 334 ++++++++++++++++++--- .../src/__tests__/provider-auth-instances.test.ts | 65 ++++ packages/engine/src/provider-auth.ts | 89 ++++++ 14 files changed, 845 insertions(+), 215 deletions(-) Fusion-Task-Id: FN-8652 Fusion-Task-Lineage: 39568d58-7f57-4d17-97cb-1837323b3a94 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
cced31208e |
FN-8672: document observed suite-only flakes
Record first-sighting evidence for three suite-only flakes while preserving their substantial test coverage. - Define the narrow first-sighting observed-register exception and second-sighting quarantine escalation. - Add reproduction data for the core and engine PostgreSQL-adjacent flakes. - Validate register metadata, paths, hierarchy segments, and escalation guidance. Files changed: AGENTS.md | 4 ++ .../suite-only-flakes-observed-register.md | 74 ++++++++++++++++++++++ docs/testing.md | 4 ++ scripts/__tests__/observed-flake-register.test.mjs | 61 ++++++++++++++++++ 4 files changed, 143 insertions(+) Fusion-Task-Id: FN-8672 Fusion-Task-Lineage: b52c74fb-aa7b-49e3-9f1d-a2c8c577f9c7 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
dd569395e8 |
FN-8671: isolate triage admission state in tests
Prevent leaked singleton admission state from affecting later triage polling tests. - Add test-only coordinator reset and inspection seams for all admission categories. - Stop tracked triage processors before clearing shared reservation and pre-held-slot state. - Cover teardown behavior and document singleton-state isolation guidance. Files changed: docs/testing.md | 6 ++ packages/engine/src/__tests__/concurrency.test.ts | 56 ++++++++++++++++ packages/engine/src/__tests__/triage.test.ts | 82 ++++++++++++++++++++--- packages/engine/src/concurrency.ts | 30 +++++++++ 4 files changed, 166 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-8671 Fusion-Task-Lineage: 41217db4-1fd6-45d6-a846-c57fc3c7052e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7334cffebd |
FN-8660: add credential instance selection persistence
Persist optional credential-instance selections across model configuration without changing runtime credential behavior. - Add credential instance IDs to global, project, task, preset, and workflow IR model lanes. - Preserve selected instance IDs through model resolution and task persistence. - Add PostgreSQL migration coverage, unit tests, documentation, and a minor changeset. Files changed: .../fn-8660-credential-instance-selection.md | 7 ++ docs/settings-reference.md | 17 +++++ .../core/src/__tests__/model-resolution.test.ts | 37 ++++++++++ .../credential-instance-selection.pg.test.ts | 81 +++++++++++++++++++++ .../postgres/settings-persistence.pg.test.ts | 83 ++++++++++++++++++++++ .../src/__tests__/workflow-ir-settings.test.ts | 66 +++++++++++++++++ packages/core/src/builtin-workflow-settings.ts | 41 +++++++++++ packages/core/src/model-resolution.ts | 57 ++++++++++++++- .../0039_fn_8660_credential_instance_selection.sql | 9 +++ packages/core/src/postgres/schema-applier.ts | 14 +++- packages/core/src/postgres/schema/project.ts | 4 ++ packages/core/src/settings-schema.ts | 25 +++++++ packages/core/src/store.ts | 2 +- .../core/src/task-store/archive-lifecycle-2.ts | 8 +++ .../core/src/task-store/branch-and-pr-entities.ts | 2 +- packages/core/src/task-store/persistence.ts | 8 +++ packages/core/src/task-store/serialization.ts | 6 ++ packages/core/src/task-store/settings-ops.ts | 30 ++++++++ packages/core/src/task-store/task-creation.ts | 18 ++++- packages/core/src/task-store/task-mutation-ops.ts | 6 +- packages/core/src/task-store/task-row-mappers.ts | 6 +- packages/core/src/task-store/task-update.ts | 24 +++++++ packages/core/src/types/archive-planning.ts | 5 ++ packages/core/src/types/settings-scope.ts | 40 +++++++++++ packages/core/src/types/task-core.ts | 30 ++++++++ packages/core/src/types/workflow-steps.ts | 9 +++ packages/core/src/workflow-ir.ts | 18 +++++ packages/core/src/workflow-settings.ts | 10 +++ 28 files changed, 650 insertions(+), 13 deletions(-) Fusion-Task-Id: FN-8660 Fusion-Task-Lineage: a3f625eb-018c-4084-954e-488b1d37691e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ee77a8d3fa |
FN-8659: preserve custom task specification sections
Preserve custom planning sections while reinjecting the original task description. - Align unmarked original-description bodies before selecting a terminator. - Anchor inserted descriptions before custom H2 sections and retain safe fallback behavior. - Add regression coverage, workflow documentation, and a patch changeset. Files changed: ...fn-8659-original-description-custom-sections.md | 7 ++ docs/workflow-steps.md | 2 + .../__tests__/original-description-policy.test.ts | 114 ++++++++++++++++- packages/core/src/original-description-policy.ts | 135 ++++++++++++++++++--- 4 files changed, 235 insertions(+), 23 deletions(-) Fusion-Task-Id: FN-8659 Fusion-Task-Lineage: 7f047a31-3750-4545-b743-bfac9546c55b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
5596d915ab |
FN-8647: quarantine flaky Kimi K3 catalog test
Quarantine the timing-sensitive Kimi K3 SDK catalog test without changing timeout budgets. - Reuse the native model registry once per test file. - Add the observed CI timeout to the dashboard quarantine ledger and config. - Document validation and timeout-budget preservation requirements. Files changed: docs/testing.md | 8 ++++++++ ...ister-model-routes-kimi-k3-supplemental.test.ts | 23 ++++++++++++++++++++-- packages/dashboard/vitest.config.ts | 8 ++++++++ scripts/lib/test-quarantine.json | 5 +++++ 4 files changed, 42 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-8647 Fusion-Task-Lineage: 31e79677-d923-4003-a8e8-082159334e65 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
182e3fdbe8 |
FN-8651: add named provider credential instances
Add provider-instance identity and auth.json storage for multiple credentials per provider. - Export provider-instance key parsing, validation, and reserved metadata helpers. - Resolve, list, mutate, and select named credential instances atomically in auth storage. - Preserve legacy bare-key hydration and document the auth.json instance contract. - Cover provider instance parsing, storage behavior, and concurrent writes. Files changed: .changeset/fn-8651-provider-instances.md | 7 + docs/secrets.md | 8 + .../src/__tests__/oauth-credential-interop.test.ts | 16 ++ packages/core/src/index.ts | 16 ++ packages/core/src/oauth-credential-interop.ts | 15 +- packages/core/src/provider-instance.test.ts | 24 +++ packages/core/src/provider-instance.ts | 65 +++++++ .../src/__tests__/auth-storage-concurrency.test.ts | 13 ++ .../src/__tests__/auth-storage-instances.test.ts | 75 ++++++++ packages/engine/src/auth-storage.ts | 214 +++++++++++++-------- 10 files changed, 367 insertions(+), 86 deletions(-) Fusion-Task-Id: FN-8651 Fusion-Task-Lineage: cfabe496-60f9-4166-a09f-87ea2028cfd9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
dfe050e8d4 |
FN-8640: add FNXC stamp anomaly advisory
Add a non-blocking census for implausible future-dated FNXC stamps. - Classify tolerated future stamps by timezone plausibility and report notable anomalies. - Add injectable gate seams and coverage for advisory, report, baseline, and discovery behavior. - Document the advisory and preserve read-only check-mode baseline handling. Files changed: docs/testing.md | 4 + scripts/__tests__/check-fnxc-future-dates.test.mjs | 185 ++++++++ scripts/check-fnxc-future-dates.mjs | 495 +++++++++++---------- 3 files changed, 439 insertions(+), 245 deletions(-) Fusion-Task-Id: FN-8640 Fusion-Task-Lineage: 7e57feb0-95e2-46b9-a1cf-9bd93c40d8e0 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
26fdb67505 |
docs(solutions): the audit table had one axis — add the one that missed three defects (#3293)
## What My blind-spot table in #3251 audited **one axis**. Adds the one that missed three defects. Docs only. That table records what each of the five lifecycle ratchets can and cannot **see**. I probed that carefully — several spellings per tool — and then wrote *"nothing found; sound"* for two of them. Within a day, three of those same tools turned out to share a completely different defect: **they wrote to the tree they were checking**, auto-tightening their own baseline during a plain check run. | gate | wrote during a check | fixed by | |---|---|---| | `check-fnxc-future-dates` | yes | #3287 | | `lifecycle-column-census` | yes, under `--strict` | #3289 | | `check-sql-column-literals` | yes | #3292 | **No number of detection probes could have surfaced that.** The table asserted one property carefully and said nothing about the other *while reading as comprehensive* — which is precisely the failure it documents in the tools it audits. ## The rule it adds 1. **What can it see?** — probe each spelling of the thing it claims to catch. 2. **Can it fail at all?** — invoke it as `package.json` does; a report-only run exits 0 forever (#3255). 3. **Does it write?** — `git status --porcelain` before and after, on a clean tree. With the trap on the third spelled out: these gates write only when a tightening is **available**, so a clean tree after a run proves the *trigger* is absent, not that the tool is read-only. Inflate a baseline entry first, then run it. I hit exactly this while reviewing #3292 — ran all three gates on main, saw a clean tree, and had to stop myself concluding the SQL gate was fine. ## Why the pattern, not the people Three tools converged on write-during-check independently. That argues the design is **attractive**, not that three authors were careless: the tightening is correct, the write saves a step, and the message even tells you to commit it. It only becomes a defect at the moment a second person runs the same gate — which is invisible from inside any one of them. What it cost, measured: #3283 and #3285 are the same `+0/-1`, five minutes apart, by two authors, **neither of whom wrote that line**. ``` lint clean; fnxc-future-dates clean ``` |
||
|
|
5efe97c0ae |
docs(solutions): your environment is a variable in every measurement you report (#3291)
Extends the doc from #3255/#3273 with the failure that cost the most in a single session: **one stale install produced five wrong reports on one issue** (#3264). ## What happened A `node_modules` that had drifted from the lockfile — `jsdom@29.0.1` installed, `29.1.1` pinned — generated failures that existed on no CI machine and no other checkout. They were not subtle: deterministic, reproducible on demand, with plausible stack traces and real-looking assertion diffs. Each round of triage got **more precise about the wrong data**: | round | claim | why it was wrong | | --- | --- | --- | | 1 | "4 deterministic failures" | measured in a 4-file batch, called it isolation | | 2 | "3 deterministic, 2 order-dependent" | isolated correctly, but a race is not deterministic | | 3 | "TaskCard is broken" | stale jsdom; the CSS assertion was correct | | 4 | "no contamination" | true of four app files; published unqualified | | 5 | "quarantine these two" | never read the failure text — both were timeouts | The through-line is not carelessness about the code. **The environment was never treated as part of the claim**, so no amount of care about the analysis could recover it. ## The checks, in the order they cost the most ```bash pnpm install --frozen-lockfile # node_modules is not evidence until it matches the lockfile <run the file ALONE, 3+ times> # isolation and repetition answer different questions <read the failure TEXT> # a timeout and an assertion failure need opposite responses uptime # a loaded box manufactures timeouts that mean nothing ``` ## Why the load check earned its place Two tests "failing" in a full-suite run were `Test timed out in 15000ms` on a box at **load average 9.7 with 84 users**. Under AGENTS.md's quarantine-on-sight rule that reads as a flake to quarantine — and the ledger's **14-day deletion ratchet would have made the lost coverage permanent**. The rule presumes the failure is a property of the test, not of the machine. A wall-clock budget crossed under local contention is evidence about the hardware. I was one comment away from deleting healthy coverage on that basis. ## The tell A finding is environment-derived when it is **local, recent, and unshared**: nobody else has reported it, CI is green, and it appeared without a commit that could explain it. Any two of those should stop a report before it is written. All three applied here, and the report went out anyway — five times. ## Verification Docs only; no code paths change. `fnxc-future-dates`, `lifecycle-columns`, `quarantine-ledger` exit 0. No changeset — internal docs are excluded. Context: the one finding in #3264 that survived all five rounds is #3286 (merged), and it survived because it was verified by **reverting the product change** rather than by trusting a red — 3/3/2 failures without the fix, 27/27 across four runs with it. |
||
|
|
f2f6795010 |
FN-8635: keep worktree slider visible
Keep Command Center capacity controls visible and correctly editable across settings states. - Render Max worktrees in the shared full-width range wrapper. - Preserve capacity values after load failures and explain disabled worktree limits. - Add control tests, browser geometry coverage, documentation, and a release changeset. Files changed: .changeset/fn-8635-worktrees-slider.md | 7 + docs/dashboard-guide.md | 2 +- .../command-center/CommandCenterControls.css | 6 + .../command-center/CommandCenterControls.tsx | 63 +++++--- .../__tests__/CommandCenterControls.test.tsx | 76 ++++++++- packages/engine/e2e/fn-8635-worktrees-slider.mjs | 180 +++++++++++++++++++++ 6 files changed, 310 insertions(+), 24 deletions(-) Fusion-Task-Id: FN-8635 Fusion-Task-Lineage: fb9c2a46-3c5c-4871-bab4-c43af20cb4de Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
475bb2d641 |
FN-8637: restrict Quick Add Start to manual-intake workflows
Restrict Quick Add Start eligibility to verified manual intake lanes. - Require the server-derived manualIntake flag instead of hold alone. - Preserve Coding Ideas routing while hiding Start for Coding's merged planning lane. - Cover desktop and mobile eligibility behavior and document the updated rule. - Add a patch changeset for the corrected workflow gating. Files changed: .changeset/fn-8637-quick-add-start-manual-intake.md | 7 ++++ docs/dashboard-guide.md | 2 +- packages/dashboard/app/components/QuickEntryBox.tsx | 21 ++++++------ packages/dashboard/app/components/__tests__/Column.test.tsx | 20 ++++++++--- packages/dashboard/app/components/__tests__/ListView.test.tsx | 40 ++++++++++++++++++---- packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx | 21 +++++++++--- packages/dashboard/app/utils/__tests__/quickAddStart.test.ts | 38 ++++++++++++++++++-- packages/dashboard/app/utils/quickAddStart.ts | 9 ++++- 8 files changed, 128 insertions(+), 30 deletions(-) Fusion-Task-Id: FN-8637 Fusion-Task-Lineage: 9652d7d8-f954-49e8-9a76-a2421654baae Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
95410b5de6 |
FN-8638: add Factory Light dashboard theme
Add a daylight industrial theme that persists across dashboard and desktop startup. - Register Factory Light in persisted theme types, selectors, and bootstrap validators. - Define Factory Light tokens and preview swatches for light and dark modes. - Cover theme registration and rendered token contracts, and document the new option. Files changed: .changeset/fn-8638-factory-light-theme.md | 7 ++ docs/dashboard-guide.md | 3 +- docs/settings-reference.md | 2 +- packages/core/src/types/execution-and-ui.ts | 2 + .../app/__tests__/factory-light-theme.test.ts | 106 +++++++++++++++++++++ .../dashboard/app/components/ThemeSelector.css | 14 +++ .../components/__tests__/ThemeDropdown.test.tsx | 2 +- .../components/__tests__/ThemeSelector.test.tsx | 2 +- .../__tests__/CommandCenterControls.test.tsx | 2 +- packages/dashboard/app/components/themeOptions.ts | 1 + packages/dashboard/app/index.html | 2 +- packages/dashboard/app/public/theme-data.css | 86 ++++++++++++++++- packages/desktop/src/renderer/index.html | 1 + 13 files changed, 223 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-8638 Fusion-Task-Lineage: 3b78bc31-0f03-4299-8f5f-1a69ac7c604a Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
29eb512d57 |
docs(solutions): the general shape — a green that answers a different question (#3273)
Extends the doc merged in #3255 with two more instances of the same pattern, both found this session, **neither involving a ratchet**. Four instances now, from four unrelated directions: | what was read as "pass" | what the green actually meant | | --- | --- | | `node scripts/check-*.mjs` exits 0 | report-only mode — the failure path needs `--strict` | | a census reports 0 for a new file | the file is untracked, so it was never scanned | | a backgrounded `cmd > log; grep …` reports exit 0 | that is `grep`'s status; the suite inside had 8 failures | | a rebased branch's tests pass | the rebase never started, so it ran on the **old** base | The two new ones are worth writing down because they are not about tooling anyone built here — they are about how results are read. **Exit codes belong to the last command in the pipeline.** A backgrounded `run_tests > log 2>&1; echo done; grep X log` exits with `grep`'s status, so the harness reported "completed, exit code 0" for a dashboard suite that had 8 failures. I nearly recorded that suite as green. Read the summary out of the log; never infer a suite's result from a wrapper's exit code. **A failed rebase leaves you on the old base, and the tests still pass there.** `git rebase` refused with `cannot rebase: You have unstaged changes`, so the branch never moved. `git diff origin/main` then listed 20+ files including other workers' commits — which reads exactly like my branch had reverted their work — and a full test run on that tree came back green. Both signals were true about a tree nobody cared about. ``` git merge-base --is-ancestor origin/main HEAD ``` said STALE while the tests said pass. That is the only check that separates the two, and it belongs before any claim of "verified on current main". The shared tell, stated once: **a result too clean, or too alarming, for what changed.** Every probe shape passing including ones that obviously should not; a two-file branch appearing to revert twenty. When the answer does not fit the size of the question, find out what was actually measured before believing it. ## Verification Docs only; no code paths change. `lifecycle-columns`, `move-target-literals`, `inert-sync-lanes`, `quarantine-ledger` all exit 0. No changeset — AGENTS.md excludes internal docs. **Pre-existing red, not from this branch:** `check:fnxc-future-dates` currently fails on main from a `2026-08-01-00:50` stamp in `packages/core/src/task-store/lifecycle-ops.ts` (commit `e52da740a5`) — a timezone-ahead clock writing tomorrow's date, at 23:45 UTC. Already claimed by **#3269 and #3270**, so I have not touched it; flagging only so this branch's CI result is not misattributed. It is the same recurring class this doc's sibling rule addresses: take the stamp from `date -u`, not the local clock. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added guidance for identifying misleadingly successful CI and test results. * Documented checks for report-only runs, untracked files, masked failures, and tests running on an outdated code base. * Included recommendations for reviewing logs and verifying branch ancestry. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d14294b6cb |
docs(solutions): add the count-based probe, which the report-only trap cannot fool (#3257)
## What Adds one technique to #3255. Docs only. #3255 records that probing a ratchet **by exit code** can read green because the tool is report-only without `--strict` — a real trap that nearly got a healthy gate reported as dead. There is a second technique that sidesteps it entirely and is strictly more informative: **parse the tool's own per-file count.** ```bash node scripts/check-move-target-literals.mjs 2>&1 | grep -a "my-probe-tmp" \ | grep -aoE "^ +[0-9]+" | tr -d ' ' ``` **Immune to the report-only trap** — a report-only run still *prints* the count, so the number moves 0 → 1 whether or not `--strict` was passed. **It measures which shapes, not just whether something fired.** An exit code is one bit for the whole run. Auditing a detector means asking *"of these five spellings, which are seen?"*, and five separate binary runs cannot distinguish **partial** detection from a probe file that failed to compile. The move-target audit read `direct 1 / backtick 1 / ternary 0 / const 0` in a single run, which named the gap immediately. ## Both belong | question | technique | |---|---| | **can this ratchet fail at all?** | `pnpm check:*` — ask this first (#3255 §1) | | **what can it see?** | per-file counts — an exit code is too coarse | I also added a caveat that applies to both: confirm the probe is actually being scanned by watching the tool's **scanned-file total** move. A probe that never compiled and a probe the tool never discovered both report zero hits, and neither is a finding — that one cost me a wasted measurement before I noticed the total had stayed at 1961. ## Why this is worth a follow-up rather than a comment #3255's rule as written — *"use `pnpm check:*`, not a bare `node scripts/...`"* — would have made the shape-coverage audits impossible, since `--strict` collapses five distinct per-form answers into one bit. The rule is right for its question and wrong for the other one, and the distinction is easy to lose once only the rule survives in someone's memory. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added guidance for evaluating ratchets using per-file output counts. * Documented report-only and shape-coverage limitations, count-based versus failure-based checks, and verifying that probe files were scanned. * Included a command example for probing ratchet behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
37d891e879 |
FN-8633: improve tablet terminal dragging
Give floating tablet terminals a dedicated drag grip while preserving tab-strip panning. - add a touch-sized tablet-only header drag grip and pop-out hit target - preserve floating geometry at the tablet breakpoint and document the gesture - cover grip availability, dragging, and horizontal tab-panning CSS isolation Files changed: .changeset/fn-8633-tablet-terminal-drag.md | 7 ++ docs/dashboard-guide.md | 4 +- packages/dashboard/app/components/TerminalModal.css | 61 +++++++++++++ packages/dashboard/app/components/TerminalModal.tsx | 16 ++++ packages/dashboard/app/components/__tests__/TerminalModal.test.tsx | 99 ++++++++++++++++++++++ 5 files changed, 185 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-8633 Fusion-Task-Lineage: f1c442a8-3302-4f6a-98e9-f1efa4083c12 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
9690f46439 |
docs(solutions): probe the instrument the way CI runs it (#3255)
Records two instrument-level defects found this session. Both were in the tools the program uses as ground truth, and both looked exactly like a pass. ## 1. A ratchet that could not fail from the command I typed `check-move-target-literals` is report-only unless given `--strict`, which `package.json` supplies. Probed bare, it returned **exit 0 for every probe** — including a blatant `moveTask(id, "in-review")` pasted into `scheduler.ts`. That is the exact signature of a dead ratchet, and I nearly reported another worker's guard as inert on the strength of it. The guard was fine; my invocation could not fail. What makes it dangerous is the output: a report-only run prints its normal summary line and exits 0, so the terminal is indistinguishable from a genuine pass. ## 2. A ratchet that could not see the file I had just written `lifecycle-column-census` and `check-move-target-literals` discovered files with `git ls-files` — **tracked only** — while the other five walk the filesystem. | new file with a plain legacy guard | result | | --- | --- | | same guard in an already-tracked file | caught | | new file, untracked | **missed, exit 0** | | identical file, `git add`ed | caught, exit 1 | The detectors are fine. The blindness is discovery, and it lands at the one moment the number is consulted: add a helper, check your own work, read zero, commit — and it surfaces later in someone else's CI run, attributed to a push instead of to the edit. The tool was answering about the last commit while being asked about the working tree. ## 3. Why it is worth a doc rather than two one-line fixes Individually these are cheap. Together they cost a day. Because `check-inert-sync-lane-conversions` walks the filesystem and the census did not, the **same probe file** was caught by one and missed by the other. I read that differential as a claim about expression walking and investigated it as one — the real cause was that two instruments in the same program disagreed about which files exist. When the measuring tools disagree about their own domain, every differential between them is unreadable until someone notices. That is the transferable lesson, and it is not visible from either fix alone. ## Status of the fixes - Census discovery scope: **#3254** (open). - Type-assertion blind spot in the sync-lane ratchet: **#3252** (open). - `check-move-target-literals` discovery scope: reported to **#3253**, whose author is already in that file — not touching it. ## Verification Docs only; no code paths change. All eight ratchets exit 0. No changeset — AGENTS.md excludes internal docs. |
||
|
|
59dfc4678b |
docs(solutions): record what each lifecycle ratchet cannot see, measured (#3251)
## What This note already prescribes: *"Before trusting a ratchet: mutate the shape it claims to catch and confirm it exits non-zero."* This is that checklist item **executed against all five lifecycle gates** on one tree, one staged probe file per form. Docs only. **Two of the five were wrong.** | gate | catches | does NOT catch | |---|---|---| | `lifecycle-column-census` | `===` / `!==` | ~~membership, switch~~ **fixed (#3247)** | | `check-move-target-literals` | direct + backtick destinations | ~~ternary~~ **fixed (#3250)**; still misses a destination bound to a local | | `check-sql-column-literals` | `"column"` comparisons — **including plain template literals**, not only drizzle `sql` tags | nothing; the one miss probed was an identifier the schema never uses | | `check-inert-sync-lane-conversions` | lane reads via the `resolvePlannerLanes` helper | a **direct** `store.resolveTaskWorkflowIrSync(...)` read feeding `resolveLifecycleColumns` — inert by the same mechanism, untracked | | `check-fnxc-future-dates` | future stamps | nothing — it caught this table's author, twice | ## The two lessons the table encodes **A ratchet's blind spot is invisible in exactly the way its subject is.** Both fixed gaps sat next to a printed zero *and a sentence promising nothing could land silently*. The count was true. The sentence was true only for the forms the parser happened to visit. That is the same shape as the conversions this program spent weeks finding — code that looks converted because the instrument cannot see the difference. **Probe correctness is its own trap.** The first census probe measured nothing: the scanner enumerates git-tracked files, the probe was untracked, and the scanned-file count staying flat reads *exactly* like "no gap". A `DELIBERATE-LITERAL` probe likewise read as a broken escape hatch until the marker moved to its own line — mid-expression it attaches to the wrong node, which is the documented gotcha, and it still caught the person who had just written it down. ## Reported, not fixed The inert-sync gap is left open deliberately: it is one narrow shape, the only in-tree instance (`replan-target.ts:95`) is documented, new conversions would use the tracked helper, and that gate has uncommitted work from another worker. Recording it beats editing a file someone else is mid-change on. ``` lint clean; fnxc-future-dates: none added; all five gates --strict green on this tree ``` |
||
|
|
bcaa48390b |
FN-8627: add Sage color theme
Add the Sage palette across persisted dashboard and desktop theme selection paths. - Register Sage in core, dashboard bootstrap, desktop, and selector metadata. - Add dark and light Sage tokens plus independently resolvable swatches. - Cover registration, token, selector, and documentation updates. Files changed: .changeset/fn-8627-sage-theme.md | 7 ++ docs/dashboard-guide.md | 3 +- packages/core/src/types/execution-and-ui.ts | 2 + .../dashboard/app/__tests__/sage-theme.test.ts | 101 +++++++++++++++++++++ .../dashboard/app/components/ThemeSelector.css | 14 +++ .../components/__tests__/ThemeDropdown.test.tsx | 2 +- .../components/__tests__/ThemeSelector.test.tsx | 2 +- .../__tests__/CommandCenterControls.test.tsx | 2 +- packages/dashboard/app/components/themeOptions.ts | 1 + packages/dashboard/app/index.html | 2 +- packages/dashboard/app/public/theme-data.css | 86 +++++++++++++++++- packages/desktop/src/renderer/index.html | 1 + 12 files changed, 217 insertions(+), 6 deletions(-) Fusion-Task-Id: FN-8627 Fusion-Task-Lineage: fd4353b3-1e0c-4c7e-84dd-bcad2815178c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
478b15d7ec |
docs(solutions): add the CI failure-rate method, and a fourth instance (#3244)
## What Follow-up to #3243. That note said *"take a second measurement of a different kind"* — true, and useless at 2am without the technique. This adds the one that actually settled every case, plus a fourth instance that occurred after #3243 was written. Docs only. ## The technique Enumerate recent failing CI runs and compute a **per-file failure rate**. Seven runs separated three populations that are indistinguishable from a single local run: | rate on CI | meaning | action | |---|---|---| | **7/7** | consistent, real | fix, or diagnose and hand off with evidence | | **1/7** | intermittent | flake or race; two in one subsystem is a product-race smell | | **0/7** (fails only locally) | environment | fix your sandbox, change **nothing** in the repo | Measured on this repo's main while writing it: `planning-browser-e2e` **7/7**, `postgres/schema-applier` **1/7**, `report-store.pg` **1/7**. ## The fourth instance #3243 documented three reversals. A fourth happened after it merged: a component test with **2 failing cases locally, 0/7 on CI**. That makes **three separate local-only failures in a single session** — a model-routes test hanging offline, a component test with four failing cases, and a set of assertions I was ready to call a regression. Each felt like a finding. All three were my sandbox. That is frequent enough to be a habit rather than bad luck, which is why it is worth a row in a table rather than a mention. ## The cost asymmetry, which should drive the default Acting on a **0/7** by quarantining **deletes coverage that is green everywhere else**. Acting on a **7/7** by investigating costs an hour. The errors are not symmetric, so when unsure which row you are in, the cheap move is always more samples from the *other* environment — not more confidence about the one you have. This is the concrete form of the point the standing quarantine rule already encodes with *"without a corresponding real bug"*: **"I saw it fail" is not that clause**, and the failure-rate table is how you tell the difference before acting. ``` lint clean; fnxc-future-dates: none added (exit code checked before piping) ``` |
||
|
|
5365746d37 |
docs(solutions): record "one sample is not a diagnosis" (#3243)
## What A `docs/solutions` note recording three diagnoses I reversed **in one session**, all wrong the same way. Docs only. ## The three | observed | my story | what it was | |---|---|---| | `planning-browser-e2e` fails at width **769**, passes at **768** | layout regression at the tablet breakpoint, from FN-8606 | a **race** — 5 passes in 6 runs; on every pass the control sits inside the viewport at 769 (`right: 753 ≤ 769`) | | a model-routes test fails **3 of 3** locally | red on main; quarantine candidate | **green on CI**; a sandbox interaction. The fixture is configured offline, so a sandbox should not have changed the outcome — the tell was there from run one | | one approach could not cover a resolver | the site is **unpinnable** | a *different shape* covered it — a helper that **resolves** rather than one that **receives** | Each was plausible, mechanistic, and consistent with the evidence I had. That is what made each dangerous: **a diagnosis that explains your one data point feels finished.** Each survived exactly until a second measurement **of a different kind** — another environment, more samples, an instrumented probe. Re-running the same command is not a second measurement. ## The reusable part | observation | tempting story | check first | |---|---|---| | fails at boundary X, passes at X−1 | structural bug at the boundary | run it 5 more times — boundaries are where races surface | | **consistent** locally, green on CI | main is broken | the environment; consistency is not universality | | **intermittent** locally, consistent on CI | flaky test | a race the slower runner loses every time | | one approach failed | the site cannot be done | whether a different *shape* of the approach works | ## Why it matters beyond debugging hygiene Two of the three would have caused real damage if acted on: - Quarantining the model-routes test — the action the standing rule seems to license on "observed failing" — would have **deleted coverage that is green everywhere else**. The rule's *"without a corresponding real bug"* clause is load-bearing, and a local observation does not satisfy it. - "Unpinnable" hardened a single failed approach into a property of the site. Left standing, it becomes a permanent excuse not to look — the same failure I corrected in an inherited note earlier today, which had recorded four resolvers as unmeasurable for environment reasons that did not hold here. Hence the last rule: **record cautions as environment-scoped, not as properties of the code.** Say where you measured. ``` lint clean; fnxc-future-dates: none added (exit code checked before piping) ``` |
||
|
|
24ef266e48 |
FN-8628: add Factory Dark dashboard theme
Add a low-light industrial dashboard color theme with first-paint support and release documentation. - Register Factory Dark across persisted theme types, selector metadata, and desktop/dashboard bootstrap validators. - Define dark and light Factory Dark tokens, swatches, and selector styling. - Cover theme registration, tokens, bootstrap behavior, and UI theme-option counts. - Add a minor @runfusion/fusion changeset and document the theme. Files changed: .changeset/fn-8628-factory-dark-theme.md | 7 ++ docs/dashboard-guide.md | 3 +- docs/settings-reference.md | 2 +- packages/core/src/types/execution-and-ui.ts | 2 + .../app/__tests__/factory-dark-theme.test.ts | 106 +++++++++++++++++++++ .../dashboard/app/components/ThemeSelector.css | 14 +++ .../components/__tests__/ThemeDropdown.test.tsx | 2 +- .../components/__tests__/ThemeSelector.test.tsx | 2 +- .../__tests__/CommandCenterControls.test.tsx | 2 +- packages/dashboard/app/components/themeOptions.ts | 1 + packages/dashboard/app/index.html | 2 +- packages/dashboard/app/public/theme-data.css | 86 ++++++++++++++++- packages/desktop/src/renderer/index.html | 1 + 13 files changed, 223 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-8628 Fusion-Task-Lineage: 6f3c7cd9-0130-482d-8aa8-ca47d48b134f Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
851369a480 |
docs(solutions): record "silence is not success" (#3241)
## What A new `docs/solutions` note recording a failure that hit **three different tools in one session**, each time reading as a pass. Docs only. ## The three costumes | what happened | looked like | was | |---|---|---| | `git stash --keep-index` swept the new test file out of the tree | "45 passed" | the pre-existing count; the new test never ran | | a blinding script hit an unmapped role and `sys.exit(2)` **with no message**; `&&` skipped the check, `;` let the run proceed | "375/375 green under blinding" | nothing blinded — run was against unmodified source | | a gate piped to `tail -1`, printing a blank line | "gate ran, no complaints" | exit code 1; the FNXC stamp check had failed, and **CI caught it in #3238** | ## Why it deserves its own note **A passing run and a run that never happened produce the same evidence: no failure text.** Every other bug announces itself; this one is defined by the absence of an announcement. The instinct that catches ordinary bugs — *"nothing looks wrong"* — is precisely the instinct that certifies this one. It gets worse under automation, where output is piped and skimmed. `| tail -1`, `| grep "Tests"`, `>/dev/null 2>&1` all discard the part that would have said `No test files found` or `command not found`. ## The five rules, each paid for above 1. **Assert the exit code before any pipe.** A pipeline's status is the *last* stage's — `cmd | tail -1` reports `tail`'s success, never `cmd`'s. 2. **Confirm the run did the work.** "Test Files 1 passed" when you expected 16 is a finding, not a pass. 3. **A tool that can no-op must say what it did** — print the substitution and location, fail loudly where it cannot act. 4. **Verify the mutation, not the tool's promise** — `git diff --stat`, not the exit code. 5. **Break the guard on purpose once** and watch it fail. A guard never observed failing has not been shown to work — the standard this repo already applies to product ratchets, turned on your own verification. ## The uncomfortable part, kept in The third instance was a rule **I added to AGENTS.md myself in #3174**, broken for the second time. I ran the gate. I read `tail -1`. I moved on. Writing a rule down does not make you follow it. The only reason it was caught is that **CI read the output when I did not** — an argument for the gate existing, not for me having been careful. Cross-linked from the resolver-audit note, whose every wrong reading came from a run that never happened rather than from the blinding itself. That connection is the point: I spent this session auditing a program whose subject is defects hiding behind green results, and reproduced the same class three times in my own tooling. ``` lint clean; fnxc-future-dates: none added (exit code checked before piping this time) ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added workflow guidance explaining why silent or seemingly successful output does not confirm that a test, script, or validation gate ran. * Documented verification practices including checking exit codes, work counts, no-op detection, post-run changes, and intentional failure checks. * Added a case study highlighting how filtered output can conceal verification failures. * Added cross-references connecting resolver interpretation, test execution, and conversion coverage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
4bcaddafc5 |
docs: index workflow-owned-lifecycle-closing-verification.md in Audit Reports
Found during routine docs orphan scan. The file (added 2026-07-30,
commit
|
||
|
|
05f09c29f8 |
docs(solutions): complete the repo-wide resolver audit; correct a superseded note (#3236)
## What Completes the repo-wide resolver audit and **corrects a note of mine that had gone stale**. Docs only. Every `resolveProjectColumnsForRoles` call site in the repository has now been blinded individually. ## Final results | package | sites | outcome | |---|---|---| | `engine` | 10 files | scheduler, triage, evaluator uncovered → pinned; executor, restart-recovery, notification already covered; self-healing 21 pinned / 1 inert | | `core` | 14 | 9 covered, **5 uncovered → all 5 pinned** (#3225, #3227, #3233, #3234, #3235) | | `dashboard` | 4 | `register-task-workflow-routes.ts:1268` covered; `server.ts` ×3 flagged | | `cli` | 1 | flagged | ## The correction A note recorded `workflow-analytics.ts` and `team-analytics.ts` — 4 resolvers — as **unmeasurable**, because `pgDescribe` probes TCP and the `.pg` suites skip without it. The caution is real and stays: a skipped suite reads exactly like a passing one. But on an environment where those suites **do** run, all 4 were measured, and `team-analytics.ts` turned out to have a half-covered pair — `completeLanes` covered, **`activeLanes` not** — in a file named `team-analytics-renamed-lanes`. That is now pinned (#3227, merged). Left standing, the note converts a real finding into a **permanent excuse for not looking**. It now says: confirm the suite actually skips *here* before recording a site as unmeasurable for environment reasons. ## A fourth measurement failure mode — the opposite direction The three already recorded all produce false *uncovered*. This one produces false *covered*: **A COVERED verdict needs a baseline.** The dashboard sweep reported 5 failing files under the global blind. **4 of them fail on clean `main`** and have nothing to do with lanes — a docs-inventory test and a model-routes test among them. Read as-is, that is four resolvers falsely credited as covered. Only `register-task-workflow-routes.awaiting-planning.test.ts` passes clean and fails blinded, so it is the sole real detector. Second time today a baseline changed a conclusion (the first found a genuine red on main, #3229). ## Why 4 sites are flagged rather than pinned - **`server.ts:1922/1923/1938`** — inside the `/api/health/reliability` route closure. No route-level test exists, and the only way in is booting `createServer(store)` behind a mock-the-world shell, which the slow-test rule forbids. The alternative is a refactor to expose a seam — its own commit, since moving code and changing behaviour do not ride together. (A note already in this doc reached the same conclusion independently; this confirms it by measurement.) - **`cli/commands/task.ts:660`** — worth its own warning. Extracting a pure helper and testing it **would look like coverage and would not be**: blinding the resolver leaves such a test green, because the helper *receives* the lane set rather than resolving it. The uncovered thing is the resolve call, not the decision it feeds. Its sibling test file already records the same limit honestly for `boardColumnsForDisplay`. ## Reported, not fixed: 4 pre-existing red dashboard files on main `lazy-loaded-views-docs.test.ts` (AGENTS lazy-view inventory drifted — 24 actual vs 18 documented), `ResearchView.test.tsx`, `planning-browser-e2e.test.ts`, `register-model-routes-kimi-k3-supplemental.test.ts` — 7 failing tests, all in the non-blocking suite. I am not fixing them here: the lazy-views inventory is a curated list other workers are actively adding to, and rewriting it mid-flight would collide. Flagging so it is visible rather than silently absorbed into my blind's noise. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated workflow guidance to require baseline comparisons and verification that all relevant tests run. * Added safeguards for detecting ineffective changes and distinguishing pre-existing failures. * Expanded PostgreSQL audit documentation with measured coverage results, including uncovered resolver paths. * Recorded completed coverage sweeps across core, dashboard, and CLI areas, including pinned and non-pinnable sites. * Clarified limitations when testing extracted decision helpers instead of resolver calls. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
01ab2400d0 |
docs(learnings): blinding measures the instrument you picked — rule 5, and where the measurement cannot be taken (#3222)
Extends `blind-the-resolver-to-find-uncovered-conversions.md` rather than forking a second doc on the same technique. ## Rule 5: blinding measures the instrument you picked, not the site A suite that never reaches the blinded site reports `0 failed` for the same reason a covered one does. The outputs are identical. This produced a **wrong answer twice in one sweep**, both times reading as a finding: | blinded | suite run | said | actually | |---|---|---|---| | `reads.ts` ×3 | `search-excludes-renamed-archive-lane.test.ts` | 3 uncovered | that file unit-tests `liveSearchPredicate` and never runs `reads.ts`; against `cold-storage-renamed-archive-lane.test.ts` one of the three is covered | | `server.ts` ×3 | `reliability-metrics.test.ts` | 3 uncovered | that file imports `../reliability-metrics`; nothing executes the route at all | The `reads.ts` case is the one to remember, because **the misleading suite was written for that exact conversion**. It proves the collaborator honours a resolved set — which says nothing about whether the caller passes one, and can never fail when the call site is blinded. That gap shipped as a real hole and was closed in #3220. Doc adds the cheap guard: make the blinded edit obviously fatal (`throw new Error("x")`) and re-run. Still green means the suite does not reach the site and the measurement is void. ## Where the measurement cannot be taken Per #3212's stance that recording *why* something cannot be pinned is a result, three groups are written down so nobody re-derives them: - **No TCP PostgreSQL** — `workflow-analytics.ts` / `team-analytics.ts` (4 resolvers) keep renamed-lane coverage in `.pg` suites. `pgDescribe` probes **TCP**; `pg_isready` succeeding on a **Unix socket** is not the same thing. I made exactly this mistake and reported PG as reachable one round before correcting it — mistaking the two turns 4 skipped suites into 4 false "uncovered" readings. - **No injectable seam** — `reads.ts`'s incremental-sync scan composes Drizzle conditions against `layer.db`. A test there asserts the query built, not the rows excluded: green, and blind to the bug. - **Logic inside a route closure** — `server.ts`'s three resolvers sit in the `/api/health/reliability` handler, which has no route-level test. The only harness in that package is a mock-the-world shell the slow-test rule forbids; the alternative is a refactor to expose a seam, which is its own commit. ## Census **Unchanged — `CONVERSION QUEUE EMPTY`, `AVAILABLE: 0`.** Documentation only. Gates verified green (`check-fnxc-future-dates`, `lifecycle-column-census --strict`). No changeset: internal docs, per AGENTS.md. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added guidance for verifying the test instrument used during blinding. * Documented fatal-edit reachability checks. * Added troubleshooting guidance for situations where resolver coverage cannot be measured. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
206ff11874 |
docs(solutions): record the blinding audit's own failure modes (#3223)
## What Extends `docs/solutions/workflow-learnings/blind-the-resolver-to-find-uncovered-conversions.md` with what this session's audit work paid for. Docs only — no code, no changeset (internal doc). ## The main addition: the audit's own failure modes **Every wrong reading this method has produced came from test *selection*, not from the blind.** Three in one session, each of which reads exactly like coverage: | what I ran | why it lied | |---|---| | `vitest run src/__tests__ -t "executor"` | `-t` filters test **names**, not files. Reported two `executor.ts` resolvers uncovered; **both are covered.** | | `blind3.py <file> <var>` with an unmapped role | exited non-zero **silently**; `&&` skipped the check and `;` let vitest run against **unmodified source**. Reported "375/375 green under blinding" with nothing blinded. | | `vitest run src/__tests__/notification` | missed `src/notification/__tests__/` — a nested `__tests__` the glob never reached. Reported covered code as uncovered. | The rule that follows: an UNCOVERED verdict is a claim about the whole tree and needs the whole tree's tests. Confirm the blind actually modified the file with `git diff --stat` — *not* the tool's exit code — and that the run included every file importing the module. I am documenting my own instrument failing the standard I have been applying to product guards all phase: *a guard that reports success without checking anything is worse than no guard.* Mine reported success without checking anything. It now echoes what it substituted and where, and fails loudly on an unmapped role or missing variable; I self-tested both directions before trusting any number in #3219 and #3221. ## Rule 5: the resolver must be able to answer differently in the harness `resolveProjectColumnsForRoles` returns **legacy ids and nothing else** when the store has no `listWorkflowDefinitions` — an intentional degrade so an unreadable workflow list cannot fail a sweep. A harness omitting it makes the resolved set and the literal set **equal by construction**, so the conversion is unobservable however good the assertion is. This is not a test bug. It is correct production behaviour that erases the difference the test is trying to measure — and it alone left both the `scheduler.ts` and `triage.ts` conversions unpinnable. ## A correction to my own earlier rule I had "seed-then-union sites hide defects" too broad. Such a site hides a defect **only while every lane you assert on is already in the seed**. On a renamed board the resolver is the sole contributor of the renamed lane, so the legacy blind is *not* a no-op — I predicted it would be and it failed. Also: expand roles to legacy ids **per role** from `LEGACY_COLUMN_IDS_BY_ROLE`; `intake` is `["todo","triage"]`, not `["triage"]`, and a stricter-than-real blind manufactures failures that read as coverage. ## Inventory, so the gap is legible **116 non-test call sites across 30 files** — core 17, engine 10, dashboard 2, cli 1. Audited so far, all in engine: `self-healing.ts` (64 mapped / 21 pinned / 1 inert by construction), `executor.ts` (2, covered), `scheduler.ts` (uncovered → pinned in #3219), `triage.ts` (uncovered → pinned in #3221), `restart-recovery-coordinator.ts` (covered), `notification-service.ts` (covered). **`packages/core`'s 17 files are entirely unaudited.** Stated as a gap rather than left implied, so nobody reads engine's coverage as a repo-wide clean bill. ## Flagged, not guessed - `evaluator.ts`'s archived read is uncovered — **no test file imports that module at all.** Left unpinned deliberately: it is a thin pass-through into `collectDeterministicSignals`, which is testable directly, and it affects eval signal quality rather than task lifecycle. Recorded in the doc rather than silently skipped. - I did not audit core; it is outside my package and I am not claiming anything about it either way. |
||
|
|
2868eb4797 |
docs(learnings): blind the resolver to find uncovered conversions (#3214)
Sibling to #3203 (`a-falling-count-is-not-evidence`), which records that a metric moving is not proof the system moved. **This is the positive procedure**: how to find out whether a landed conversion is held by anything, and how to write a test that holds it. ## The measurement it is written from Of **64 resolved lane sets in `self-healing.ts`, 26 had no test that could distinguish them from the literal they replaced** — including three conversions I shipped that same day, and two halves of sweeps I had already recorded as covered. ## The procedure ``` - const reviewColumns = await resolveProjectColumnsForRoles(this.store, REVIEW_ROLES); + const reviewColumns = new Set<string>(["in-review"]); ``` Suite fails → covered. Suite passes → nothing in the tree can tell the conversion from the literal. One resolver, one 17-second run — cheaper than writing the conversion was. ## Why the census cannot answer this | instrument | question | |---|---| | census / lane-wiring ratchet | is this site written in the resolved vocabulary? | | blinding | does anything break if it stops being? | Neither substitutes for the other. A conversion merged with 204 green tests behind it and zero able to see it. ## Four rules, each paid for by a test that proved nothing 1. **Blind each resolver separately** — coverage is per-resolver, not per-sweep. Twice a sweep recorded as done was half-done, because control flow short-circuited before the second guard. 2. **The fixture must reach the branch the resolver gates.** A card in a renamed *wip* lane cannot exercise a *terminal* skip — it is caught by the wip∪review set first. 3. **Assert a path-specific side effect, never a return value.** `outcome === "reclaimed"` is reachable without the guarded branch. 4. **A store fake must honour `options.column`.** Flat and call-order stubs answer identically whatever column is requested — a fake that ignores its own filter cannot see a filter bug. ## The two shapes a ratchet cannot distinguish - **resolved gate, literal branch** — reads as *unwired*, was a live defect (#3208: a working agent lost its task link) - **passed-but-unread** — reads as *wired*, is dead code (#3212) A ratchet counting call sites scores the first as debt and the second as done. Both wrong. ## Why a doc and not more PR comments Everything above currently lives in ~20 PR descriptions. The next person to touch a lane conversion will not read those. `docs/solutions/` is where this project already keeps the things it learned the expensive way, and the frontmatter (`applies_when: deciding whether a lane conversion is actually protected by a test`) is what makes it findable. ## Verification `pnpm test:gate` 13 + 161 + 499 + 71 · lint · fnxc-dates (TZ=UTC) · `self-healing-docs` 2 passed. Docs only; no changeset, per the AGENTS.md rule for internal docs. |