N/ NIFT LABS

Task runners / same-node experiment

Work has
an order.

Nift, Turbo and Nx run the same project workflow. What happens when tasks are clean, inputs change, branches run together—or a prerequisite fails?

20 → 100 → 1,000 tasks / workers 1, 2, 4

WORKFLOW / 012 CORE TASKSCHECKED
generate
schema→client
check
typesunitlint
produce
webhelperdocs
release
package→integration→verify→release

Branches converge on package. Client feeds docs; helper is independent. Added asset families exercise fan-out and independent lanes. Exact relationships ↓

Nift 4.12.0 finalSource-built snapshot. Programmable .f actions, tracked ordering and file invalidation.
Turbo 2.11.7Package-script tasks, explicit pipeline and native local task cache.
Nx 23.3.0Project targets, run-commands executor and native local task cache.
1,434 measured observations93 runner cells93 retained warmups1 fresh shared-CPU node

At 1,000 mixed tasks / j4, unchanged CLI medians were Nift 118.418 ms, Turbo 436.115 ms, Nx 1,736.465 ms. All-dirty medians were Nift 13.410 s, Turbo 112.412 s, Nx 17.838 s. These are descriptive observations of this workflow; the full-dirty cells have three measured samples.

01 / workflow

One workflow. Three native descriptions.

The common quantitative graph uses identical Python task bodies: content-hashed JSON outputs, text transforms, checks, one real helper compilation/execution, deterministic in-memory packaging and release validation. Additional asset tasks expand the graph. Each successful check produces a receipt in all runners.

Task names model workflow roles. Checks assert known properties of a 32-record input; web/docs transform text; the helper compiles a trivial C program; package validates an in-memory tar. No real TypeScript compiler, application test suite, framework build or deployment is measured.

Cached check receipts are not always-run, outputless checks. This is a synthetic single-project workflow—not a production JavaScript framework, package discovery benchmark, or remote-cache comparison. Outputless APIs are outside this refresh’s matched capability certification.

Core ordering; task inputs additionally declare consumed artifact bytes
TaskPrerequisites
generate-schemanone
generate-clientgenerate-schema
typecheck / unit-testgenerate-client
lint / build-helpernone
build-webtypecheck, lint, unit-test
docsgenerate-client
packagebuild-web, build-helper, docs
integration-testpackage
verifyintegration-test
release-prepverify

02 / noop

Nothing changed. State still costs time.

Every task body must remain unexecuted. Nift checks retained tracked input/output state; Turbo and Nx report native local cache hits with output files already present. These are different skip mechanisms, measured as fresh CLI invocations over prepared state. Nx daemon and remote caching are disabled.

Unchanged mixed workflow; Nift, Turbo, Nx
Unchanged mixed workflow. Both axes logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
Unchanged mixed workflow; median ms; j4
TasksNift msTurbo msNx msn / cell
207.43258.387616.19650
10016.35471.943703.38650
1,000118.418436.1151,736.46550

03 / leaf

One leaf changes. Selection stays explicit.

Changing one independent asset executes exactly that task while the full graph remains in view. The targeted comparisons start with dirty selected tasks, so Nift’s force-target behavior does not add unneeded work. Release selection includes its prerequisite closure; an untimed full invocation subsequently refreshes unselected consumers.

One dirty leaf; Nift, Turbo, Nx
One dirty leaf. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
One dirty leaf; median ms; j4
TasksNift msTurbo msNx msn / cell
2056.099414.070689.27520
10065.364431.787767.16520
1,000172.437747.9221,878.94620
20 mixed tasks; j4; median ms
CaseNift msTurbo msNx msExecutedn / cell
Targeted leaf52.611404.850620.304110
Targeted release closure393.0052,972.0421,048.4021010
Two targets54.834435.153641.712210

Nift named targets are forced rather than a clean “ensure” operation. The graph’s worker limit is configured in the project; the frozen adapter does not use per-invocation worker overrides; this is not an exhaustive current-API capability test.

04 / fanout

A changed input reaches its consumers.

The 10% case changes independent asset inputs. The generated-prerequisite case changes schema input and requires the complete transitive consumer set, including schema-dependent added assets. Ordering alone is insufficient: consumed output bytes are declared as invalidation inputs.

10% task inputs dirty; Nift, Turbo, Nx
10% task inputs dirty. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
10% task inputs dirty; median ms; j4
TasksNift msTurbo msNx msn / cell
2058.449442.417701.24010
100163.8451,345.675928.2155
1,0001,449.16911,544.6503,372.8053
Generated prerequisite dirty; Nift, Turbo, Nx
Generated prerequisite dirty. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
Generated prerequisite dirty; median ms; j4
TasksNift msTurbo msNx msn / cell
20412.4783,127.5841,121.10310
100903.6967,478.4411,554.1005
1,0006,798.75757,030.6369,865.5743

05 / full

All inputs dirty. Every task runs.

Unique bytes change in every task input. Native caching remains enabled, including cache writes, but the exact execution oracle requires all tasks to run. These light controlled bodies do not estimate savings in compiler- or application-test-dominated projects. A separate 20-task cohort explicitly disables Turbo/Nx task-cache reads and writes and forces Nift work; these modes are not pooled.

All mixed-task inputs dirty; Nift, Turbo, Nx
All mixed-task inputs dirty. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
All mixed-task inputs dirty; median s; j4
TasksNift sTurbo sNx sn / cell
200.4643.6011.12510
1001.42512.2092.2875
1,00013.410112.41217.8383
20 mixed tasks; j4; median ms
CaseNift msTurbo msNx msExecutedn / cell
Cache-disabled full442.1043,555.3341,089.7352010
Full-dirty throughput; task count / median wall seconds; j4
GraphNift tasks/sTurbo tasks/sNx tasks/s
mixed / 2043.0605.55417.775
mixed / 10070.1728.19143.723
mixed / 100074.5688.89656.059
tiny / 100763.7229.98867.133
tiny / 1000651.69210.17393.544

06 / parallel

Independent branches share the worker budget.

One hundred mixed tasks execute with limits of one, two and four. Task-body start/complete events independently verify ordering and overlap. These limits control task bodies; they do not imply an equal total operating-system process count because native launch layers differ.

Mixed workflow worker scaling; Nift, Turbo, Nx
Mixed workflow worker scaling. Value axis starts at zero; worker-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
Mixed workflow worker scaling; median s; 100 mixed tasks
WorkersNift sTurbo sNx sn / cell
14.71635.7016.1395
22.52519.4583.5865
41.42512.2092.2875
Maximum observed task-body overlap, 100 mixed tasks, full dirty
Worker limitNiftTurboNx
1111
2222
4323

07 / failure

A failure blocks descendants, not independent work.

Semantic certification injects a schema failure, requires a nonzero exit, blocks its descendants and checks independent branch completion. Recovery verifies all expected work and output bytes. These feature tests are separate from successful timing distributions.

Observed failure and retry behavior
RunnerFailure / recovery
NiftNames the failed custom action; independent branches complete. A normal retry reports unfinished build; build --repair is required.
TurboFailed npm task exits nonzero; dependencies-successful continuation permits independent work and blocks dependent tasks. Fix then rerun.
NxTarget failure produces a failed-task summary and nonzero status. Independent targets complete; dependent targets do not run. Fix then rerun.

Actual stdout/stderr and start/complete/fail traces are retained with the semantic observations. Exit-code values differ and are not treated as a performance result. Turbo/Nx recovery is tested with full forced execution; Nift uses repair. These tests certify correct retry, not the fastest default incremental recovery path.

08 / tiny

Tiny work exposes orchestration and launch cost.

The same compiled C body hashes a small input and writes one deterministic output. Independent 100- and 1,000-task graphs exercise unchanged, one-task, 1%, 10% and full-dirty cases. Turbo retains its npm script launch layer, Nx uses run-commands, and Nift uses cmd: this is not isolated scheduler CPU.

Unchanged tiny-task graph; Nift, Turbo, Nx
Unchanged tiny-task graph. Both axes logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
Unchanged tiny-task graph; median ms; j4
TasksNift msTurbo msNx msn / cell
10014.09070.034656.82250
1,00098.629412.6281,554.18850
One dirty tiny task; Nift, Turbo, Nx
One dirty tiny task. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
One dirty tiny task; median ms; j4
TasksNift msTurbo msNx msn / cell
10018.794385.966692.07320
1,000104.292683.5101,646.31820
10% tiny-task inputs dirty; Nift, Turbo, Nx
10% tiny-task inputs dirty. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
10% tiny-task inputs dirty; median ms; j4
TasksNift msTurbo msNx msn / cell
10027.7051,187.426758.1905
1,000238.54410,095.7972,566.7313
Fully dirty tiny-task graph; Nift, Turbo, Nx
Fully dirty tiny-task graph. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
Fully dirty tiny-task graph; median s; j4
TasksNift sTurbo sNx sn / cell
1000.13110.0121.4905
1,0001.53498.30410.6903
1,000 tiny tasks; j4; median ms
CaseNift msTurbo msNx msExecutedn / cell
Unchanged98.629412.6281,554.188050
One leaf dirty104.292683.5101,646.318120
1% inputs dirty117.4001,432.0191,761.650103
10% inputs dirty238.54410,095.7972,566.7311003
All inputs dirty1,534.46798,304.24010,690.13510003

The optional 10,000-task cohort was excluded after local feasibility because repeated launch-heavy runs were disproportionate to this bounded diagnostic. This is a runtime-budget decision, not evidence of a graph-size capability limit.

09 / inputs

Inputs, outputs and cache are distinct contracts.

The frozen adapter declares file inputs and artifact ownership separately from task completion order. Nift validates retained state; Turbo/Nx use their native local result caches. Incremental skipping is not restoring missing outputs. Remote caching and daemon-assisted execution are excluded.

Capability evidence boundaries
QuestionWhat this refresh establishes
Artifact-producing DAGAll three execute equivalent input/output/order contracts; exact action and output oracles pass.
Outputless checks / environment inputsNot recertified as a matched new capability comparison. Receipt-producing checks in this adapter must not be presented as proof of every current API limit.
Task-result restorationNative peer cache hits and prepared outputs are audited; no new Nift result-restoration implementation is claimed.
Ordering vs invalidationCompletion prerequisites and declared consumed file bytes remain distinct facts.
Remote cache / project inferenceNot measured; choose a tool for these requirements using its own capability contract.

Supplemental comparisons not recertified by this suite are excluded from current results.

10 / resources

Resource figures keep their measurement boundary.

Every observation retains C-supervised wall time, CPU time and Linux wait4 maximum-child RSS. RSS is a child high-water measure—not summed simultaneous memory across parallel task/Node/compiler processes. The same incremental workloads appear in timing and memory panels.

Unchanged workflow memory; Nift, Turbo, Nx
Unchanged workflow memory. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
Unchanged workflow memory; median MiB; j4
TasksNift MiBTurbo MiBNx MiBn / cell
205.75046.234108.73650
1005.87549.959115.47950
1,0006.969108.133165.76650
One dirty leaf memory; Nift, Turbo, Nx
One dirty leaf memory. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
One dirty leaf memory; median MiB; j4
TasksNift MiBTurbo MiBNx MiBn / cell
2017.37580.863108.06220
10017.37580.846115.94320
1,00018.000112.090165.26820
All dirty workflow memory; Nift, Turbo, Nx
All dirty workflow memory. Value axis starts at zero; task-count spacing is logarithmic. Lines join measured points, not a fitted model. Same cohort, ordering, units and medians in chart and table. SVG / PNG
All dirty workflow memory; median MiB; j4
TasksNift MiBTurbo MiBNx MiBn / cell
2020.00081.721110.61710
10020.00082.199120.2305
1,00019.875113.047170.5703

11 / correctness

A fast skipped task is a rejected result.

All 1,527 accepted observations pass exact task-start/completion/output, prerequisite order, concurrency, rotation, raw-metric and distribution audits. Every warmup remains. A first attempt reused preflight caches and was rejected at the first changed leaf when Turbo restored a cached result rather than executing the required action. Its 153 observations and failed command are preserved separately; none enter these distributions. The accepted run starts at the first cell in a fresh exact suite checkout with empty fixture/project caches.

The independently certified 21 semantic observations check failure, blocked descendants, independent completion and recovery. Outputless/environment behavior is outside the matched performance matrix. The unchanged refresh runner recognizes the accepted Nx cache-disabled receipt; this is a full new run, not a continuation or pooled partial series.

23 of 93 cells have a min–max span greater than 25% of their median. This is a descriptive spread flag, not a confidence interval. Sparse three-sample cells do not support tail or significance claims.

All 93 cells: timing distributions, CPU, memory and executed counts
All observations retained; p95 only n ≥ 20; interpolated percentiles
CaseRunnernMedian msMin–max msp95 msCPU msRSS MiBExecuted
mixed / 20 / j4 / 10% inputs dirtyNift1058.44955.854–67.660—113.26517.4412
mixed / 20 / j4 / 10% inputs dirtyNx10701.240661.003–720.747—1,388.121107.7322
mixed / 20 / j4 / 10% inputs dirtyTurbo10442.417425.656–456.883—975.72280.6052
mixed / 20 / j4 / All inputs dirtyNift10464.470439.748–612.463—1,071.33020.00020
mixed / 20 / j4 / All inputs dirtyNx101,125.1951,050.379–1,216.618—2,456.672110.61720
mixed / 20 / j4 / All inputs dirtyTurbo103,601.1723,539.753–3,866.850—8,738.27281.72120
mixed / 20 / j4 / One leaf dirtyNift2056.09953.278–88.29062.34261.78217.3751
mixed / 20 / j4 / One leaf dirtyNx20689.275643.684–737.027716.8161,333.051108.0621
mixed / 20 / j4 / One leaf dirtyTurbo20414.070398.948–547.051499.485509.73080.8631
mixed / 20 / j4 / Two targetsNift1054.83452.653–59.430—103.41317.3752
mixed / 20 / j4 / Two targetsNx10641.712624.986–660.636—1,323.990108.1292
mixed / 20 / j4 / Two targetsTurbo10435.153421.275–476.955—953.07080.4712
mixed / 20 / j4 / UnchangedNift507.4326.480–10.9889.79412.2735.7500
mixed / 20 / j4 / UnchangedNx50616.196574.520–777.118650.593819.171108.7360
mixed / 20 / j4 / UnchangedTurbo5058.38754.027–77.29769.05074.82746.2340
mixed / 20 / j4 / Generated prerequisite dirtyNift10412.478386.153–445.961—732.50017.56214
mixed / 20 / j4 / Generated prerequisite dirtyNx101,121.1031,083.608–1,166.944—2,118.177109.04714
mixed / 20 / j4 / Generated prerequisite dirtyTurbo103,127.5843,034.554–3,424.482—6,176.99181.70514
mixed / 20 / j4 / Targeted leafNift1052.61151.333–65.399—51.83117.3751
mixed / 20 / j4 / Targeted leafNx10620.304610.238–667.823—1,234.264106.9101
mixed / 20 / j4 / Targeted leafTurbo10404.850391.509–578.525—493.14381.0901
mixed / 20 / j4 / Targeted release closureNift10393.005382.501–436.912—493.07317.50010
mixed / 20 / j4 / Targeted release closureNx101,048.4021,032.050–1,149.503—1,769.548106.85210
mixed / 20 / j4 / Targeted release closureTurbo102,972.0422,874.247–3,027.004—4,455.87881.51810
mixed / 20 / j4 / Cache-disabled fullNift10442.104421.346–460.946—1,016.78420.00020
mixed / 20 / j4 / Cache-disabled fullNx101,089.7351,055.418–1,139.032—2,366.720108.92420
mixed / 20 / j4 / Cache-disabled fullTurbo103,555.3343,491.139–4,059.638—8,648.14981.59820
mixed / 100 / j1 / All inputs dirtyNift54,716.4454,688.667–4,831.884—4,718.76020.000100
mixed / 100 / j1 / All inputs dirtyNx56,139.4736,090.862–6,537.112—6,794.891120.109100
mixed / 100 / j1 / All inputs dirtyTurbo535,700.83035,268.800–36,438.313—43,379.20882.461100
mixed / 100 / j2 / All inputs dirtyNift52,525.4782,482.060–2,554.872—4,815.84420.000100
mixed / 100 / j2 / All inputs dirtyNx53,586.4963,460.881–3,703.912—7,051.815118.227100
mixed / 100 / j2 / All inputs dirtyTurbo519,458.06619,399.598–20,268.609—43,702.88482.145100
mixed / 100 / j4 / 10% inputs dirtyNift5163.845161.577–173.394—521.47417.48410
mixed / 100 / j4 / 10% inputs dirtyNx5928.215859.667–929.475—1,984.184115.48410
mixed / 100 / j4 / 10% inputs dirtyTurbo51,345.6751,324.245–1,440.487—4,510.02281.32010
mixed / 100 / j4 / All inputs dirtyNift51,425.0741,407.273–1,527.202—4,853.41220.000100
mixed / 100 / j4 / All inputs dirtyNx52,287.1102,190.814–2,390.148—6,975.336120.230100
mixed / 100 / j4 / All inputs dirtyTurbo512,208.81512,139.558–12,467.575—42,457.59882.199100
mixed / 100 / j4 / One leaf dirtyNift2065.36461.579–76.69175.23087.29217.3751
mixed / 100 / j4 / One leaf dirtyNx20767.165725.741–1,001.403837.2431,433.155115.9431
mixed / 100 / j4 / One leaf dirtyTurbo20431.787401.255–545.077461.535555.15080.8461
mixed / 100 / j4 / UnchangedNift5016.35414.115–19.26818.61138.4865.8750
mixed / 100 / j4 / UnchangedNx50703.386642.050–877.500746.153938.307115.4790
mixed / 100 / j4 / UnchangedTurbo5071.94367.381–88.78280.284109.67549.9590
mixed / 100 / j4 / Generated prerequisite dirtyNift5903.696875.765–1,159.209—2,648.05917.50054
mixed / 100 / j4 / Generated prerequisite dirtyNx51,554.1001,541.022–1,578.031—4,299.430116.78954
mixed / 100 / j4 / Generated prerequisite dirtyTurbo57,478.4417,316.147–7,528.788—23,104.81782.44954
mixed / 1,000 / j4 / 10% inputs dirtyNift31,449.1691,437.979–1,479.934—5,471.86018.000100
mixed / 1,000 / j4 / 10% inputs dirtyNx33,372.8053,359.855–3,460.728—8,743.753166.848100
mixed / 1,000 / j4 / 10% inputs dirtyTurbo311,544.65011,287.011–11,549.681—44,118.034112.102100
mixed / 1,000 / j4 / All inputs dirtyNift313,410.49713,227.737–13,545.120—51,619.21219.8751000
mixed / 1,000 / j4 / All inputs dirtyNx317,838.28717,368.879–18,100.818—61,772.930170.5701000
mixed / 1,000 / j4 / All inputs dirtyTurbo3112,412.417111,816.614–112,537.266—432,836.734113.0471000
mixed / 1,000 / j4 / One leaf dirtyNift20172.437161.334–188.555184.440385.03818.0001
mixed / 1,000 / j4 / One leaf dirtyNx201,878.9461,834.386–2,124.4012,038.9562,990.431165.2681
mixed / 1,000 / j4 / One leaf dirtyTurbo20747.922703.977–814.099792.8001,576.822112.0901
mixed / 1,000 / j4 / UnchangedNift50118.418107.218–173.430131.746332.2116.9690
mixed / 1,000 / j4 / UnchangedNx501,736.4651,634.803–2,030.2201,859.8652,342.836165.7660
mixed / 1,000 / j4 / UnchangedTurbo50436.115399.335–773.195504.1041,146.745108.1330
mixed / 1,000 / j4 / Generated prerequisite dirtyNift36,798.7576,754.315–6,869.772—25,901.75418.125504
mixed / 1,000 / j4 / Generated prerequisite dirtyNx39,865.5749,591.053–10,119.385—32,350.729168.477504
mixed / 1,000 / j4 / Generated prerequisite dirtyTurbo357,030.63656,937.077–58,053.630—216,071.479118.062504
tiny / 100 / j4 / 10% inputs dirtyNift527.70525.560–28.753—64.9797.62510
tiny / 100 / j4 / 10% inputs dirtyNx5758.190710.772–774.041—1,417.798115.30110
tiny / 100 / j4 / 10% inputs dirtyTurbo51,187.4261,144.975–1,193.217—3,949.31681.08210
tiny / 100 / j4 / All inputs dirtyNift5130.938116.224–140.168—395.4887.625100
tiny / 100 / j4 / All inputs dirtyNx51,489.5711,393.462–1,550.249—2,218.322117.496100
tiny / 100 / j4 / All inputs dirtyTurbo510,011.8699,783.629–10,165.612—38,337.89181.883100
tiny / 100 / j4 / One leaf dirtyNift2018.79417.499–22.90721.85632.2927.5001
tiny / 100 / j4 / One leaf dirtyNx20692.073669.927–738.196732.2851,141.396112.2031
tiny / 100 / j4 / One leaf dirtyTurbo20385.966362.545–416.346411.659506.44180.9341
tiny / 100 / j4 / UnchangedNift5014.09012.752–20.64216.36127.7615.8750
tiny / 100 / j4 / UnchangedNx50656.822626.428–827.572742.879894.064111.9280
tiny / 100 / j4 / UnchangedTurbo5070.03465.318–84.78979.224108.01349.9060
tiny / 100 / j4 / 1% inputs dirtyNift518.31817.086–18.894—31.2947.5001
tiny / 100 / j4 / 1% inputs dirtyNx5691.039670.109–716.734—1,152.569112.0591
tiny / 100 / j4 / 1% inputs dirtyTurbo5382.282360.968–394.894—501.96281.0701
tiny / 1,000 / j4 / 10% inputs dirtyNift3238.544237.419–251.027—692.3238.863100
tiny / 1,000 / j4 / 10% inputs dirtyNx32,566.7312,476.270–2,566.864—3,636.693158.535100
tiny / 1,000 / j4 / 10% inputs dirtyTurbo310,095.79710,090.992–10,294.454—38,709.316108.469100
tiny / 1,000 / j4 / All inputs dirtyNift31,534.4671,494.854–1,631.212—4,807.6379.1131000
tiny / 1,000 / j4 / All inputs dirtyNx310,690.13510,148.098–10,740.128—12,647.889163.5271000
tiny / 1,000 / j4 / All inputs dirtyTurbo398,304.24097,869.821–98,576.084—383,624.039115.1021000
tiny / 1,000 / j4 / One leaf dirtyNift20104.29296.783–130.515121.849241.9388.3611
tiny / 1,000 / j4 / One leaf dirtyNx201,646.3181,565.497–1,912.4121,778.4452,471.122156.8111
tiny / 1,000 / j4 / One leaf dirtyTurbo20683.510645.701–805.022733.5981,464.522110.0531
tiny / 1,000 / j4 / UnchangedNift5098.62989.516–126.818109.456241.2686.4840
tiny / 1,000 / j4 / UnchangedNx501,554.1881,486.365–1,650.3791,617.4132,151.386157.4490
tiny / 1,000 / j4 / UnchangedTurbo50412.628360.601–1,243.480574.3171,093.295107.9020
tiny / 1,000 / j4 / 1% inputs dirtyNift3117.400114.357–124.691—293.3668.86310
tiny / 1,000 / j4 / 1% inputs dirtyNx31,761.6501,744.474–1,762.258—2,771.659156.12910
tiny / 1,000 / j4 / 1% inputs dirtyTurbo31,432.0191,428.106–1,463.275—4,789.735114.34010

12 / practitioner

AI-DX changes the choice—but not the evidence.

Qualitative practitioner judgement / observed contracts kept separate

For human-plus-agent and agent-primary bespoke authored workflows, I would choose Nift. The same applies to mixed website/assets/helpers/tasks projects owned by Nift. All 31 measured configurations have the lowest Nift wall and maximum-child RSS medians here; programmable .f policy and explicit ownership, ordering, invalidation and lifecycle also matter.

I would choose Turbo/Nx for specific task-result restoration, remote-cache/platform or framework/workspace integration requirements. Those are concrete needs, not an architectural reason to default away from Nift for new bespoke work. The timed adapter does not establish the absence of every alternative current API.

AI-DX evidence classes
EvidenceConclusion
DemonstratedExact actions, output bytes, completion order, bounded overlap, targeting and failure/recovery checks pass.
Source / representationSeparate artifact/input/order declarations make semantic roles inspectable.
Qualitative inferenceThat explicit structure can help agents make bounded, reviewable edits; helpers should remove duplicated boilerplate without collapsing semantics.
Not measuredAutonomous authoring success, repair rate, token/time cost, arbitrary-edit safety or a complete product-native structured error contract.

No numeric productivity or safety score is assigned. Harness JSON is not product-native structured feedback. Missing comparative probes do not establish competitor incapability.

13 / method

Frozen sources. Retained samples. One node.

One fresh 4-logical-CPU / 8-GB Ubuntu 24.04 Linode, us-east. CPU affinity includes all four CPUs. Runner order rotates within rounds; scenario order follows a fixed frozen plan. Fresh CLI invocation, prepared local state, no remote cache, Nx daemon disabled. Setup/input mutations are outside the timer; native dispatch, task work and bookkeeping are inside. Stdout/stderr are captured: native status formatting and cache-log costs are included; terminal painting is excluded. Turbo uses errors-only task logs and Nx uses static output. These CLI modes are retained with each command, not presented as equal pure scheduler CPU. No outlier removal.

The mixed body reads the canonical graph for each invocation; that identical cost is included. The suite covers 20/100/1,000 mixed tasks, 100/1,000 tiny tasks, j4 scaling, 100-task j1/j2 full-dirty work and 20-task cache-disabled/targeting cohorts. Failure and unsupported semantics are separate capability tests. Shared-CPU variance, sparse expensive cells and this synthetic single-project model limit generalization.

Nift source
c14d06835bca515a5281e41da0e40219c2d60ef0
Measured suite
f37b63bd13cf71256607ba4652bcc911e270f94e
Toolchain
Node 22.22.1 / npm 9.2.0 / Turbo 2.11.7 / Nx 23.3.0 / g++ (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
Machine
AMD EPYC 7642 48-Core Processor / 6.8.0-134-generic / ext4; prepared local fixtures
Canonical evidence
Raw samples, traces, provenance, semantic probes, audit and lifecycle
Core follow-up
Reproducible semantic/DX gaps; Nift core was not changed.
Reproduce
Fairness contract · Sample plan · Independent auditor
Actual invocations and reusable Nift action

Representative 20-task unchanged command; worker count four. Nx daemon/cloud disabled; remote cache disabled. Each observation retains its complete invocation.

Nift: /opt/nift/nift build
Turbo: /opt/suites/task-runners-official/work/tools/node_modules/.bin/turbo run generate-schema generate-client lint typecheck unit-test build-web build-helper docs package integration-test verify release-prep asset-00000 asset-00001 asset-00002 asset-00003 asset-00004 asset-00005 asset-00006 asset-00007 --concurrency=4 --cache=local:rw --continue=dependencies-successful --output-logs=errors-only
Nx: /opt/suites/task-runners-official/work/tools/node_modules/.bin/nx run-many --projects=workflow --targets=generate-schema,generate-client,lint,typecheck,unit-test,build-web,build-helper,docs,package,integration-test,verify,release-prep,asset-00000,asset-00001,asset-00002,asset-00003,asset-00004,asset-00005,asset-00006,asset-00007 --parallel=4 --outputStyle=static

The Nift tracked graph uses one reusable supported .f hook:

r := cmd("python3", "task_body.py", getenv("NIFT_HOOK_TARGET")).cwd(getenv("NIFT_HOOK_ROOT")).run()
if(!r.launched || r.exit_code != 0) { throw error(r.stderr, "user.task.failed") }

Direct lint/test/package/release .f examples are separately certified over prepared prerequisites; they do not implement an adapter scheduler.