{"id":"build-cache","title":"Fix an incremental build","summary":"Cache invalidation, dependency changes, cycles.","phases":["Repair a build cache. Input: {nodes:[{id,deps:[id],revision:integer}],\nrequests:[{changes:[{id,revision}],targets:[id]}]}. IDs are unique ASCII\nidentifiers; references exist. Only nodes reachable backward from targets are\nrequired. deps may repeat. Begin with an empty cache. Apply changes in order\nbefore each build. Build the required subgraph in the lexicographically smallest\ntopological order (smallest currently ready ID each step). A node is cached only\nif its last successful build used the same revision, same distinct dependencies,\nand same last successful build of each dependency. Otherwise rebuild it. A\nrebuilt dependency forces its consumers to rebuild. Store only each node's last\nsuccessful build, not all historical revisions. Ignore unrelated changes.\nReturn one {built:[ids],cached:[ids]} per request; both lists follow build order.\nEmpty targets returns empty lists. No nodes are added or removed. Phase-one\ninputs are DAGs. Avoid enumerating paths through shared dependencies.","Extend the build system. A change can now set revision, deps, or\nboth. Dependency order and duplicate entries do not affect cache identity.\nCycles can exist. If the REQUIRED subgraph contains a cycle, return\n{error:'cycle',built:[],cached:[]} for that request and do not update any build\ncache. Definitions from changes still persist, so a later request can fix the\ncycle. Ignore unrelated cycles. All previous behavior remains required. A\nchanged dependency set invalidates that node even when revisions are equal."],"prompts":["Work in this repository. Implement synchronous CommonJS JavaScript.\nThe entry point is src/index.js, exporting { solve }. solve(input) must return a\nJSON-serializable value. Use only relative .js modules within src/. No packages,\nfilesystem, network, timers, process, eval, or async in submitted source.\nSubmit at most 24 .js files totaling at most 128 KiB.\nYou may inspect files, edit code, add tests, and run node --test. Change src/ and\ntest/ only. Do not change the existing test/smoke.test.js. Each hidden case runs\nin a fresh QuickJS context with 32 MiB memory and 500 ms CPU time. Object key\norder does not matter; array order does. Numbers are safe integers. All inputs\nsatisfy the stated contract. No Internet or external tools are needed.\nFinish by describing the change briefly. The code on disk is the submission.\n\nWORK ORDER 1\nRepair a build cache. Input: {nodes:[{id,deps:[id],revision:integer}],\nrequests:[{changes:[{id,revision}],targets:[id]}]}. IDs are unique ASCII\nidentifiers; references exist. Only nodes reachable backward from targets are\nrequired. deps may repeat. Begin with an empty cache. Apply changes in order\nbefore each build. Build the required subgraph in the lexicographically smallest\ntopological order (smallest currently ready ID each step). A node is cached only\nif its last successful build used the same revision, same distinct dependencies,\nand same last successful build of each dependency. Otherwise rebuild it. A\nrebuilt dependency forces its consumers to rebuild. Store only each node's last\nsuccessful build, not all historical revisions. Ignore unrelated changes.\nReturn one {built:[ids],cached:[ids]} per request; both lists follow build order.\nEmpty targets returns empty lists. No nodes are added or removed. Phase-one\ninputs are DAGs. Avoid enumerating paths through shared dependencies.","Work in this repository. Implement synchronous CommonJS JavaScript.\nThe entry point is src/index.js, exporting { solve }. solve(input) must return a\nJSON-serializable value. Use only relative .js modules within src/. No packages,\nfilesystem, network, timers, process, eval, or async in submitted source.\nSubmit at most 24 .js files totaling at most 128 KiB.\nYou may inspect files, edit code, add tests, and run node --test. Change src/ and\ntest/ only. Do not change the existing test/smoke.test.js. Each hidden case runs\nin a fresh QuickJS context with 32 MiB memory and 500 ms CPU time. Object key\norder does not matter; array order does. Numbers are safe integers. All inputs\nsatisfy the stated contract. No Internet or external tools are needed.\nFinish by describing the change briefly. The code on disk is the submission.\n\nWORK ORDER 2\nRepair a build cache. Input: {nodes:[{id,deps:[id],revision:integer}],\nrequests:[{changes:[{id,revision}],targets:[id]}]}. IDs are unique ASCII\nidentifiers; references exist. Only nodes reachable backward from targets are\nrequired. deps may repeat. Begin with an empty cache. Apply changes in order\nbefore each build. Build the required subgraph in the lexicographically smallest\ntopological order (smallest currently ready ID each step). A node is cached only\nif its last successful build used the same revision, same distinct dependencies,\nand same last successful build of each dependency. Otherwise rebuild it. A\nrebuilt dependency forces its consumers to rebuild. Store only each node's last\nsuccessful build, not all historical revisions. Ignore unrelated changes.\nReturn one {built:[ids],cached:[ids]} per request; both lists follow build order.\nEmpty targets returns empty lists. No nodes are added or removed. Phase-one\ninputs are DAGs. Avoid enumerating paths through shared dependencies.\n\nExtend the build system. A change can now set revision, deps, or\nboth. Dependency order and duplicate entries do not affect cache identity.\nCycles can exist. If the REQUIRED subgraph contains a cycle, return\n{error:'cycle',built:[],cached:[]} for that request and do not update any build\ncache. Definitions from changes still persist, so a later request can fix the\ncycle. Ignore unrelated cycles. All previous behavior remains required. A\nchanged dependency set invalidates that node even when revisions are equal."],"starter":{"src/index.js":"module.exports = require(\"./engine.js\");\n","src/engine.js":"// Cache currently keys only on a node's own revision.\nfunction solve(input) {\n  const nodes=new Map(input.nodes.map(n=>[n.id,{...n}])), cache=new Map();\n  return input.requests.map(r=>{\n    r.changes.forEach(c=>Object.assign(nodes.get(c.id),c));\n    const needed=new Set();\n    function visit(id){if(needed.has(id))return;needed.add(id);nodes.get(id).deps.forEach(visit);}\n    r.targets.forEach(visit);\n    const built=[],cached=[];\n    for(const id of [...needed].sort()){\n      const n=nodes.get(id);\n      if(cache.get(id)===n.revision)cached.push(id);\n      else {cache.set(id,n.revision);built.push(id);}\n    }\n    return {built,cached};\n  });\n}\nmodule.exports={solve};\n"}}