elanous 0.2.41 → 0.2.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{2fe2c302.41b517f88d6fe502.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{385e4574.e9886ab32759eda3.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
- package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6874.d5cf7eb8edb2cabe.js → 1406.a1dc2ab6f8449374.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5744.b9415e18ad623100.js → 1961.a81b12872c3e93a9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5471.1e611302ed3a7c53.js → 2144.25b292396712196d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3230-49298c3b73ef2268.js → 2268-53861f339e0b65a2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9834.63ab2bbc3153172e.js → 2312.0c8b61e22d3136d7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1800.f7ff51dc4978a958.js → 2573.387a707f6f9d720c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9048.212083de42d25be3.js → 3072.01338851ca21a6f7.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
- package/apps/pwa/out/_next/static/chunks/3095.dc44586a5f83b86d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2263.e09b6edea33bad2d.js → 3113.d7472bbc27d580c7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{addc2b32.8c4ff8f0aefe987d.js → 3557ac4a.c8931684475018ad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +79 -0
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{a0a01613.6d1cca322238d7fe.js → 363bfab3.9623b9f89363541f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
- package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
- package/apps/pwa/out/_next/static/chunks/4199.ce86b281fd0a60b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{530.d26346e18089640a.js → 4445.7990c76b3751a918.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4894.fec2ca9e99caefa2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
- package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1219.7e17964e0e7cd8e5.js → 5564.9e72532188f57586.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5628.6ddb2d5ffba4ff4c.js +309 -0
- package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1178.1aa9cad0e7695427.js → 5789.2da35c258292e1e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4133.2056bb4d78f621af.js → 5824.da9527b15a3221e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4527.a69f2894d1bc9f4a.js → 5930.8b4df3b46c32b05a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
- package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
- package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9507.7026657a2f47eb64.js → 6540.c7bef57ad8f90a87.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5574.f35accf4f132b29d.js → 6944.309f4e3ea54d1537.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7483.427a2fe2049e388d.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5947-135e26537d80a6b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
- package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
- package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2743.5d3f76948be32b34.js → 868.6e953be05bcf6dca.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5964-7e21164a8f2cf0ce.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5159.115f1c2ca471386c.js → 8986.8e2e4efbfa655c59.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
- package/apps/pwa/out/_next/static/chunks/923.2034d10ae91e9c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
- package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
- package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b2271e54.c1de3347976e90b0.js → aa57532f.510551854ff239b1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-9ee28f7df07428ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-40f9e19149024298.js → page-79a8b5fee4c20871.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-a142dfb0331a05f5.js → page-ca2d09128c585ca4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{53aeb4ee-51c92f8d683f5220.js → c7945435-b44d4dbe90ba0dcb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2fdf2931.b431eee4fb468bc3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{c0c1a699.0ba79f97005965d4.js → d96660fb.cbc21a2a88539dbb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{83184dcd-0ee6247ff41eb3f2.js → fb7d20d5-6892502b6ee39ca6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +1 -0
- package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
- package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +24 -25
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +23 -23
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +24 -25
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +24 -25
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/external-commands.yaml +5 -3
- package/catalog/meta/catalogVersion.yaml +2 -1
- package/catalog/signing/catalog-signing-public.pem +3 -0
- package/docs/goal-context/04-mock-scenarios.md +13 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/heal/heal-loop.yaml +1 -0
- package/graphs/intake/intake-daily.yaml +16 -0
- package/graphs/intake/news-sources.yaml +1 -0
- package/graphs/intake/recipes.yaml +7 -0
- package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
- package/graphs/overlays/stop-heal-ladder.yaml +113 -0
- package/graphs/profiles/local.yaml +5 -0
- package/graphs/profiles/pod.yaml +4 -0
- package/graphs/units/verbs/recipes.yaml +11 -11
- package/graphs/work/research-report.yaml +10 -2
- package/package.json +6 -2
- package/plugins/demo-absorption-briefing/plugin.json +18 -0
- package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
- package/plugins/demo-browser-hand/plugin.json +13 -0
- package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
- package/plugins/demo-linear-secretary/plugin.json +15 -0
- package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
- package/plugins/demo-plugin-wizard/plugin.json +11 -0
- package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
- package/plugins/demo-research/plugin.json +16 -0
- package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
- package/plugins/demo-video-briefing/plugin.json +15 -0
- package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
- package/scripts/build-signed-catalog.ts +48 -0
- package/scripts/ci-typecheck-main-delta.sh +88 -0
- package/scripts/codex-fallback-live-probe.ts +1 -1
- package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
- package/scripts/demo/demo1104-stage.config.ts +21 -0
- package/scripts/demo/demo1104-stage.ts +316 -0
- package/scripts/goal-method-audit.ts +17 -1
- package/scripts/graph-units/land-enqueue.ts +90 -0
- package/scripts/heal/run-role.ts +99 -5
- package/scripts/hooks/codex-notify.sh +32 -0
- package/scripts/install.sh +10 -38
- package/scripts/land-global-checks.ts +6 -1
- package/scripts/landing-heal/land-plan.ts +57 -0
- package/scripts/lib/decompose-ab.ts +1 -0
- package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
- package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
- package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
- package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
- package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
- package/scripts/lib/tui-regress-checks.ts +33 -13
- package/scripts/release-loop/auto-approve-node.ts +1 -1
- package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
- package/scripts/release-loop/gate-baseline-receipt.ts +47 -9
- package/scripts/release-loop/gate-image-pin.ts +81 -0
- package/scripts/release-loop/gate-method.ts +139 -0
- package/scripts/release-loop/gate-node-sim.ts +207 -0
- package/scripts/release-loop/gate-node.ts +463 -64
- package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
- package/scripts/release-loop/gate-radius-live.ts +97 -13
- package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
- package/scripts/release-loop/gate-traffic-mode.ts +151 -3
- package/scripts/release-loop/gate-train-receipts.ts +122 -0
- package/scripts/release-loop/node-verdict.ts +38 -25
- package/scripts/release-loop/preflight.ts +362 -8
- package/scripts/release-loop/resume-release.ts +83 -8
- package/scripts/release-loop/unattended-release.ts +20 -9
- package/scripts/rhythm/daily.ts +36 -4
- package/scripts/rhythm/linear-progress-sync.ts +298 -0
- package/scripts/ux-sim.ts +18 -1
- package/scripts/video-pipeline.ts +9 -1
- package/scripts/warm-pool-provider-config.ts +286 -0
- package/skills/omni-crawl/SKILL.md +5 -2
- package/skills/omni-crawl/scripts/main.ts +84 -23
- package/src/acp/agent-manager.ts +1 -0
- package/src/acp/codex-app-server-agent.ts +33 -0
- package/src/acp/codex-app-server-client.ts +153 -16
- package/src/acp/core-turn-bridge.ts +27 -9
- package/src/acp/event-router.ts +20 -1
- package/src/acp/server.ts +6 -0
- package/src/agent/registry.ts +2 -0
- package/src/agent/task-notification.ts +25 -5
- package/src/agent/types.ts +6 -0
- package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
- package/src/agent-mission/claude-headless.ts +4 -1
- package/src/agent-mission/codex-exec.ts +105 -0
- package/src/agent-mission/driver.ts +192 -11
- package/src/agent-mission/grok-auth-status.ts +47 -0
- package/src/agent-mission/hand-hooks.ts +101 -0
- package/src/agent-mission/mission-cli.ts +63 -4
- package/src/agent-mission/mission-hand-reply.ts +118 -0
- package/src/agent-mission/mission-line.ts +180 -0
- package/src/agent-mission/mission-out.ts +833 -0
- package/src/agent-mission/tool-install.ts +200 -3
- package/src/agent-substrate/context-strategy.ts +4 -4
- package/src/agent-substrate/self-review-cli.ts +178 -13
- package/src/agents/general-purpose.md +1 -1
- package/src/auto-research/research-turn.ts +211 -53
- package/src/autopilot/pr-manager.ts +69 -10
- package/src/autopilot/pty-control-loop.ts +2 -0
- package/src/boot/daemon-tools/self-implement.ts +3 -1
- package/src/boot/daemon-tools/web-search.ts +1 -2
- package/src/briefing/brief-items.ts +55 -11
- package/src/capture/tui-self-report.ts +22 -6
- package/src/chat/index.ts +1 -1
- package/src/cli/agent-cli.ts +2 -1
- package/src/cli/catalog-cli.ts +31 -0
- package/src/cli/connector-cli.ts +16 -0
- package/src/cli/doctor-fix.ts +2 -2
- package/src/cli/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
- package/src/cli/intake-source-cli.ts +44 -8
- package/src/cli/msg-cli.ts +32 -3
- package/src/cli/pr-cli.ts +21 -1
- package/src/cli/pr-land-heavy-remote.ts +75 -5
- package/src/cli/pr-land-overlap-evidence.ts +113 -2
- package/src/cli/pr-land-pod-shadow-job.ts +202 -4
- package/src/cli/pr-land-pod-shadow.ts +9 -2
- package/src/cli/release-checklist-read-cli.ts +57 -19
- package/src/cli/release-cli.ts +23 -3
- package/src/cli/research-cli.ts +13 -5
- package/src/cli/setup-cli.ts +166 -6
- package/src/cli/setup-keys.ts +187 -0
- package/src/cli/task-plugin-wizard-host.ts +114 -0
- package/src/cli/tasks-cli.ts +61 -9
- package/src/cli/tui-test-cli.ts +186 -0
- package/src/compact/auto.ts +8 -1
- package/src/config.ts +4 -2
- package/src/connectors/linear-daily-progress.ts +228 -0
- package/src/connectors/linear-projector.ts +34 -12
- package/src/connectors/linear.ts +151 -7
- package/src/control-plane/ledger.ts +52 -2
- package/src/control-plane/server.ts +16 -2
- package/src/core-turn/deep-turn-bloom.ts +67 -0
- package/src/core-turn/research-policy.ts +37 -0
- package/src/core-turn/run-core-turn.ts +606 -95
- package/src/core-turn/run-goal-loop.ts +18 -0
- package/src/core-turn/types.ts +4 -0
- package/src/dashboard/chat/acp-chat.ts +10 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +161 -0
- package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
- package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
- package/src/dashboard/classic-sidetab-mission.ts +347 -0
- package/src/dashboard/index.ts +517 -18
- package/src/dashboard/input/agent-wake.ts +23 -1
- package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +17 -0
- package/src/dashboard/mission-cli-consumer.ts +165 -0
- package/src/dashboard/plugin-wizard-runtime.ts +50 -0
- package/src/dashboard/plugin-wizard-tool.ts +55 -0
- package/src/dashboard/seat-boot-preamble.ts +171 -1
- package/src/dashboard/side-basic-runtime.ts +54 -1
- package/src/dashboard/sidetab-runtime.ts +90 -1
- package/src/dashboard/skill-catalog-preamble.ts +101 -0
- package/src/dashboard/skill-detection-runtime.ts +55 -15
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
- package/src/dashboard/terminal-popup-runtime.ts +6 -3
- package/src/dashboard/turn-preamble.ts +53 -15
- package/src/dashboard/turn-prompt-runtime.ts +4 -2
- package/src/decisions/linear-progress-summary.ts +78 -0
- package/src/decisions/linear-progress-sync.ts +152 -0
- package/src/domains/outbound-alert.ts +49 -11
- package/src/domains/telegram-kind-route.ts +16 -9
- package/src/graph-runner/arg-allowance.ts +13 -0
- package/src/graph-runner/graph-cli.ts +23 -7
- package/src/graph-runner/graph-run-api.ts +3 -1
- package/src/graph-runner/graph-tick.ts +10 -2
- package/src/graph-runner/runner.ts +86 -18
- package/src/graph-wizard/mission-compose.ts +407 -12
- package/src/grok/agent-search.ts +14 -4
- package/src/grok/credential.ts +28 -11
- package/src/harness/dispatch-backpressure.ts +54 -1
- package/src/harness/dispatch-shadow-compare.ts +74 -0
- package/src/harness/harness-cli-command.ts +11 -1
- package/src/harness/harness-pod-dispatch.ts +81 -15
- package/src/harness/harness-stop.ts +155 -11
- package/src/harness/skill-exec.ts +21 -9
- package/src/harness/skill-select.ts +1 -1
- package/src/hooks/error-report-cloud.ts +101 -0
- package/src/hooks/receiver.ts +29 -2
- package/src/index.ts +159 -13
- package/src/instance/spawn-elanous.ts +6 -4
- package/src/intake-plane/actions.ts +354 -0
- package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
- package/src/intake-plane/intake-sources.ts +78 -8
- package/src/intake-plane/items.ts +14 -4
- package/src/intake-plane/linear-mission-sync.ts +80 -0
- package/src/intake-plane/linear-secretary-runtime.ts +178 -0
- package/src/intake-plane/linear-wish.ts +227 -1
- package/src/life/life-cli.ts +168 -0
- package/src/life/life-kinds.ts +160 -0
- package/src/live-supply/budget-consumer.ts +78 -0
- package/src/live-supply/read.ts +3 -0
- package/src/live-supply/snapshot.ts +45 -0
- package/src/llm/provider-credentials.ts +8 -2
- package/src/llm.ts +168 -9
- package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
- package/src/loops/orchestrator/tick.ts +13 -0
- package/src/maturity/feature-maturity.ts +4 -4
- package/src/msg/msg-sse-server.ts +3 -3
- package/src/msg/msg-store.ts +177 -19
- package/src/native-tool-catalog.ts +38 -4
- package/src/nexus/api/harness-traversal.ts +11 -0
- package/src/nexus/api/http-server.ts +37 -1
- package/src/nexus/api/mcp-public-allowlist.ts +2 -0
- package/src/nexus/index.ts +7 -2
- package/src/nexus/outbound/format.ts +9 -0
- package/src/nexus/outbound/router.ts +98 -13
- package/src/nexus/setup-status.ts +9 -0
- package/src/nexus/state/state.ts +3 -0
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-owner-mirror.ts +44 -0
- package/src/oauth/codex.ts +17 -2
- package/src/oauth/fallback-chain.ts +47 -17
- package/src/onboarding/first-run-doctor.ts +8 -1
- package/src/onboarding/first-run.ts +85 -26
- package/src/onboarding/key-setup.ts +103 -0
- package/src/onboarding/menu-answer.ts +13 -0
- package/src/onboarding/secret-prompt.ts +37 -0
- package/src/plugins/install/plugin-install.ts +59 -0
- package/src/pr-tool/census.ts +133 -2
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/pty-shell/tui-run-state.ts +188 -2
- package/src/registry/catalog-server.ts +232 -0
- package/src/registry/loader.ts +45 -1
- package/src/registry/types.ts +1 -2
- package/src/release-loop/checklist-target-path-hint.ts +13 -0
- package/src/release-loop/checklist.ts +9 -1
- package/src/repl/index.ts +43 -2
- package/src/research/axis-fanout.ts +136 -16
- package/src/research/bloom-exemplars.ts +3 -1
- package/src/research/gap-followup.ts +13 -1
- package/src/research/plugin-discovery.ts +36 -14
- package/src/research-bridge/invoke.ts +22 -5
- package/src/research-bridge/types.ts +2 -0
- package/src/self-dev/ask-launch-flow.ts +72 -1
- package/src/self-dev/decompose.ts +119 -5
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +5 -0
- package/src/self-dev/draft-residue.ts +64 -5
- package/src/self-dev/graph-front-nodes.ts +2 -1
- package/src/self-dev/graph-journey-route.ts +76 -21
- package/src/self-dev/launch-preflight-text.ts +5 -6
- package/src/self-dev/launch-preflight.ts +58 -0
- package/src/self-dev/orchestrate.ts +13 -3
- package/src/self-dev/review-provider-fallback.ts +9 -2
- package/src/self-dev/run-supervisor.ts +42 -4
- package/src/self-dev/run-types.ts +4 -0
- package/src/self-dev/shard-aggregate.ts +4 -0
- package/src/self-dev/shard-run.ts +36 -15
- package/src/self-implement/abandoned-classification.ts +12 -3
- package/src/self-implement/budget-gate.ts +7 -0
- package/src/self-implement/child-llm-preference.ts +10 -1
- package/src/self-implement/doctor-visit.ts +118 -8
- package/src/self-implement/elanous-tui-spawn.ts +3 -0
- package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
- package/src/self-implement/gate-artifacts.ts +2 -1
- package/src/self-implement/goal-author-cli.ts +4 -2
- package/src/self-implement/goal-author.ts +684 -7
- package/src/self-implement/graph-overlay-yaml.ts +37 -4
- package/src/self-implement/graph-overlay.ts +3 -1
- package/src/self-implement/graph-profile-yaml.ts +107 -0
- package/src/self-implement/graph-yaml.ts +26 -3
- package/src/self-implement/headless-elanous-driver.ts +31 -2
- package/src/self-implement/heal-intake.ts +112 -4
- package/src/self-implement/heal-triage.ts +20 -0
- package/src/self-implement/host-regate.ts +27 -4
- package/src/self-implement/merge-train.ts +5 -0
- package/src/self-implement/off-diff-evidence.ts +249 -5
- package/src/self-implement/orchestrator.ts +365 -25
- package/src/self-implement/regate-detail.ts +38 -1
- package/src/self-implement/rework-child-provider.ts +25 -0
- package/src/self-implement/run-chart.ts +122 -0
- package/src/self-implement/run-ledger.ts +162 -11
- package/src/self-implement/run-stop.ts +188 -4
- package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
- package/src/self-implement/stop-autoheal.ts +13 -0
- package/src/self-implement/tdd-evidence-tags.ts +9 -0
- package/src/self-implement/train-gate-receipt.ts +166 -0
- package/src/self-implement/train-gate-remote.ts +62 -18
- package/src/session/chat.ts +40 -4
- package/src/session/session-fanout.ts +2 -0
- package/src/session/streaming/acp-stream-sink.ts +2 -1
- package/src/session/streaming/chunk-producer.ts +6 -0
- package/src/session/streaming/stream-compositor.ts +3 -2
- package/src/session-runtime/index.ts +135 -5
- package/src/session-runtime/retry-policy.ts +1 -1
- package/src/session-runtime/tier-flip.ts +3 -3
- package/src/setup/llm-env-detect.ts +3 -0
- package/src/setup/service-key-catalog.ts +46 -0
- package/src/setup/service-keys.ts +241 -0
- package/src/sidetab-core/model.ts +19 -5
- package/src/sidetab-core/visible-agent-mission.ts +262 -0
- package/src/skills/name-match.ts +20 -0
- package/src/skills/tools/agent.ts +53 -6
- package/src/skills/tools/omni-search.ts +173 -13
- package/src/task-agent/parent-host.ts +10 -0
- package/src/task-agent/pod-distributor-entry.ts +3 -0
- package/src/task-agent/repair-outcomes.ts +65 -0
- package/src/task-agent/task-hand.ts +47 -7
- package/src/task-orchestrator/dispatcher.ts +14 -1
- package/src/task-orchestrator/linear-capture-events.ts +55 -0
- package/src/task-orchestrator/store.ts +16 -5
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
- package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
- package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +178 -16
- package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +237 -41
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +337 -51
- package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
- package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
- package/src/task-orchestrator/types.ts +14 -0
- package/src/telegram.ts +14 -16
- package/src/terminal/coding-agent.ts +14 -5
- package/src/terminal/session-registry.ts +1 -1
- package/src/tokens.ts +35 -2
- package/src/tool-hints/gate.ts +1 -0
- package/src/tool-runtime/agent-runtime.ts +2 -0
- package/src/tool-runtime/browser-hand-runtime.ts +381 -0
- package/src/tool-runtime/browser-runtime.ts +2 -1
- package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
- package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
- package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
- package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
- package/src/tool-runtime/index.ts +6 -0
- package/src/tool-runtime/skill-exec-runtime.ts +33 -13
- package/src/tool-runtime/types.ts +4 -0
- package/src/tui/entry.ts +38 -5
- package/src/tui/sidetab/attach.ts +177 -1
- package/src/tui/sidetab/herdr-portal.ts +225 -0
- package/src/tui-client/local-chat-turn.ts +26 -13
- package/src/tui.ts +22 -0
- package/src/user-config.ts +34 -9
- package/src/user-intent/types.ts +4 -3
- package/src/ux-sim/browser-hand.ts +165 -0
- package/src/ux-sim/draft-inventory-builder.ts +198 -0
- package/src/ux-sim/fake-browser-page.ts +81 -0
- package/src/ux-sim/fake-kubectl.ts +37 -3
- package/src/ux-sim/fake-linear-device.ts +31 -0
- package/src/ux-sim/fault-pool-cap.ts +11 -6
- package/src/ux-sim/graph-engine-sim.ts +47 -0
- package/src/ux-sim/linear-secretary.ts +216 -0
- package/src/ux-sim/mock-scenario-catalog.json +93 -0
- package/src/ux-sim/mock-scenario-catalog.ts +274 -0
- package/src/ux-sim/onboarding-first-run-device.ts +31 -21
- package/src/ux-sim/scenario.ts +185 -48
- package/src/ux-sim/service-key-setup.ts +50 -0
- package/src/ux-sim/term-slash-device.ts +74 -0
- package/src/ux-sim/turn-throw-sim.ts +31 -0
- package/src/version/packed-revision.json +1 -1
- package/src/voice/voice-tts-singleton.ts +18 -3
- package/src/web-search/exa.ts +77 -0
- package/src/web-search/grok.ts +5 -9
- package/src/web-search/index.ts +30 -9
- package/src/web-search/provider.ts +4 -1
- package/src/web-search/x-intent.ts +5 -0
- package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +0 -90
- package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +0 -1
- package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +0 -32
- package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +0 -79
- package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +0 -148
- package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +0 -226
- package/apps/pwa/out/_next/static/chunks/4667.97e31aa38c95c475.js +0 -309
- package/apps/pwa/out/_next/static/chunks/4702.4a4adc1f16d7c93b.js +0 -64
- package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +0 -24
- package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +0 -286
- package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +0 -62
- package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +0 -122
- package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8050-9b364bdef8f71927.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +0 -104
- package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +0 -34
- package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-14949db884bfa672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +0 -1
- package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
- package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
- /package/apps/pwa/out/_next/static/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { classifyObservation } from '../design/behaviour-signal.js';
|
|
2
2
|
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync, type Dirent } from 'node:fs';
|
|
3
|
-
import { spawn } from 'node:child_process';
|
|
3
|
+
import { execFileSync, spawn } from 'node:child_process';
|
|
4
4
|
import { randomBytes } from 'node:crypto';
|
|
5
5
|
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path';
|
|
6
6
|
import { isRepositoryImplementationCandidate, type CodebaseGrounding } from '../autopilot/codebase-grounding.js';
|
|
@@ -10,6 +10,7 @@ import type { LLMUsage } from '../prompt-cache/types.js';
|
|
|
10
10
|
import { debug } from '../debug/log.js';
|
|
11
11
|
import { ensureDeviceFirstSteps, inspectDeviceFirstGoal } from './device-first.js';
|
|
12
12
|
import { COMPLETION_BOUNDARY_STEP_PREFIX, FOLDED_DEVICE_FIRST_ACTION_MARKER } from './goal-author-decompose.js';
|
|
13
|
+
import { loadMockScenarioCatalog, type MockScenarioDevice, type MockScenarioEntry } from '../ux-sim/mock-scenario-catalog.js';
|
|
13
14
|
|
|
14
15
|
function observeGoalAuthor(
|
|
15
16
|
category: 'goal-author' | 'goal-author.clarify',
|
|
@@ -20,6 +21,7 @@ function observeGoalAuthor(
|
|
|
20
21
|
debug.log(category === 'goal-author' ? 'harness.author' : 'harness.author.clarify', event, data);
|
|
21
22
|
}
|
|
22
23
|
import { getUserConfig } from '../user-config.js';
|
|
24
|
+
import { getProviderForConfig, streamLLM, type LLMMessage } from '../llm.js';
|
|
23
25
|
|
|
24
26
|
export type GoalAuthorGrade = 'full' | 'lite';
|
|
25
27
|
export type GoalAuthorGradeSource = 'flag' | 'env' | 'config' | 'default';
|
|
@@ -79,6 +81,10 @@ export interface GoalAuthorDeps {
|
|
|
79
81
|
ground: (ask: string, groundingDeps?: GoalAuthorGroundingDeps) => Promise<CodebaseGrounding>;
|
|
80
82
|
persistentGrounding?: GoalAuthorGroundingDeps;
|
|
81
83
|
authorGrade?: GoalAuthorGradeSelection;
|
|
84
|
+
/** Production Terra reviewer precheck; omitted is disabled unless the shared config switch is on. */
|
|
85
|
+
reviewerPrecheckEnabled?: boolean;
|
|
86
|
+
/** Optional seam for focused tests; production uses the pinned Terra medium reviewer. */
|
|
87
|
+
reviewerPrecheck?: (document: string, authorRunId: string) => Promise<GoalAuthorReviewerPrecheckResult>;
|
|
82
88
|
enhance: (ask: string, opts?: EnhanceOpts) => Promise<GoalEnhancement>;
|
|
83
89
|
/** Additive enhancer options supplied by the file-writing entrypoint. */
|
|
84
90
|
enhanceOpts?: EnhanceOpts;
|
|
@@ -121,6 +127,12 @@ export interface GoalAuthorDeps {
|
|
|
121
127
|
decomposeSteps?: (objective: string, opts?: { context?: string; runId?: string; goalId?: string }) => Promise<readonly string[]>;
|
|
122
128
|
/** Optional launch preflight result supplied by the caller; authoring never reads the ledger or logs itself. */
|
|
123
129
|
launchPreflight?: LaunchPreflightResult;
|
|
130
|
+
/**
|
|
131
|
+
* SELF-REVIEW-PRELAUNCH ⑤ — 완료 경계 증거 명령이 «현재 main» 에서 실행 가능한지 판정하는
|
|
132
|
+
* 읽기 전용 존재 심. 저작 코어(`authorGoal`)는 파일을 열지 않으므로 심이 없으면 판정을
|
|
133
|
+
* `not-applicable` 로 남기고, 생산 진입점(`writeAuthoredGoal`)이 repositoryRoot 기준 심을 공급한다.
|
|
134
|
+
*/
|
|
135
|
+
selfReviewExistsOnMain?: (repositoryRelativePath: string) => boolean | undefined;
|
|
124
136
|
/** Optional in-process notification for each authored-goal phase transition. */
|
|
125
137
|
onProgress?: (phase: GoalAuthorPhase, event: 'start' | 'end') => void;
|
|
126
138
|
/** AUTHOR-TIMEBOX: budget for the `ground` phase. Omitted means `GOAL_AUTHOR_GROUND_TIMEBOX_MS`. */
|
|
@@ -131,6 +143,209 @@ export interface GoalAuthorDeps {
|
|
|
131
143
|
authoringLessons?: string;
|
|
132
144
|
}
|
|
133
145
|
|
|
146
|
+
export interface GoalAuthorReviewerPrecheckResult {
|
|
147
|
+
readonly suggestions: readonly string[];
|
|
148
|
+
readonly fixes: readonly string[];
|
|
149
|
+
/** Exact, replayable edits in fixes order; together they must explain the entire document diff. */
|
|
150
|
+
readonly fixEvidence?: readonly { readonly fix: string; readonly originalText: string; readonly revisedText: string }[];
|
|
151
|
+
readonly remainingNeedsHuman: readonly string[];
|
|
152
|
+
readonly revisedDocument: string;
|
|
153
|
+
readonly appliedFixes: readonly string[];
|
|
154
|
+
readonly unappliedItems: readonly string[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const GOAL_AUTHOR_REVIEWER_PRECHECK_MODEL = 'gpt-6.1-terra';
|
|
158
|
+
|
|
159
|
+
export function parseGoalAuthorReviewerPrecheck(raw: string): GoalAuthorReviewerPrecheckResult {
|
|
160
|
+
const text = raw.trim().replace(/^```(?:json)?\s*/iu, '').replace(/\s*```$/u, '');
|
|
161
|
+
const value: unknown = JSON.parse(text);
|
|
162
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('reviewer response must be an object');
|
|
163
|
+
const record = value as Record<string, unknown>;
|
|
164
|
+
const readList = (key: string): string[] => {
|
|
165
|
+
const candidate = record[key];
|
|
166
|
+
if (!Array.isArray(candidate) || candidate.some((item) => typeof item !== 'string')) {
|
|
167
|
+
throw new Error(`reviewer response ${key} must be a string array`);
|
|
168
|
+
}
|
|
169
|
+
return candidate;
|
|
170
|
+
};
|
|
171
|
+
const revisedDocument = record.revisedDocument;
|
|
172
|
+
if (typeof revisedDocument !== 'string' || !revisedDocument.trim()) throw new Error('reviewer response revisedDocument must be non-empty text');
|
|
173
|
+
return {
|
|
174
|
+
suggestions: readList('suggestions'),
|
|
175
|
+
fixes: readList('fixes'),
|
|
176
|
+
...(record.fixEvidence === undefined ? {} : {
|
|
177
|
+
fixEvidence: (() => {
|
|
178
|
+
const candidate = record.fixEvidence;
|
|
179
|
+
if (!Array.isArray(candidate) || candidate.some((item) => !item || typeof item !== 'object'
|
|
180
|
+
|| typeof (item as Record<string, unknown>).fix !== 'string'
|
|
181
|
+
|| typeof (item as Record<string, unknown>).originalText !== 'string'
|
|
182
|
+
|| typeof (item as Record<string, unknown>).revisedText !== 'string')) {
|
|
183
|
+
throw new Error('reviewer response fixEvidence must be an array of { fix, originalText, revisedText }');
|
|
184
|
+
}
|
|
185
|
+
return candidate as { fix: string; originalText: string; revisedText: string }[];
|
|
186
|
+
})(),
|
|
187
|
+
}),
|
|
188
|
+
remainingNeedsHuman: readList('remainingNeedsHuman'),
|
|
189
|
+
revisedDocument,
|
|
190
|
+
appliedFixes: [],
|
|
191
|
+
unappliedItems: [],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function reviewerRevisionIsValid(original: string, revised: string): boolean {
|
|
196
|
+
if (!revised.trim() || verbatimOriginalAsk(revised) !== verbatimOriginalAsk(original)) return false;
|
|
197
|
+
if (parseGoalId(revised) !== parseGoalId(original)
|
|
198
|
+
|| parseRootIntent(revised) !== parseRootIntent(original)
|
|
199
|
+
|| parseGoalType(revised) !== parseGoalType(original)) return false;
|
|
200
|
+
if (JSON.stringify(canonicalBlocks(revised)) !== JSON.stringify(canonicalBlocks(original))) return false;
|
|
201
|
+
return !lintGoalFile(revised, 'reviewer-precheck').some((finding) => finding.level === 'ERROR');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function reviewerEditIsGrounded(original: string, edit: { fix: string; originalText: string; revisedText: string }): boolean {
|
|
205
|
+
if (!edit.originalText || edit.revisedText === edit.originalText || !edit.revisedText.startsWith(edit.originalText)) return false;
|
|
206
|
+
const acceptanceStart = original.indexOf('## ACCEPTANCE CRITERIA');
|
|
207
|
+
const evidenceStart = original.indexOf('## REQUIRED EVIDENCE');
|
|
208
|
+
const nextHeading = (start: number): number => {
|
|
209
|
+
const next = original.indexOf('\n## ', start + 1);
|
|
210
|
+
return next < 0 ? original.length : next;
|
|
211
|
+
};
|
|
212
|
+
const editStart = original.indexOf(edit.originalText);
|
|
213
|
+
if (editStart < 0 || original.indexOf(edit.originalText, editStart + edit.originalText.length) >= 0) return false;
|
|
214
|
+
const sectionTexts = [
|
|
215
|
+
acceptanceStart >= 0 ? original.slice(acceptanceStart + '## ACCEPTANCE CRITERIA'.length, nextHeading(acceptanceStart)) : '',
|
|
216
|
+
evidenceStart >= 0 ? original.slice(evidenceStart + '## REQUIRED EVIDENCE'.length, nextHeading(evidenceStart)) : '',
|
|
217
|
+
];
|
|
218
|
+
const isCompleteCriterion = sectionTexts.some((section) => section.split('\n').some((line) =>
|
|
219
|
+
/^\s*[-*]\s+\S/u.test(line) && line.trim() === edit.originalText.trim()));
|
|
220
|
+
if (!isCompleteCriterion) return false;
|
|
221
|
+
const appended = edit.revisedText.slice(edit.originalText.length);
|
|
222
|
+
if (!/^\r?\n[ \t]*[-*][ \t]+\S/u.test(appended)) return false;
|
|
223
|
+
const added = appended
|
|
224
|
+
.replace(/^\r?\n[ \t]*[-*][ \t]*/u, '')
|
|
225
|
+
.replace(/^\[[a-z-]+\][ \t]*/iu, '')
|
|
226
|
+
.trim();
|
|
227
|
+
if (edit.fix !== added) return false;
|
|
228
|
+
const ask = verbatimOriginalAsk(original);
|
|
229
|
+
if (!added || !ask) return false;
|
|
230
|
+
const sentences = ask
|
|
231
|
+
.split(/(?<=[.!?])(?:[ \t]+|$)|\r?\n/u)
|
|
232
|
+
.map((sentence) => sentence.trim())
|
|
233
|
+
.filter(Boolean);
|
|
234
|
+
return sentences.includes(added);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function resolveGoalAuthorReviewerPrecheckEnabled(config = getUserConfig()): boolean {
|
|
238
|
+
return config.tools.selfImplement.goalAuthorReviewerPrecheck === true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export async function runGoalAuthorReviewerPrecheck(
|
|
242
|
+
document: string,
|
|
243
|
+
deps: { config?: ReturnType<typeof getUserConfig>; stream?: typeof streamLLM } = {},
|
|
244
|
+
): Promise<GoalAuthorReviewerPrecheckResult> {
|
|
245
|
+
const config = deps.config ?? getUserConfig();
|
|
246
|
+
const pinnedConfig = {
|
|
247
|
+
...config,
|
|
248
|
+
llm: { ...config.llm, provider: 'openai-codex' as const, model: GOAL_AUTHOR_REVIEWER_PRECHECK_MODEL },
|
|
249
|
+
};
|
|
250
|
+
const provider = getProviderForConfig(pinnedConfig, GOAL_AUTHOR_REVIEWER_PRECHECK_MODEL);
|
|
251
|
+
const prompt = [
|
|
252
|
+
'Review this completed goal document before it is written. Return only JSON with string-array fields suggestions, fixes, remainingNeedsHuman, a fixEvidence array of { fix, originalText, revisedText }, and a revisedDocument string.',
|
|
253
|
+
'Apply each necessary fix to revisedDocument exactly once while preserving the original ask, GoalId, RootIntent, GoalType, every existing criterion and scope boundary, and canonical section structure. Be strictly conservative: only append one complete sentence copied verbatim from the original ask to an existing acceptance-criteria or required-evidence line; never append a partial substring or clause, especially one inside a negation or condition, and do not delete or reword existing text, add new scope, or edit other sections. For every fixes item, include one fixEvidence object in the same order: fixes item and fix must both equal the exact complete sentence appended from the original ask; originalText and revisedText must be exact spans where revisedText starts with originalText and appends that sentence, and replaying every single replacement reproduces the complete revisedDocument with no other edits. If you cannot explain and ground every change this way, return no fixes and leave revisedDocument byte-for-byte unchanged. Keep optional suggestions separate; list unresolved decisions or evidence as remainingNeedsHuman.',
|
|
254
|
+
document,
|
|
255
|
+
].join('\n\n');
|
|
256
|
+
const messages: LLMMessage[] = [{ role: 'user', content: prompt }];
|
|
257
|
+
let actualProvider = provider.name;
|
|
258
|
+
let actualModel = GOAL_AUTHOR_REVIEWER_PRECHECK_MODEL;
|
|
259
|
+
const raw = await (deps.stream ?? streamLLM)(messages, () => undefined, {
|
|
260
|
+
provider,
|
|
261
|
+
model: GOAL_AUTHOR_REVIEWER_PRECHECK_MODEL,
|
|
262
|
+
reasoningEffort: 'medium',
|
|
263
|
+
maxTokens: 3000,
|
|
264
|
+
usageRole: 'review',
|
|
265
|
+
usagePhase: 'author-reviewer-precheck',
|
|
266
|
+
usageSite: 'author-reviewer-precheck',
|
|
267
|
+
onResolvedProvider: (resolvedProvider, resolvedModel) => { actualProvider = resolvedProvider; actualModel = resolvedModel; },
|
|
268
|
+
});
|
|
269
|
+
debug.log('author.reviewer-precheck', 'response', { provider: actualProvider, model: actualModel, responseChars: raw.length });
|
|
270
|
+
return parseGoalAuthorReviewerPrecheck(raw);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export async function executeGoalAuthorReviewerPrecheck(
|
|
274
|
+
enabled: boolean,
|
|
275
|
+
document: string,
|
|
276
|
+
authorRunId: string,
|
|
277
|
+
run: (document: string) => Promise<GoalAuthorReviewerPrecheckResult> = (value) => runGoalAuthorReviewerPrecheck(value),
|
|
278
|
+
observe: (event: string, data: Record<string, unknown>) => void = (event, data) => debug.log('author.reviewer-precheck', event, data),
|
|
279
|
+
): Promise<{ status: 'skipped' | 'completed' | 'rejected-soft' | 'failed-soft'; result?: GoalAuthorReviewerPrecheckResult }> {
|
|
280
|
+
if (!enabled) {
|
|
281
|
+
observe('precheck-skipped', { authorRunId, reason: 'disabled', providerCalls: 0 });
|
|
282
|
+
return { status: 'skipped' };
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
const proposed = await run(document);
|
|
286
|
+
const evidence = proposed.fixEvidence ?? [];
|
|
287
|
+
let replayed = document;
|
|
288
|
+
let fixesSupported = proposed.fixes.length === 0
|
|
289
|
+
? proposed.revisedDocument === document && evidence.length === 0
|
|
290
|
+
: evidence.length === proposed.fixes.length;
|
|
291
|
+
if (fixesSupported) {
|
|
292
|
+
for (let index = 0; index < proposed.fixes.length; index += 1) {
|
|
293
|
+
const edit = evidence[index];
|
|
294
|
+
if (!edit || edit.fix !== proposed.fixes[index] || !reviewerEditIsGrounded(document, edit) || !replayed.includes(edit.originalText)) {
|
|
295
|
+
fixesSupported = false;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
const at = replayed.indexOf(edit.originalText);
|
|
299
|
+
if (replayed.indexOf(edit.originalText, at + edit.originalText.length) !== -1) {
|
|
300
|
+
fixesSupported = false;
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
replayed = replayed.slice(0, at) + edit.revisedText + replayed.slice(at + edit.originalText.length);
|
|
304
|
+
}
|
|
305
|
+
fixesSupported = fixesSupported && replayed === proposed.revisedDocument;
|
|
306
|
+
}
|
|
307
|
+
const valid = reviewerRevisionIsValid(document, proposed.revisedDocument)
|
|
308
|
+
&& fixesSupported
|
|
309
|
+
&& (proposed.fixes.length === 0 || proposed.revisedDocument !== document);
|
|
310
|
+
const result: GoalAuthorReviewerPrecheckResult = valid
|
|
311
|
+
? { ...proposed, appliedFixes: proposed.fixes, unappliedItems: [] }
|
|
312
|
+
: {
|
|
313
|
+
...proposed,
|
|
314
|
+
revisedDocument: document,
|
|
315
|
+
appliedFixes: [],
|
|
316
|
+
unappliedItems: proposed.fixes,
|
|
317
|
+
remainingNeedsHuman: [...new Set([...proposed.remainingNeedsHuman, ...proposed.fixes])],
|
|
318
|
+
};
|
|
319
|
+
const status = valid ? 'completed' : 'rejected-soft';
|
|
320
|
+
observe(valid ? 'completed' : 'revision-rejected', {
|
|
321
|
+
authorRunId,
|
|
322
|
+
provider: 'openai-codex',
|
|
323
|
+
model: GOAL_AUTHOR_REVIEWER_PRECHECK_MODEL,
|
|
324
|
+
status,
|
|
325
|
+
proposedSuggestionCount: result.suggestions.length,
|
|
326
|
+
proposedFixCount: result.fixes.length,
|
|
327
|
+
appliedFixCount: result.appliedFixes.length,
|
|
328
|
+
appliedFixes: result.appliedFixes,
|
|
329
|
+
fixEvidence: result.fixEvidence ?? [],
|
|
330
|
+
correctedItems: result.appliedFixes.length,
|
|
331
|
+
unappliedItemCount: result.unappliedItems.length,
|
|
332
|
+
unappliedItems: result.unappliedItems,
|
|
333
|
+
remainingNeedsHuman: result.remainingNeedsHuman,
|
|
334
|
+
suggestionsResult: result.suggestions,
|
|
335
|
+
fixesResult: result.fixes,
|
|
336
|
+
remainingNeedsHumanResult: result.remainingNeedsHuman,
|
|
337
|
+
});
|
|
338
|
+
return { status, result };
|
|
339
|
+
} catch (error) {
|
|
340
|
+
observe('failed-soft', {
|
|
341
|
+
authorRunId,
|
|
342
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
343
|
+
correctedItems: 0,
|
|
344
|
+
});
|
|
345
|
+
return { status: 'failed-soft' };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
134
349
|
export type GoalAuthorGroundingPath = 'groundMissionInCodebase';
|
|
135
350
|
|
|
136
351
|
export interface GoalAuthorGroundingDeps {
|
|
@@ -657,9 +872,139 @@ export function inspectGoalDoneBoundary(document: string): { values: Partial<Rec
|
|
|
657
872
|
return { values, missing: GOAL_DONE_BOUNDARY_LABELS.filter((label) => !values[label]) };
|
|
658
873
|
}
|
|
659
874
|
|
|
660
|
-
|
|
875
|
+
function goalDoneTestPaths(targetPath: string): string[] {
|
|
876
|
+
if (/\.(?:test|spec)\.[cm]?[jt]sx?$/i.test(targetPath)) return [targetPath];
|
|
877
|
+
const source = /^(.*)\.([cm]?[jt]sx?)$/i.exec(targetPath);
|
|
878
|
+
if (!source) return [`${targetPath}.test.ts`, `${targetPath}.spec.ts`];
|
|
879
|
+
const extension = source[2]!.toLowerCase();
|
|
880
|
+
const siblingExtensions = extension === 'tsx' ? ['tsx', 'ts'] : extension === 'jsx' ? ['jsx', 'js'] : extension === 'ts' ? ['ts', 'tsx'] : extension === 'js' ? ['js', 'jsx'] : [extension];
|
|
881
|
+
return siblingExtensions.flatMap((testExtension) => [`${source[1]}.test.${testExtension}`, `${source[1]}.spec.${testExtension}`]);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function bunTestEvidencePath(command: string | undefined): string | undefined {
|
|
885
|
+
if (command === undefined) return undefined;
|
|
886
|
+
return /^bun\s+test\s+(?:(?:--\s+)?)(\S+\.(?:test|spec)\.[cm]?[jt]sx?)(?:\s|$)/u.exec(unwrapGoalDoneValue(command))?.[1];
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
function goalPathTokens(paths: readonly string[]): Set<string> {
|
|
890
|
+
return new Set(paths.map((path) => path.split(/[\\/]/u).at(-1) ?? path)
|
|
891
|
+
.flatMap((path) => path.toLowerCase().split(/[._-]+/u))
|
|
892
|
+
.filter((token) => token.length > 2 && !['src', 'test', 'tests', 'spec', 'tsx', 'ts', 'jsx', 'js'].includes(token)));
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
function goalPathStems(paths: readonly string[]): Set<string> {
|
|
896
|
+
return new Set(paths.map((path) => (path.split(/[\\/]/u).at(-1) ?? path).toLowerCase()
|
|
897
|
+
.replace(/\.(?:test|spec)\.[^.]+$/u, '')
|
|
898
|
+
.replace(/\.[^.]+$/u, '')));
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
function matchingPathCount(paths: readonly string[], targetPaths: readonly string[]): number {
|
|
902
|
+
const targetStems = goalPathStems(targetPaths);
|
|
903
|
+
if ([...goalPathStems(paths)].some((stem) => targetStems.has(stem))) return 10;
|
|
904
|
+
const targetTokens = goalPathTokens(targetPaths);
|
|
905
|
+
return [...goalPathTokens(paths)].filter((token) => targetTokens.has(token)).length;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
function behaviorTokens(value: string): Set<string> {
|
|
909
|
+
const stop = new Set(['the', 'and', 'with', 'from', 'this', 'that', 'when', 'then', 'into', 'only', 'are', 'is', 'for', 'bun', 'test', 'code', 'boundary', 'request', 'expected', 'target', 'file', '완료', '경계', '증거', '명령', '대상', '요청', '기대', '시험', '확인', '시나리오']);
|
|
910
|
+
return new Set((value.toLowerCase().match(/[\p{L}\p{N}]{2,}/gu) ?? []).filter((token) => !stop.has(token)));
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function matchingScenarioBehaviorCount(scenario: MockScenarioEntry, ask: string): number {
|
|
914
|
+
const { values } = inspectGoalDoneBoundary(ask);
|
|
915
|
+
const requestedText = `${values['완료 경계 코드'] ?? ''} ${values['완료 경계 실물'] ?? ''}`;
|
|
916
|
+
const describedText = `${scenario.name} ${scenario.kind} ${scenario.trigger} ${scenario.observe.join(' ')} ${scenario.expected}`;
|
|
917
|
+
const requested = behaviorTokens(requestedText);
|
|
918
|
+
const described = behaviorTokens(describedText);
|
|
919
|
+
const polarity = (text: string, token: string): boolean => {
|
|
920
|
+
const words = text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
921
|
+
return words.some((word, index) => word === token && words.slice(Math.max(0, index - 3), index).some((nearby) => /^(?:not|never|no|without|isn't|doesn't|않|못|아니)/u.test(nearby)));
|
|
922
|
+
};
|
|
923
|
+
const oppositePairs = [
|
|
924
|
+
['distinct', 'indistinguishable'], ['preserved', 'lost'], ['visible', 'hidden'], ['visible', 'invisible'],
|
|
925
|
+
['harvestable', 'unharvestable'], ['independent', 'dependent'], ['succeeds', 'fails'], ['accepted', 'rejected'],
|
|
926
|
+
];
|
|
927
|
+
const shared = [...described].filter((token) => requested.has(token));
|
|
928
|
+
if (shared.some((token) => polarity(requestedText, token) !== polarity(describedText, token))
|
|
929
|
+
|| oppositePairs.some(([left, right]) => (requested.has(left) && described.has(right)) || (requested.has(right) && described.has(left)))) return 0;
|
|
930
|
+
return shared.length;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
function nextGoalScenarioId(catalogIds: readonly string[], targets: readonly string[]): string {
|
|
934
|
+
const targetName = targets.map((path) => path.split(/[\\/]/u).at(-1) ?? '')
|
|
935
|
+
.map((name) => name.replace(/\.[^.]+$/u, '').replace(/\.(?:test|spec)$/u, ''))
|
|
936
|
+
.find(Boolean) ?? 'TARGET';
|
|
937
|
+
const slug = targetName.toUpperCase().replace(/[^A-Z0-9]+/gu, '-').replace(/^-|-$/gu, '').slice(0, 32) || 'TARGET';
|
|
938
|
+
const prefix = `MK-${slug}-TDD-EVIDENCE`;
|
|
939
|
+
const existing = new Set(catalogIds);
|
|
940
|
+
for (let sequence = 1; sequence <= 99; sequence++) {
|
|
941
|
+
const candidate = `${prefix}-${String(sequence).padStart(2, '0')}`;
|
|
942
|
+
if (!existing.has(candidate)) return candidate;
|
|
943
|
+
}
|
|
944
|
+
return `${prefix}-${Date.now().toString(36).toUpperCase()}`;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
function selectGoalMockStage(ask: string, targets: readonly string[]): { device: MockScenarioDevice; scenario?: MockScenarioEntry } | undefined {
|
|
948
|
+
const catalog = loadMockScenarioCatalog();
|
|
949
|
+
const device = catalog.devices
|
|
950
|
+
.map((candidate) => ({ candidate, score: matchingPathCount([...candidate.implementation, ...candidate.tests], targets) }))
|
|
951
|
+
.filter((entry) => entry.score >= 2)
|
|
952
|
+
.sort((left, right) => right.score - left.score)[0]?.candidate
|
|
953
|
+
?? (/(?:author|goal|mission|저작|골|미션)/iu.test(`${targets.join(' ')}\n${ask}`)
|
|
954
|
+
? catalog.devices.find((candidate) => candidate.id === 'product-devices')
|
|
955
|
+
: catalog.devices.find((candidate) => candidate.id === 'scenario-runner'));
|
|
956
|
+
if (!device) return undefined;
|
|
957
|
+
const scenario = catalog.scenarios
|
|
958
|
+
.filter((candidate) => candidate.device === device.id)
|
|
959
|
+
.map((candidate) => ({ candidate, pathScore: matchingPathCount([...candidate.implementation, ...candidate.tests], targets), behaviorScore: matchingScenarioBehaviorCount(candidate, ask) }))
|
|
960
|
+
.filter((entry) => entry.pathScore >= 2 && entry.behaviorScore >= 2)
|
|
961
|
+
.sort((left, right) => right.behaviorScore - left.behaviorScore || right.pathScore - left.pathScore)[0]?.candidate;
|
|
962
|
+
return { device, ...(scenario ? { scenario } : {}) };
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
export function explicitGoalDoneBoundaryLines(ask: string, repositoryRoot?: string): string[] {
|
|
661
966
|
const { values } = inspectGoalDoneBoundary(ask);
|
|
662
|
-
|
|
967
|
+
const explicitLines = GOAL_DONE_BOUNDARY_LABELS.flatMap((label) => values[label] ? [`- ${label}: ${values[label]}`] : []);
|
|
968
|
+
// Keep the exported extractor's original contract for callers that only ask
|
|
969
|
+
// for verbatim values. Goal authoring opts into catalog planning by supplying
|
|
970
|
+
// its repository root at the production call sites below.
|
|
971
|
+
if (repositoryRoot === undefined) return explicitLines;
|
|
972
|
+
const unquotedAsk = ask.replace(/```[\s\S]*?```/gu, '');
|
|
973
|
+
const targets = declaredTargetPaths(unquotedAsk);
|
|
974
|
+
const existingEvidence = values['완료 경계 증거 명령'];
|
|
975
|
+
const targetTestPaths = targets.flatMap(goalDoneTestPaths);
|
|
976
|
+
const existingBunTestPath = bunTestEvidencePath(existingEvidence);
|
|
977
|
+
const testPath = targetTestPaths.find((path) => existsSync(resolve(repositoryRoot, path)))
|
|
978
|
+
?? (existingBunTestPath && targetTestPaths.includes(existingBunTestPath) ? existingBunTestPath : undefined)
|
|
979
|
+
?? targetTestPaths[0]
|
|
980
|
+
?? existingBunTestPath;
|
|
981
|
+
const shouldReplaceEvidence = existingBunTestPath === undefined;
|
|
982
|
+
const plannedTestPath = !shouldReplaceEvidence && existingBunTestPath ? existingBunTestPath : testPath;
|
|
983
|
+
const evidenceCommand = shouldReplaceEvidence && testPath ? `bun test ${testPath}` : existingEvidence;
|
|
984
|
+
const needsNewTest = plannedTestPath !== undefined && !existsSync(resolve(repositoryRoot, plannedTestPath));
|
|
985
|
+
const mockStage = targets.length ? selectGoalMockStage(ask, targets) : undefined;
|
|
986
|
+
const lines = GOAL_DONE_BOUNDARY_LABELS.flatMap((label) => {
|
|
987
|
+
if (label === '완료 경계 증거 명령' && evidenceCommand !== undefined) return [`- ${label}: ${evidenceCommand}`];
|
|
988
|
+
return values[label] ? [`- ${label}: ${values[label]}`] : [];
|
|
989
|
+
});
|
|
990
|
+
if (needsNewTest && plannedTestPath) lines.push(`- 신설: ${plannedTestPath}`);
|
|
991
|
+
if (shouldReplaceEvidence && existingEvidence && /type-?check|tsc|typescript/iu.test(existingEvidence)) {
|
|
992
|
+
lines.push(`- 증거 보충: ${existingEvidence} (타입검사는 보조 검증)`);
|
|
993
|
+
}
|
|
994
|
+
if (mockStage) {
|
|
995
|
+
lines.push(`- 장치: ${mockStage.device.id} — ${mockStage.device.name} (카탈로그 경로 일치: ${[...mockStage.device.implementation, ...mockStage.device.tests].filter((path) => matchingPathCount([path], targets) > 0).join(' · ') || mockStage.device.target})`);
|
|
996
|
+
if (mockStage.scenario) {
|
|
997
|
+
lines.push(`- 시나리오: ${mockStage.scenario.id} — ${mockStage.scenario.name}`);
|
|
998
|
+
} else {
|
|
999
|
+
const id = nextGoalScenarioId(loadMockScenarioCatalog().scenarios.map((scenario) => scenario.id), targets);
|
|
1000
|
+
const requestedCode = values['완료 경계 코드'] ?? '요청 대상의 완료 경계';
|
|
1001
|
+
const requestedObservation = values['완료 경계 실물'] ?? '격리 시험에서 요청된 생산 동작과 결과를 관측한다';
|
|
1002
|
+
lines.push(`- 시나리오: 신설 초안 (MS-id 후보: ${id})`);
|
|
1003
|
+
lines.push(`- 시나리오 초안: 사건은 ${targets.join(' · ') || '요청 대상'}에 «${requestedCode}» 경계를 적용한 입력; 기대는 생산 경로에서 «${requestedObservation}»을 관측하고 bun test ${plannedTestPath ?? '<대상 시험 파일>'}로 GREEN을 확인하는 것이다. 자식은 기존 카탈로그 API·ScenarioV0 형식에 맞춰 요청 대상의 사건·기대를 구체화해 등록한다.`);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (plannedTestPath) lines.push(`- 검증 계획(TDD): 장치 ${mockStage?.device.id ?? '미선정'} · 시나리오 ${mockStage?.scenario?.id ?? '신설 초안'} · ${needsNewTest ? '신설 시험' : '기존 시험에 요청 동작 회귀 사례 추가'} ${plannedTestPath} · 피처 시험 bun test ${plannedTestPath}를 구현 전에 RED로 확인한다.`);
|
|
1007
|
+
return lines;
|
|
663
1008
|
}
|
|
664
1009
|
|
|
665
1010
|
/**
|
|
@@ -1013,7 +1358,7 @@ function targetPathsInLabelPiece(piece: string): string[] {
|
|
|
1013
1358
|
return askPathTokens(piece).filter((path) => classifyTracedPathToken(path).kind === 'path');
|
|
1014
1359
|
}
|
|
1015
1360
|
|
|
1016
|
-
function declaredTargetPaths(document: string): string[] {
|
|
1361
|
+
export function declaredTargetPaths(document: string): string[] {
|
|
1017
1362
|
return linesOutsideFencedCode(document).flatMap(({ text }) => {
|
|
1018
1363
|
const match = TARGET_PATH_LABEL.exec(text.trim());
|
|
1019
1364
|
return match ? match[1].split(/\s+[·,]\s*|[·,]\s+/).flatMap(targetPathsInLabelPiece) : [];
|
|
@@ -2529,6 +2874,8 @@ export interface AuthoredGoal {
|
|
|
2529
2874
|
authorRunId: string;
|
|
2530
2875
|
/** AUTHOR-TIMEBOX: present only when the `ground` phase was short-circuited for exceeding its budget. */
|
|
2531
2876
|
groundingTimebox?: GoalAuthorGroundingTimebox;
|
|
2877
|
+
/** Raw structured reviewer output is preserved for the caller and run observability. */
|
|
2878
|
+
reviewerPrecheck?: GoalAuthorReviewerPrecheckResult;
|
|
2532
2879
|
}
|
|
2533
2880
|
|
|
2534
2881
|
/** AUTHOR-TIMEBOX 산출 — 예산과 실제 경과. 둘 다 «잰 값»이고 지어낸 값이 아니다. */
|
|
@@ -5804,6 +6151,278 @@ function acceptanceCriteria(
|
|
|
5804
6151
|
return acceptance;
|
|
5805
6152
|
}
|
|
5806
6153
|
|
|
6154
|
+
// ── SELF-REVIEW-PRELAUNCH — 발사 전 self-review 페이즈(다섯 검사 · 1회 재저작 · 잔여 needs-human) ─────────────
|
|
6155
|
+
/**
|
|
6156
|
+
* ⭐ 저작물이 «발사 전에» 자기를 검열한다 — ask 밖 목표·칸 밖 경로·미래 가정·mock 무대 누락·
|
|
6157
|
+
* main 에서 실행 불가능한 완료 경계 증거 명령을 lint·발사 흐름 «앞에서» 잡는다.
|
|
6158
|
+
* ⛔ 검사 대상은 «모델이 만든 목표 줄»(`- Checkable requested criterion:` · 분해 조각)뿐이다 —
|
|
6159
|
+
* 사람 ask(verbatim 울타리 안)와 저작기의 결정론 계약 줄(완료 경계 3행·보존·배선 줄)은 손대지 않는다.
|
|
6160
|
+
* ⭐ 걸리면 «1회» 재저작한다: ① 상 조각 재분해 ⊕ ② 줄 제거 ⊕ ③ FU(후속 조각) 화.
|
|
6161
|
+
* 그 뒤에도 남으면 «해당 조각만» needs-human verdict 로 남긴다(author.self-review 관측).
|
|
6162
|
+
*/
|
|
6163
|
+
export const GOAL_AUTHOR_SELF_REVIEW_CHECKS = ['slice-difficulty', 'ask-scope', 'future-assumption', 'mock-stage', 'evidence-command'] as const;
|
|
6164
|
+
export type GoalSelfReviewCheck = (typeof GOAL_AUTHOR_SELF_REVIEW_CHECKS)[number];
|
|
6165
|
+
export type GoalSelfReviewVerdict = 'pass' | 'fixed' | 'needs-human' | 'not-applicable';
|
|
6166
|
+
|
|
6167
|
+
export interface GoalSelfReviewItem {
|
|
6168
|
+
readonly check: GoalSelfReviewCheck;
|
|
6169
|
+
readonly verdict: GoalSelfReviewVerdict;
|
|
6170
|
+
readonly detail: string;
|
|
6171
|
+
readonly slice?: string;
|
|
6172
|
+
readonly fix?: string;
|
|
6173
|
+
readonly judgment?: 'main-runnable' | 'main-not-runnable' | 'unknown';
|
|
6174
|
+
}
|
|
6175
|
+
|
|
6176
|
+
export interface GoalSelfReviewAttempt {
|
|
6177
|
+
readonly attempt: 1 | 2;
|
|
6178
|
+
readonly reauthored: boolean;
|
|
6179
|
+
readonly items: readonly GoalSelfReviewItem[];
|
|
6180
|
+
}
|
|
6181
|
+
|
|
6182
|
+
export interface GoalAuthorSelfReviewOutcome {
|
|
6183
|
+
readonly document: string;
|
|
6184
|
+
readonly reviews: readonly GoalSelfReviewAttempt[];
|
|
6185
|
+
}
|
|
6186
|
+
|
|
6187
|
+
export interface GoalAuthorSelfReviewInput {
|
|
6188
|
+
readonly ask: string;
|
|
6189
|
+
readonly document: string;
|
|
6190
|
+
readonly steps: readonly string[] | undefined;
|
|
6191
|
+
readonly checklist: readonly string[];
|
|
6192
|
+
readonly facts: CodebaseGrounding | null;
|
|
6193
|
+
readonly decomposeSteps?: GoalAuthorDeps['decomposeSteps'];
|
|
6194
|
+
readonly existsOnMain?: (repositoryRelativePath: string) => boolean | undefined;
|
|
6195
|
+
readonly runId?: string;
|
|
6196
|
+
readonly goalId?: string;
|
|
6197
|
+
}
|
|
6198
|
+
|
|
6199
|
+
const SLICE_DIFFICULTY_DECLARATION = /(?:난이도|difficulty)\s*[::]?\s*(하|중|상|low|medium|high)/iu;
|
|
6200
|
+
const SLICE_LANDABLE_DECLARATION = /(착지\s*가능|완료\s*경계|completion\s*boundary|landable)/iu;
|
|
6201
|
+
const SLICE_PREREQUISITE_DECLARATION = /(선행|depends\s*on|prerequisite|prereq)/iu;
|
|
6202
|
+
const SLICE_TIER_BY_DECLARATION: Record<string, '하' | '중' | '상'> = { 하: '하', 중: '중', 상: '상', low: '하', medium: '중', high: '상' };
|
|
6203
|
+
/** 미래 가정 — 현재 main 상태가 아니라 «앞으로 생길 것»을 전제하는 문면(제거하거나 FU 조각화). */
|
|
6204
|
+
const FUTURE_ASSUMPTION_DECLARATION = /나중에|향후|미래(?:에|의)|다음\s*(?:판|버전)|(?:착지|머지|반영|merge|land)(?:되|된|한다)?\s*(?:면|후|뒤|한\s*뒤)|after\s+#\d+|once\s+#\d+|#\d+\s+(?:lands|merges)|will\s+be\s+(?:added|landed|merged|available)|future\s+assumptions?/iu;
|
|
6205
|
+
/** ask 가 이름대지 않은 칸 id — ask 밖 목표의 결정론 표지(숫자로 시작하는 두번째 마디 `MS-02` 는 제외). */
|
|
6206
|
+
const OUT_OF_ASK_CELL_ID = /\b[A-Z][A-Z0-9]{1,}-[A-Z][A-Z0-9-]*\b/g;
|
|
6207
|
+
|
|
6208
|
+
function declaredSliceTier(step: string): '하' | '중' | '상' | null {
|
|
6209
|
+
const match = SLICE_DIFFICULTY_DECLARATION.exec(step);
|
|
6210
|
+
return match ? SLICE_TIER_BY_DECLARATION[match[1]!.toLowerCase()] ?? null : null;
|
|
6211
|
+
}
|
|
6212
|
+
|
|
6213
|
+
/** 칸 = ask ⊕ 접지 — 사람이 이름댔거나 접지가 Read 한 경로가 «칸 안»이다. */
|
|
6214
|
+
function inCellPathTokens(ask: string, facts: CodebaseGrounding | null): Set<string> {
|
|
6215
|
+
return new Set([
|
|
6216
|
+
...declaredTargetPaths(ask),
|
|
6217
|
+
...evidencePaths(ask),
|
|
6218
|
+
...(facts?.files ?? []),
|
|
6219
|
+
...(facts?.persistentEvidence ?? []).flatMap((entry) => evidencePaths(entry)),
|
|
6220
|
+
]);
|
|
6221
|
+
}
|
|
6222
|
+
|
|
6223
|
+
function outOfCellReasons(criterion: string, ask: string, inCellPaths: ReadonlySet<string>): string[] {
|
|
6224
|
+
const reasons: string[] = [];
|
|
6225
|
+
const outPaths = evidencePaths(criterion).filter((path) => !inCellPaths.has(path) && !ask.includes(path));
|
|
6226
|
+
if (outPaths.length) reasons.push(`칸 밖 경로: ${outPaths.join(' · ')}`);
|
|
6227
|
+
const ids = [...criterion.matchAll(OUT_OF_ASK_CELL_ID)].map((match) => match[0]).filter((id) => !ask.includes(id));
|
|
6228
|
+
if (ids.length) reasons.push(`ask 밖 목표(칸 id): ${ids.join(' · ')}`);
|
|
6229
|
+
return reasons;
|
|
6230
|
+
}
|
|
6231
|
+
|
|
6232
|
+
/** ④ mock 무대 — 검증 계획(TDD) 의 무대 줄이 MS id·사건 주입·관측 줄을 갖췄나. */
|
|
6233
|
+
function mockStageSelfReviewItem(document: string): GoalSelfReviewItem {
|
|
6234
|
+
const start = document.indexOf(VERIFICATION_PLAN_HEADING);
|
|
6235
|
+
if (start === -1) return { check: 'mock-stage', verdict: 'not-applicable', detail: '검증 계획(TDD) 절이 없어 mock 무대 줄을 검사하지 않는다.' };
|
|
6236
|
+
const rest = document.slice(start + VERIFICATION_PLAN_HEADING.length);
|
|
6237
|
+
const nextHeading = rest.indexOf('\n## ');
|
|
6238
|
+
const section = nextHeading === -1 ? rest : rest.slice(0, nextHeading);
|
|
6239
|
+
const missing = [
|
|
6240
|
+
...(/MS-\d+/u.test(section) ? [] : ['MS id']),
|
|
6241
|
+
...(section.includes('사건 주입') ? [] : ['사건 주입 줄']),
|
|
6242
|
+
...(section.includes('관측:') ? [] : ['관측 줄']),
|
|
6243
|
+
];
|
|
6244
|
+
return missing.length
|
|
6245
|
+
? { check: 'mock-stage', verdict: 'needs-human', detail: `mock 무대 줄 미비 — ${missing.join(' · ')} — 사람이 무대를 확정한다.` }
|
|
6246
|
+
: { check: 'mock-stage', verdict: 'pass', detail: 'mock 무대가 MS id·사건 주입·관측 줄을 갖췄다.' };
|
|
6247
|
+
}
|
|
6248
|
+
|
|
6249
|
+
/** ⑤ 완료 경계 증거 명령 — 경로 인자가 «현재 main» 에 있는지 판정한다(심이 없으면 판정을 남기지 못한다). */
|
|
6250
|
+
function evidenceCommandSelfReviewItem(document: string, existsOnMain: ((repositoryRelativePath: string) => boolean | undefined) | undefined): GoalSelfReviewItem {
|
|
6251
|
+
const command = inspectGoalDoneBoundary(document).values['완료 경계 증거 명령'];
|
|
6252
|
+
if (command === undefined) return { check: 'evidence-command', verdict: 'not-applicable', detail: '완료 경계 증거 명령이 없어 main 실행 가능 판정을 하지 않는다.' };
|
|
6253
|
+
if (existsOnMain === undefined) return { check: 'evidence-command', verdict: 'not-applicable', detail: 'main 존재 심(selfReviewExistsOnMain)이 없어 판정하지 못한다 — 생산 진입점이 심을 공급한다.', slice: command };
|
|
6254
|
+
const paths = evidencePaths(command);
|
|
6255
|
+
if (!paths.length) return { check: 'evidence-command', verdict: 'pass', judgment: 'main-runnable', detail: `증거 명령에 저장소 경로 인자가 없다 — 현재 main 에서 그대로 실행된다: ${command}` };
|
|
6256
|
+
const presence = paths.map((path) => [path, existsOnMain(path)] as const);
|
|
6257
|
+
const unknown = presence.filter(([, exists]) => exists === undefined).map(([path]) => path);
|
|
6258
|
+
if (unknown.length) return { check: 'evidence-command', verdict: 'needs-human', judgment: 'unknown', detail: `origin/main 에서 경로 존재를 잴 수 없음: ${unknown.join(' · ')} — main 실행 가능성을 확인할 수 없어 사람이 판정한다.`, slice: command };
|
|
6259
|
+
const missing = presence.filter(([, exists]) => exists === false).map(([path]) => path);
|
|
6260
|
+
return missing.length
|
|
6261
|
+
? { check: 'evidence-command', verdict: 'needs-human', judgment: 'main-not-runnable', detail: `현재 main 에 없는 경로: ${missing.join(' · ')} — 신설 경로면 착지 뒤에 실행 가능하다.`, slice: command }
|
|
6262
|
+
: { check: 'evidence-command', verdict: 'pass', judgment: 'main-runnable', detail: `증거 명령의 모든 경로 인자가 현재 main 에 있다: ${paths.join(' · ')}` };
|
|
6263
|
+
}
|
|
6264
|
+
|
|
6265
|
+
interface SelfReviewPass {
|
|
6266
|
+
readonly items: readonly GoalSelfReviewItem[];
|
|
6267
|
+
readonly removeCriterionLines: readonly string[];
|
|
6268
|
+
readonly fuCriterionLines: readonly (readonly [line: string, fuLine: string])[];
|
|
6269
|
+
readonly fuStepLines: readonly (readonly [line: string, fuLine: string])[];
|
|
6270
|
+
readonly oversizeSteps: readonly string[];
|
|
6271
|
+
}
|
|
6272
|
+
|
|
6273
|
+
function passGoalSelfReview(input: {
|
|
6274
|
+
readonly document: string;
|
|
6275
|
+
readonly steps: readonly string[] | undefined;
|
|
6276
|
+
readonly modelCriteria: readonly string[];
|
|
6277
|
+
readonly ask: string;
|
|
6278
|
+
readonly inCellPaths: ReadonlySet<string>;
|
|
6279
|
+
readonly existsOnMain: ((repositoryRelativePath: string) => boolean | undefined) | undefined;
|
|
6280
|
+
}): SelfReviewPass {
|
|
6281
|
+
const items: GoalSelfReviewItem[] = [];
|
|
6282
|
+
const removeCriterionLines: string[] = [];
|
|
6283
|
+
const fuCriterionLines: Array<readonly [string, string]> = [];
|
|
6284
|
+
const fuStepLines: Array<readonly [string, string]> = [];
|
|
6285
|
+
const oversizeSteps: string[] = [];
|
|
6286
|
+
|
|
6287
|
+
// ① 조각 난이도 하·중·착지 가능·선행 명시 — 상이면 더 분해한다.
|
|
6288
|
+
if (input.steps === undefined || input.steps.length === 0) {
|
|
6289
|
+
items.push({ check: 'slice-difficulty', verdict: 'not-applicable', detail: '검토할 분해 조각이 없다 — 난이도·착지 가능·선행 명시를 검사하지 않는다.' });
|
|
6290
|
+
} else {
|
|
6291
|
+
for (const step of input.steps) {
|
|
6292
|
+
const tier = declaredSliceTier(step);
|
|
6293
|
+
const missing = [
|
|
6294
|
+
...(tier === null ? ['난이도(하·중)'] : []),
|
|
6295
|
+
...(SLICE_LANDABLE_DECLARATION.test(step) ? [] : ['착지 가능']),
|
|
6296
|
+
...(SLICE_PREREQUISITE_DECLARATION.test(step) ? [] : ['선행']),
|
|
6297
|
+
];
|
|
6298
|
+
if (tier === '상') {
|
|
6299
|
+
oversizeSteps.push(step);
|
|
6300
|
+
items.push({ check: 'slice-difficulty', verdict: 'needs-human', detail: `난이도 상 — 더 분해해야 한다 (미명시: ${missing.join(' · ')})`, slice: step });
|
|
6301
|
+
continue;
|
|
6302
|
+
}
|
|
6303
|
+
items.push(missing.length
|
|
6304
|
+
? { check: 'slice-difficulty', verdict: 'needs-human', detail: `조각이 난이도 하·중·착지 가능·선행을 명시하지 않았다 — 미명시: ${missing.join(' · ')}`, slice: step }
|
|
6305
|
+
: { check: 'slice-difficulty', verdict: 'pass', detail: `난이도 ${tier} · 착지 가능 · 선행 명시 확인`, slice: step });
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
|
|
6309
|
+
const documentLines = input.document.split('\n');
|
|
6310
|
+
const modelCriterionLines = input.modelCriteria
|
|
6311
|
+
.map((criterion) => ({ criterion, line: requestedCriterionLine(criterion) }))
|
|
6312
|
+
.filter(({ line }) => documentLines.includes(line));
|
|
6313
|
+
|
|
6314
|
+
// ② ask 밖 목표·칸 밖 경로 제거 — 칸 = ask ⊕ 접지.
|
|
6315
|
+
for (const { criterion, line } of modelCriterionLines) {
|
|
6316
|
+
const reasons = outOfCellReasons(criterion, input.ask, input.inCellPaths);
|
|
6317
|
+
if (!reasons.length) continue;
|
|
6318
|
+
items.push({ check: 'ask-scope', verdict: 'fixed', detail: `ask 밖 목표·칸 밖 경로 — ${reasons.join(' · ')}`, slice: criterion, fix: '1회 재저작에서 이 목표 줄을 문서에서 제거한다.' });
|
|
6319
|
+
removeCriterionLines.push(line);
|
|
6320
|
+
}
|
|
6321
|
+
if (!removeCriterionLines.length) items.push({ check: 'ask-scope', verdict: 'pass', detail: 'ask 밖 목표·칸 밖 경로가 없다.' });
|
|
6322
|
+
|
|
6323
|
+
// ③ 미래 가정 — 제거하거나 FU(후속 조각) 로 바꾼다.
|
|
6324
|
+
for (const { criterion, line } of modelCriterionLines) {
|
|
6325
|
+
if (removeCriterionLines.includes(line) || !FUTURE_ASSUMPTION_DECLARATION.test(criterion)) continue;
|
|
6326
|
+
items.push({ check: 'future-assumption', verdict: 'fixed', detail: '미래 가정 — 현재 main 상태가 아니라 앞으로 생길 것을 전제한다.', slice: criterion, fix: '1회 재저작에서 FU(후속 조각) 줄로 바꾼다.' });
|
|
6327
|
+
fuCriterionLines.push([line, `- FU(후속 조각): ${criterion}`]);
|
|
6328
|
+
}
|
|
6329
|
+
for (const step of input.steps ?? []) {
|
|
6330
|
+
// A declared step dependency is a present plan relationship, not an assumption
|
|
6331
|
+
// that an external future event will happen (e.g. shadow → live after step ① lands).
|
|
6332
|
+
if (SLICE_PREREQUISITE_DECLARATION.test(step) || !FUTURE_ASSUMPTION_DECLARATION.test(step)) continue;
|
|
6333
|
+
items.push({ check: 'future-assumption', verdict: 'fixed', detail: '미래 가정 조각 — 현재 main 상태가 아니라 앞으로 생길 것을 전제한다.', slice: step, fix: '1회 재저작에서 FU(후속 조각) 줄로 바꾼다.' });
|
|
6334
|
+
fuStepLines.push([`- ${step}`, `- FU(후속 조각): ${step}`]);
|
|
6335
|
+
}
|
|
6336
|
+
if (!fuCriterionLines.length && !fuStepLines.length) items.push({ check: 'future-assumption', verdict: 'pass', detail: '미래 가정이 없다.' });
|
|
6337
|
+
|
|
6338
|
+
items.push(mockStageSelfReviewItem(input.document));
|
|
6339
|
+
items.push(evidenceCommandSelfReviewItem(input.document, input.existsOnMain));
|
|
6340
|
+
return { items, removeCriterionLines, fuCriterionLines, fuStepLines, oversizeSteps };
|
|
6341
|
+
}
|
|
6342
|
+
|
|
6343
|
+
function renderGoalStepsSection(steps: readonly string[]): string {
|
|
6344
|
+
return ['## STEPS', ...(steps.length ? steps.map((step) => `- ${step}`) : ['- No externally injected steps.']), '', ''].join('\n');
|
|
6345
|
+
}
|
|
6346
|
+
|
|
6347
|
+
function replaceGoalStepsSection(document: string, steps: readonly string[]): string {
|
|
6348
|
+
const outside = linesOutsideFencedCode(document);
|
|
6349
|
+
const start = outside.find((line) => line.text === '## STEPS');
|
|
6350
|
+
const next = start && outside.find((line) => line.start > start.start && line.text === '## ACCEPTANCE CRITERIA');
|
|
6351
|
+
if (!start || !next) return document;
|
|
6352
|
+
return `${document.slice(0, start.start)}${renderGoalStepsSection(steps)}${document.slice(next.start)}`;
|
|
6353
|
+
}
|
|
6354
|
+
|
|
6355
|
+
function reviseGoalDocumentLines(document: string, revision: { remove: readonly string[]; fu: readonly (readonly [line: string, fuLine: string])[] }): string {
|
|
6356
|
+
const remove = new Set(revision.remove);
|
|
6357
|
+
const fu = new Map(revision.fu);
|
|
6358
|
+
return document.split('\n').flatMap((line) => {
|
|
6359
|
+
if (remove.has(line)) return [];
|
|
6360
|
+
const fuLine = fu.get(line);
|
|
6361
|
+
return fuLine ? [fuLine] : [line];
|
|
6362
|
+
}).join('\n');
|
|
6363
|
+
}
|
|
6364
|
+
|
|
6365
|
+
/**
|
|
6366
|
+
* 발사 전 self-review 엔진 — 1차 검사 → (결정론적 수정이 있으면) 1회 재저작 → 2차 검사.
|
|
6367
|
+
* 파일·원장·LLM 효과는 없다: 재분해는 주입된 `decomposeSteps` 심으로만, main 존재 판정은 주입된 심으로만.
|
|
6368
|
+
*/
|
|
6369
|
+
export async function runGoalAuthorSelfReview(input: GoalAuthorSelfReviewInput): Promise<GoalAuthorSelfReviewOutcome> {
|
|
6370
|
+
const modelCriteria = withoutDedicatedSectionDuplicates(input.checklist, input.ask);
|
|
6371
|
+
const inCellPaths = inCellPathTokens(input.ask, input.facts);
|
|
6372
|
+
const first = passGoalSelfReview({ document: input.document, steps: input.steps, modelCriteria, ask: input.ask, inCellPaths, existsOnMain: input.existsOnMain });
|
|
6373
|
+
const canRedecompose = first.oversizeSteps.length > 0 && input.decomposeSteps !== undefined;
|
|
6374
|
+
const fixable = first.removeCriterionLines.length > 0 || first.fuCriterionLines.length > 0 || first.fuStepLines.length > 0 || canRedecompose;
|
|
6375
|
+
if (!fixable) return { document: input.document, reviews: [{ attempt: 1, reauthored: false, items: first.items }] };
|
|
6376
|
+
|
|
6377
|
+
// 1회 재저작 — ① 상 조각 재분해 ⊕ ② ask 밖 목표 제거 ⊕ ③ 미래 가정 FU 화.
|
|
6378
|
+
let document = input.document;
|
|
6379
|
+
let steps = input.steps;
|
|
6380
|
+
let stepsReauthored = false;
|
|
6381
|
+
if (canRedecompose) {
|
|
6382
|
+
const feedback = [
|
|
6383
|
+
'SELF-REVIEW ①: 이전 분해 조각이 난이도 상이거나 하·중·착지 가능·선행을 명시하지 않았다.',
|
|
6384
|
+
`상 조각: ${first.oversizeSteps.join(' · ')}`,
|
|
6385
|
+
'전체 계획을 다시 내라 — 각 조각에 난이도(하|중)·착지 가능·선행을 명시하고, 상 조각은 하·중 조각으로 더 분해하라.',
|
|
6386
|
+
].join('\n');
|
|
6387
|
+
const reDecomposed = await input.decomposeSteps!(input.ask, {
|
|
6388
|
+
context: feedback,
|
|
6389
|
+
...(input.runId === undefined ? {} : { runId: input.runId }),
|
|
6390
|
+
...(input.goalId === undefined ? {} : { goalId: input.goalId }),
|
|
6391
|
+
});
|
|
6392
|
+
if (reDecomposed.length) {
|
|
6393
|
+
const replacementSteps = [...reDecomposed];
|
|
6394
|
+
const replacementDocument = replaceGoalStepsSection(document, replacementSteps);
|
|
6395
|
+
if (replacementDocument !== document) {
|
|
6396
|
+
steps = replacementSteps;
|
|
6397
|
+
document = replacementDocument;
|
|
6398
|
+
stepsReauthored = true;
|
|
6399
|
+
}
|
|
6400
|
+
}
|
|
6401
|
+
}
|
|
6402
|
+
const oversizeStepLines = new Set(canRedecompose ? first.oversizeSteps.map((step) => `- ${step}`) : []);
|
|
6403
|
+
const fuStepLines = first.fuStepLines.filter(([line]) => !oversizeStepLines.has(line));
|
|
6404
|
+
document = reviseGoalDocumentLines(document, { remove: first.removeCriterionLines, fu: [...first.fuCriterionLines, ...fuStepLines] });
|
|
6405
|
+
const fuSteps = new Set(fuStepLines.map(([line]) => line.slice(2)));
|
|
6406
|
+
const second = passGoalSelfReview({
|
|
6407
|
+
document,
|
|
6408
|
+
steps: steps?.filter((step) => !fuSteps.has(step)),
|
|
6409
|
+
modelCriteria,
|
|
6410
|
+
ask: input.ask,
|
|
6411
|
+
inCellPaths,
|
|
6412
|
+
existsOnMain: input.existsOnMain,
|
|
6413
|
+
});
|
|
6414
|
+
const attempt1Items = first.items.map((item) => item.check === 'slice-difficulty' && item.verdict === 'needs-human' && item.slice !== undefined && first.oversizeSteps.includes(item.slice) && stepsReauthored
|
|
6415
|
+
? { ...item, verdict: 'fixed' as const, fix: '1회 재저작에서 상 조각을 재분해로 대체했다.' }
|
|
6416
|
+
: item);
|
|
6417
|
+
return {
|
|
6418
|
+
document,
|
|
6419
|
+
reviews: [
|
|
6420
|
+
{ attempt: 1, reauthored: true, items: attempt1Items },
|
|
6421
|
+
{ attempt: 2, reauthored: true, items: second.items },
|
|
6422
|
+
],
|
|
6423
|
+
};
|
|
6424
|
+
}
|
|
6425
|
+
|
|
5807
6426
|
/** Compose one grounded goal artifact without filesystem, process, pipeline, or daemon effects. */
|
|
5808
6427
|
export async function authorGoal(ask: string, deps: GoalAuthorDeps): Promise<AuthoredGoal> {
|
|
5809
6428
|
if ('supersessionRootIntent' in deps) {
|
|
@@ -5958,7 +6577,7 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
5958
6577
|
'',
|
|
5959
6578
|
'## ACCEPTANCE CRITERIA',
|
|
5960
6579
|
...enhancement.checklist.map(requestedCriterionLine),
|
|
5961
|
-
...explicitGoalDoneBoundaryLines(ask),
|
|
6580
|
+
...explicitGoalDoneBoundaryLines(ask, deps.repositoryRoot ?? process.cwd()),
|
|
5962
6581
|
'',
|
|
5963
6582
|
'## REQUIRED EVIDENCE',
|
|
5964
6583
|
'- [requested] Verify the decision signal and the verbatim ask.',
|
|
@@ -6397,7 +7016,7 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
6397
7016
|
? tracedPathsSection(facts, ask, deps.repositoryRoot, narrative.tracedPathsUnavailableEvidence, authorRunId, deps.recordTracedPath)
|
|
6398
7017
|
: [];
|
|
6399
7018
|
if (goalType === 'implement') observeEmptyPersistentEvidence(facts, tracedPathsForDocument, authorRunId);
|
|
6400
|
-
|
|
7019
|
+
let document = [
|
|
6401
7020
|
explicitGoalTitle ?? goalSummary(enhancement.original),
|
|
6402
7021
|
`- GoalId: ${assignedGoalId}`,
|
|
6403
7022
|
...(deps.authoringLessonIds?.length ? [`- AuthoringLessons: ${deps.authoringLessonIds.join(', ')}`] : []),
|
|
@@ -6443,7 +7062,7 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
6443
7062
|
: ['## STEPS', ...(resolvedSteps.length ? resolvedSteps.map((step) => `- ${step}`) : ['- No externally injected steps.']), '']),
|
|
6444
7063
|
'## ACCEPTANCE CRITERIA',
|
|
6445
7064
|
...acceptanceSection,
|
|
6446
|
-
...explicitGoalDoneBoundaryLines(ask),
|
|
7065
|
+
...explicitGoalDoneBoundaryLines(ask, deps.repositoryRoot ?? process.cwd()),
|
|
6447
7066
|
...preservationAmbiguityCriteria(ambiguities, clarificationAnswers),
|
|
6448
7067
|
...preservationAmbiguityNotice(ambiguities),
|
|
6449
7068
|
...preservationAmbiguityClarification(clarificationQuestions, clarificationResponses),
|
|
@@ -6483,6 +7102,38 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
6483
7102
|
endAssembleSubphase();
|
|
6484
7103
|
assembleCompleted = true;
|
|
6485
7104
|
endGoalAuthorPhase('assemble', assembleStartedAt, authorRunId, deps.onProgress);
|
|
7105
|
+
// ⭐ SELF-REVIEW-PRELAUNCH — assemble 완료 뒤·발사(lint→return→파일 쓰기) 직전에 저작물을 검열한다.
|
|
7106
|
+
// ⛔ lite 저작은 assemble 단계 자체가 없다 — self-review 는 full 저작 경로에만 붙는다(의도적 경계).
|
|
7107
|
+
// 외부 페이즈 관측 계약(ground→enhance→assemble→lint)은 그대로 보존한다 — 검열 자국은
|
|
7108
|
+
// author.self-review 관측(attempt·항목별 verdict)으로만 남는다.
|
|
7109
|
+
try {
|
|
7110
|
+
const selfReview = await runGoalAuthorSelfReview({
|
|
7111
|
+
ask,
|
|
7112
|
+
document,
|
|
7113
|
+
steps: resolvedSteps,
|
|
7114
|
+
checklist: enhancement.checklist,
|
|
7115
|
+
facts,
|
|
7116
|
+
decomposeSteps: deps.decomposeSteps,
|
|
7117
|
+
existsOnMain: deps.selfReviewExistsOnMain,
|
|
7118
|
+
runId: authorRunId,
|
|
7119
|
+
goalId: assignedGoalId,
|
|
7120
|
+
});
|
|
7121
|
+
for (const review of selfReview.reviews) {
|
|
7122
|
+
try {
|
|
7123
|
+
observeGoalAuthor('goal-author', 'author.self-review', {
|
|
7124
|
+
authorRunId,
|
|
7125
|
+
goalId: assignedGoalId,
|
|
7126
|
+
attempt: review.attempt,
|
|
7127
|
+
reauthored: review.reauthored,
|
|
7128
|
+
items: review.items,
|
|
7129
|
+
});
|
|
7130
|
+
} catch { /* observation is fail-soft */ }
|
|
7131
|
+
}
|
|
7132
|
+
document = selfReview.document;
|
|
7133
|
+
} catch (error) {
|
|
7134
|
+
// 검열은 저작을 막지 않는다 — 실패는 관측으로 남기고 종전 문서를 그대로 발사한다.
|
|
7135
|
+
try { observeGoalAuthor('goal-author', 'author.self-review-failed', { authorRunId, error: error instanceof Error ? error.message : String(error) }); } catch { /* observation is fail-soft */ }
|
|
7136
|
+
}
|
|
6486
7137
|
const lintStartedAt = startGoalAuthorPhase('lint', authorRunId, deps.onProgress);
|
|
6487
7138
|
let lintPassed = false;
|
|
6488
7139
|
try {
|
|
@@ -6688,6 +7339,19 @@ export async function writeAuthoredGoal(
|
|
|
6688
7339
|
...deps,
|
|
6689
7340
|
repositoryRoot: deps.repositoryRoot ?? groundingRoot,
|
|
6690
7341
|
};
|
|
7342
|
+
// ⭐ SELF-REVIEW-PRELAUNCH ⑤ — 완료 경계 증거 명령의 origin/main 실행 가능 판정 심(읽기 전용).
|
|
7343
|
+
// 현재 worktree 파일 존재를 main 증거로 오인하지 않는다. ref를 못 읽으면 unknown 으로 남긴다.
|
|
7344
|
+
resolvedDeps.selfReviewExistsOnMain = deps.selfReviewExistsOnMain
|
|
7345
|
+
?? ((repositoryRelativePath: string) => {
|
|
7346
|
+
try {
|
|
7347
|
+
const entry = execFileSync('git', ['-C', resolvedDeps.repositoryRoot, 'ls-tree', '-r', '--name-only', 'origin/main', '--', repositoryRelativePath], {
|
|
7348
|
+
encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
|
|
7349
|
+
});
|
|
7350
|
+
return entry.trim().length > 0;
|
|
7351
|
+
} catch {
|
|
7352
|
+
return undefined;
|
|
7353
|
+
}
|
|
7354
|
+
});
|
|
6691
7355
|
const mandatoryGoalContextEvidence = goalContextEvidence(cwd);
|
|
6692
7356
|
const authoringLessons = selectRelevantAuthoringLessons(cwd, ask, elanousStateRoot());
|
|
6693
7357
|
observeGoalAuthor('goal-author', 'authoring-lessons', {
|
|
@@ -6744,6 +7408,19 @@ export async function writeAuthoredGoal(
|
|
|
6744
7408
|
...(supersededGoalId && { goalId: supersededGoalId }),
|
|
6745
7409
|
...(supersededRootIntent !== null && { supersessionRootIntent: supersededRootIntent }),
|
|
6746
7410
|
});
|
|
7411
|
+
const reviewerPrecheckEnabled = resolvedDeps.reviewerPrecheckEnabled ?? resolveGoalAuthorReviewerPrecheckEnabled();
|
|
7412
|
+
const precheck = await executeGoalAuthorReviewerPrecheck(
|
|
7413
|
+
reviewerPrecheckEnabled,
|
|
7414
|
+
authored.document,
|
|
7415
|
+
authored.authorRunId,
|
|
7416
|
+
(document) => (resolvedDeps.reviewerPrecheck
|
|
7417
|
+
? resolvedDeps.reviewerPrecheck(document, authored.authorRunId)
|
|
7418
|
+
: runGoalAuthorReviewerPrecheck(document)),
|
|
7419
|
+
);
|
|
7420
|
+
if (precheck.result) {
|
|
7421
|
+
authored.reviewerPrecheck = precheck.result;
|
|
7422
|
+
if (precheck.status === 'completed') authored.document = precheck.result.revisedDocument;
|
|
7423
|
+
}
|
|
6747
7424
|
const stampedAt = fileDeps.now?.() ?? new Date();
|
|
6748
7425
|
const identity = identityLines(ask, cwd, fileDeps.env ?? process.env, stampedAt);
|
|
6749
7426
|
if (identity.length) {
|