## A whole class of "conversions" in this program is inert, and the
census scores them as done
`resolveTaskWorkflowIrSync` returns the **default** workflow IR for
**every** task in production. `getTaskWorkflowSelectionImpl` is a
PostgreSQL-cutover stub that returns `undefined` unconditionally
(`workflow-definitions.ts:505` — *"Backend mode cannot synchronously
read PostgreSQL, so return undefined and let the sync reader fall back
to its default"*), so the sync resolver always takes its `!workflowId`
branch. Its return type is **non-optional**, so no caller can detect the
substitution.
**Proven, not argued.** The PG suite binds a task to a workflow whose
lanes are `drafting`/`building`/`checking`/`shipped`, asserts the
**async** reader sees that binding — or the next assertion would be
vacuous — and then shows the sync resolver answering `hold: "todo"` for
the same task. A third case pins the cause directly: the sync selection
reader returns `undefined` while the async one returns the workflow id.
The async resolver on the same task, in the same test, returns the real
lanes. So the remedy for any affected site is always *reach the async
resolver*, never *resolve synchronously and hope*.
### Why this is worse than an unconverted literal
```ts
resolveLifecycleColumns(store.resolveTaskWorkflowIrSync(id))?.hold
```
That **reads** as converted. It resolves an IR, asks for a trait, and
the lifecycle-column census counts it as **progress** — while being
wrong for every custom workflow, silently. A plain `=== "todo"` is
strictly better, because it is at least honest about being a literal.
That is why this needs a guard rather than a comment: the failure mode
is code that *looks right in review*.
### The ratchet earned its place immediately
It allow-lists the six call sites, in the shape this repo already uses
for `engine-no-blocking-shellout` and `check-no-nohup`. On its first run
it corrected the list I had seeded by grep:
- **Found `replan-target.ts`**, which my grep missed — it calls through
an optional-property cast, so no textual search for
`store.resolveTaskWorkflowIrSync` matches it. **Its hazard is the
sharpest of the six:** `resolvePlannerLanes` returns
`resolvedFromWorkflow: true` whenever an IR came back, so on a renamed
board a caller branching on that flag is told the lanes are
workflow-resolved while being handed the **default** ones.
- **Rejected `executor.ts`**, which my grep had matched on a *comment*
with no real call site.
It also carries a completeness case (fails if the scan finds nothing,
rather than passing vacuously) and a staleness case (an entry whose file
stops using the primitive must be removed in the same change, so the
list can't rot into unreviewed permission).
### Verified to fire
Adding a new unlisted call site fails with the offending file named:
```
+ "packages/engine/src/gridlock-detector.ts"
Tests 1 failed | 2 passed (3)
```
My first attempt at that proof landed the probe **inside a block
comment** and the guard correctly reported zero — the methodology was
wrong, not the guard. Worth stating, since a guard I couldn't make fail
is exactly the thing this PR is about.
### Scope
**No source changes.** This pins a fact and guards a primitive. The six
existing sites are deliberately left alone: each needs its own
async-reachability analysis, which is per-site work with real behaviour
risk, not a sweep. `scheduler.ts`'s entry is the honest case — it is
called from synchronous `task:moved` listeners where adding an `await`
would reorder handlers against a synchronous emitter.
### Verification
- new PG suite **3 passed** · new ratchet **3 passed**
- `pnpm test:gate` — **158 / 10 / 487 / 71** · `pnpm lint` clean · core
`tsc --noEmit` **0 errors** · `--strict` exits 0
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
82 lines
2.7 KiB
JSON
82 lines
2.7 KiB
JSON
{
|
|
"name": "@fusion/core",
|
|
"version": "0.74.0-beta.5",
|
|
"license": "MIT",
|
|
"description": "Fusion core: task store, scheduler, settings, and shared domain types backing the Fusion AI coding agent.",
|
|
"homepage": "https://github.com/Runfusion/Fusion#readme",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/Runfusion/Fusion",
|
|
"directory": "packages/core"
|
|
},
|
|
"bugs": {
|
|
"url": "https://github.com/Runfusion/Fusion/issues"
|
|
},
|
|
"type": "module",
|
|
"exports": {
|
|
".": {
|
|
"types": "./src/index.ts",
|
|
"source": "./src/index.ts",
|
|
"import": "./dist/index.js"
|
|
},
|
|
"./gh-cli": {
|
|
"types": "./src/gh-cli.ts",
|
|
"source": "./src/gh-cli.ts",
|
|
"import": "./dist/gh-cli.js"
|
|
},
|
|
"./task-delete-attribution": {
|
|
"types": "./src/task-delete-attribution.ts",
|
|
"source": "./src/task-delete-attribution.ts",
|
|
"import": "./dist/task-delete-attribution.js"
|
|
},
|
|
"./detect-content-language": {
|
|
"types": "./src/detect-content-language.ts",
|
|
"source": "./src/detect-content-language.ts",
|
|
"import": "./dist/detect-content-language.js"
|
|
},
|
|
"./package.json": "./package.json"
|
|
},
|
|
"publishConfig": {
|
|
"access": "public"
|
|
},
|
|
"files": [
|
|
"dist",
|
|
"README.md"
|
|
],
|
|
"scripts": {
|
|
"build": "tsc",
|
|
"typecheck": "tsc --noEmit",
|
|
"test": "vitest run --silent=passed-only --reporter=dot",
|
|
"test:embedded-postgres": "vitest run src/__tests__/postgres/embedded-lifecycle.test.ts --silent=passed-only --reporter=dot",
|
|
"test:pg-gate": "vitest run --config vitest.pg.config.ts src/__tests__/postgres/handoff-to-review-atomicity.pg.test.ts src/__tests__/postgres/task-lifecycle-e2e.pg.test.ts src/__tests__/postgres/sync-workflow-ir-is-always-default.pg.test.ts --silent=passed-only --reporter=dot",
|
|
"test:unit-gate": "vitest run src/__tests__/task-merge.test.ts src/__tests__/legacy-adoption.test.ts src/__tests__/no-hardcoded-lifecycle-columns.test.ts src/__tests__/sync-workflow-ir-callsite-allowlist.test.ts --silent=passed-only --reporter=dot"
|
|
},
|
|
"devDependencies": {
|
|
"@earendil-works/pi-coding-agent": "0.82.1",
|
|
"@types/dockerode": "^3.3.41",
|
|
"@types/node": "^25.5.0",
|
|
"@vitest/coverage-v8": "^4.1.10",
|
|
"typescript": "^5.7.0",
|
|
"vitest": "^4.1.10"
|
|
},
|
|
"engines": {
|
|
"node": ">=22.5.0"
|
|
},
|
|
"private": true,
|
|
"dependencies": {
|
|
"bonjour-service": "^1.3.0",
|
|
"check-disk-space": "^3.4.0",
|
|
"cron-parser": "^5.5.0",
|
|
"dockerode": "^4.0.2",
|
|
"drizzle-orm": "^0.45.2",
|
|
"embedded-postgres": "15.18.0-beta.17",
|
|
"extract-zip": "^2.0.1",
|
|
"postgres": "^3.4.9",
|
|
"tar": "^7.5.13",
|
|
"yaml": "^2.8.3"
|
|
},
|
|
"optionalDependencies": {
|
|
"keytar": "^7.9.0"
|
|
}
|
|
}
|