mulmoterminal 8.1.0 → 8.2.0
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/blueprints/adopt/templates/chaff.yml +1 -1
- package/blueprints/docs/checks/chaff.sh +1 -1
- package/blueprints/docs/skills/workspace/SKILL.md +1 -1
- package/blueprints/from-collection/checks/actions.sh +10 -1
- package/blueprints/from-collection/skills/actions/SKILL.md +2 -1
- package/blueprints/from-collection/skills/actions-cloudflare/SKILL.md +2 -1
- package/blueprints/from-collection/skills/actions-firebase/SKILL.md +2 -1
- package/blueprints/from-collection/skills/actions-supabase/SKILL.md +2 -1
- package/blueprints/style/skills/report/SKILL.md +1 -1
- package/common/appActions.ts +1 -0
- package/common/blueprint/executorPolicy.ts +19 -3
- package/common/blueprint/run.ts +2 -0
- package/common/blueprint/stepPrompt.ts +68 -4
- package/common/keymap.ts +1 -0
- package/dist/assets/{abnfDiagram-O67JEVCF-ClxVnRku.js → abnfDiagram-O67JEVCF-DpKqOyjt.js} +1 -1
- package/dist/assets/architecture-7GRP2DOG-tqxhXA_W.js +1 -0
- package/dist/assets/{architectureDiagram-NJMV4G6O-DPbRnCKN.js → architectureDiagram-NJMV4G6O-BEf7hi8B.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-422fI4GC.js → blockDiagram-BEXU5L5S-Bs_qxpCN.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-htmTlUTG.js → c4Diagram-YGBWAQC7-Cxvi1yMd.js} +1 -1
- package/dist/assets/channel-B7Hqexxy.js +1 -0
- package/dist/assets/{chunk-3FUC2YCW-BbDEpgy0.js → chunk-3FUC2YCW-CLhlVcbE.js} +1 -1
- package/dist/assets/{chunk-5DYCD2WN-D97hkTCQ.js → chunk-5DYCD2WN-tnBh5bTj.js} +1 -1
- package/dist/assets/{chunk-742MDFTN-B3Mnh8e7.js → chunk-742MDFTN-BJTRk8eI.js} +1 -1
- package/dist/assets/{chunk-7INBJB4K-B5lqXrqb.js → chunk-7INBJB4K-Bg39tnTn.js} +1 -1
- package/dist/assets/{chunk-7M6MHVWA-DghPQFUI.js → chunk-7M6MHVWA-Dy7p4wXp.js} +1 -1
- package/dist/assets/{chunk-7PRAP22T-BdAaGYkh.js → chunk-7PRAP22T-hw-m893g.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-DKvFKim8.js → chunk-GTNCS2PH-COevsxgA.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-RTEdPAf3.js → chunk-GWA4HPMP-GF0g7kkY.js} +1 -1
- package/dist/assets/{chunk-MBY4JIJT-x_wqlXNe.js → chunk-MBY4JIJT-CUUZjNcR.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-8Cs1NIno.js → chunk-NETBCI7D-ClVuU0EM.js} +1 -1
- package/dist/assets/{chunk-O7XYJQB3-Dz4vrOLX.js → chunk-O7XYJQB3-Gutmfs0i.js} +1 -1
- package/dist/assets/{chunk-UA2S7LBM-Dwd6YCa2.js → chunk-UA2S7LBM-jOPSo4_W.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-rY_Nsr-S.js → chunk-WEXAMYUT-ZT-XWGQ1.js} +1 -1
- package/dist/assets/{chunk-Z7XXMR3K-pt-6PBwB.js → chunk-Z7XXMR3K-9viSdvia.js} +1 -1
- package/dist/assets/{chunk-ZIGJFQKS-DzYvLxms.js → chunk-ZIGJFQKS-DK3D9aN6.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-DAAHQYjw.js → classDiagram-v2-NBCMYWYE-Cdjo_Ous.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-DTPNG3DO.js → cynefin-OW5HDTMX-D-a3gV2N.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-BiNAmBAf.js → cynefinDiagram-VND7K2PF-DO5Mg4b5.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-C3aACS4M.js → dagre-6A5THRUB-DDZdk1F_.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-1moWpahw.js → diagram-22UHCM2B-_jTbmIND.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-CgsKz1ze.js → diagram-3UASUU5V-OPNBnJk-.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-CtIrEsFG.js → diagram-ATOU4E4O-DTibMEtZ.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-BntC2VUx.js → diagram-CDSNMT55-DqnZQTDC.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-Cdh5tBhw.js → diagram-MLGK6HIB-C8RWNVVB.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-CQz7IrSH.js → diagram-MPIPVDR6-Bm7W9_aY.js} +1 -1
- package/dist/assets/{dist-PySjWJXd.js → dist-Bt6Uoh1p.js} +1 -1
- package/dist/assets/{dist-DANd2aqA.js → dist-CCEafgGi.js} +1 -1
- package/dist/assets/{dist--0LHNaYl.js → dist-CVg47SZ2.js} +1 -1
- package/dist/assets/{dist-DqudlEKF.js → dist-D4AUpaJv.js} +1 -1
- package/dist/assets/{dist-CkDbiiOe.js → dist-X9VE8etg.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-CZaPrV3v.js → ebnfDiagram-ZINNZB2B-CcP60K5m.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-5V_Op3XR.js → elk-276RUBZZ-DQdydmIq.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-flX7Jn68.js → erDiagram-OPXOYQCR-D3C2QS7R.js} +1 -1
- package/dist/assets/eventmodeling-NTZA5JFV-DFoSe9CC.js +1 -0
- package/dist/assets/flowDiagram-KWPJA3E3-B5HJ88J1.js +1 -0
- package/dist/assets/{ganttDiagram-FUAMR5RP-2KqutibO.js → ganttDiagram-FUAMR5RP-IZaW5VgA.js} +1 -1
- package/dist/assets/{gitGraph-4MIJSDKK-DVTDAI2J.js → gitGraph-4MIJSDKK-D3sAiw0g.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-Btc5-wfa.js → gitGraphDiagram-X574FWY7-BKQ33CxX.js} +1 -1
- package/dist/assets/{index-8Aw0tzeQ.js → index-DjO9W8uQ.js} +310 -310
- package/dist/assets/index-ct_vF1PW.css +1 -0
- package/dist/assets/{info-A6RAGUB7-BX4xPahk.js → info-A6RAGUB7-CGT6OwbO.js} +1 -1
- package/dist/assets/{infoDiagram-VRGFBTTK-ng2eNzlm.js → infoDiagram-VRGFBTTK-f8idGmV5.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-CnNc1uHK.js → ishikawaDiagram-OU5B5YK6-C3q9XWHW.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-BHr492DG.js → journeyDiagram-ZHPQQLJL-DZeP_NQJ.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-CD4FdLFL.js → kanban-definition-PNTS6WVX-Be2RPtgv.js} +1 -1
- package/dist/assets/{line-DwxnhfoI.js → line--V9C2ujH.js} +1 -1
- package/dist/assets/{mermaid-parser.core-DEnlY2ci.js → mermaid-parser.core-CA27Zh_E.js} +3 -3
- package/dist/assets/{mermaid.core-B7u-t6P9.js → mermaid.core-oKSvAMmn.js} +4 -4
- package/dist/assets/{mindmap-definition-NLK3R4M7-BdIcteCE.js → mindmap-definition-NLK3R4M7-Ds2mxwxS.js} +1 -1
- package/dist/assets/{packet-AYTQ26CC-DHisXteY.js → packet-AYTQ26CC-BQS2MXBT.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-DDOrA3Ua.js → pegDiagram-GJSIUBJH-05ZfyxXE.js} +1 -1
- package/dist/assets/{pie-WAS4IAKB-Ba76QqEP.js → pie-WAS4IAKB-BZzyas2W.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-CNlravvW.js → pieDiagram-5QR66LMP-Dbp7Nolp.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-B0D-BZQ2.js → quadrantDiagram-O4NWA36T-Cbqaez9d.js} +1 -1
- package/dist/assets/{radar-RG4KPBEZ-BCNuh25J.js → radar-RG4KPBEZ-EXcR8Xp9.js} +1 -1
- package/dist/assets/{railroad-74A4TZTK-CMJcxNfL.js → railroad-74A4TZTK-CDJiZrju.js} +1 -1
- package/dist/assets/railroad-abnf-HS5TGJTU-CjbPm8FI.js +1 -0
- package/dist/assets/railroad-ebnf-LZEXJU2U-BLPi2vqK.js +1 -0
- package/dist/assets/railroad-peg-WCYAUIDC-Bs_vw0dm.js +1 -0
- package/dist/assets/{railroadDiagram-XR7U4H2S-BpB8nxWt.js → railroadDiagram-XR7U4H2S-CsAiR60R.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-CsB3aqu0.js → requirementDiagram-PLB6GJNP-CdQreqtO.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-BKGvK8Jv.js → sankeyDiagram-IPEJSGJF-BPGpWJ6l.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-Cr9hkQye.js → sequenceDiagram-PO4LG4MO-CYfCqmWa.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-C7gWKveV.js → stateDiagram-v2-GCMORJYK-BYmaqGf3.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-iRnomZ6W.js → swimlanes-2SLR337P-D5eV_i9B.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-Bm--zlh6.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-CvM8Zt_H.js → timeline-definition-EJHVYXUP-FCIIPMQE.js} +1 -1
- package/dist/assets/{treeView-Q6P3EWNA-B-3825bR.js → treeView-Q6P3EWNA-DjyFz21S.js} +1 -1
- package/dist/assets/{treemap-WGGIJYW6-wYDmmCoC.js → treemap-WGGIJYW6-C04a3IWf.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-COfhzrb4.js → usecaseDiagram-POWQR4AR-DjWtJ5rd.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-DQz5w2Ad.js → vennDiagram-UO4OBE2U-CaGYKlrU.js} +1 -1
- package/dist/assets/{wardley-WFR3VGLG-D0qPa5yM.js → wardley-WFR3VGLG-lC7L7qz7.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-B0Ffm6Eo.js → wardleyDiagram-VNRHLVJA-BwSYaW09.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-mcCWc9NA.js → xychartDiagram-PMCCYNJV-C1KTMmj3.js} +1 -1
- package/dist/index.html +2 -2
- package/docs/guide/en/v8.2.0.md +85 -0
- package/docs/guide/ja/v8.2.0.md +74 -0
- package/package.json +8 -8
- package/plugins/plugins.json +1 -1
- package/server/backends/openPath.ts +1 -1
- package/server/backends/presentPathRoot.ts +1 -1
- package/server/backends/shapescript.ts +2 -2
- package/server/blueprint/executor.ts +68 -12
- package/server/infra/host-tools.ts +2 -2
- package/server/infra/shapescript-manage-tool.ts +3 -3
- package/server/infra/shapescript-render-tool.ts +3 -3
- package/server/infra/shapescript-usdz-tool.ts +2 -2
- package/server/skills/mulmoterminal-header/SKILL.md +1 -1
- package/server/skills/mulmoterminal-keys/SKILL.md +3 -1
- package/server/skills/mulmoterminal-shared-app/SKILL.md +13 -4
- package/server/skills/mulmoterminal-shared-app/templates/class-seats.md +413 -0
- package/server/skills/mulmoterminal-shared-app/templates/meeting-room.md +3 -2
- package/server/skills/mulmoterminal-shared-app/templates/schedule-poll.md +424 -0
- package/dist/assets/architecture-7GRP2DOG-DbBbO1l3.js +0 -1
- package/dist/assets/channel-BAfBdDqJ.js +0 -1
- package/dist/assets/eventmodeling-NTZA5JFV-B5Bz1qEf.js +0 -1
- package/dist/assets/flowDiagram-KWPJA3E3-CChoJefx.js +0 -1
- package/dist/assets/index-BcxXAO6O.css +0 -1
- package/dist/assets/railroad-abnf-HS5TGJTU-B2S-Bbzp.js +0 -1
- package/dist/assets/railroad-ebnf-LZEXJU2U-DlnwWMr4.js +0 -1
- package/dist/assets/railroad-peg-WCYAUIDC-C3FYE35J.js +0 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-DliugZOm.js +0 -8
|
@@ -21,7 +21,7 @@ jobs:
|
|
|
21
21
|
- uses: actions/setup-node@v7
|
|
22
22
|
with:
|
|
23
23
|
node-version: 24
|
|
24
|
-
- run: npx -y chaffjs@0.
|
|
24
|
+
- run: npx -y chaffjs@0.18 {{PATHS}} --sarif chaff.sarif
|
|
25
25
|
continue-on-error: true
|
|
26
26
|
- uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
|
|
27
27
|
with:
|
|
@@ -12,7 +12,7 @@ repository, `.git/info/exclude`) until the person has approved the models.
|
|
|
12
12
|
1. `.blueprint/` already exists (the build created it). Everything this build records goes there.
|
|
13
13
|
2. Run chaff once through the base pack's wrapper, so its first download happens now and not in the
|
|
14
14
|
middle of a later step: `sh <base pack>/checks/chaff.sh rules --json > /dev/null`. The wrapper runs the
|
|
15
|
-
pinned chaff (`npx -y chaffjs@0.
|
|
15
|
+
pinned chaff (`npx -y chaffjs@0.18`) unless `CHAFF_BIN` names another. If it fails, show the person the
|
|
16
16
|
error and stop — do not work around it.
|
|
17
17
|
3. If the folder is a git repository, add `.blueprint/` to `.git/info/exclude`. That keeps the build's
|
|
18
18
|
working files out of commits without touching `.gitignore`, which belongs to the person.
|
|
@@ -44,7 +44,16 @@ const problems = entries.flatMap(({ name, decision }) => {
|
|
|
44
44
|
if (decision === "manual" && !inHeading(name)) return [`${name} is left to a person, and README.md has no heading naming it`];
|
|
45
45
|
return [];
|
|
46
46
|
});
|
|
47
|
-
|
|
47
|
+
// Said with the titles it read and the rule it reads them by, so the one fixing it sees what is missing rather than guessing.
|
|
48
|
+
const untested = entries.some(({ name, decision }) => decision === "feature" && !inTestTitle(name));
|
|
49
|
+
const hint = untested
|
|
50
|
+
? [
|
|
51
|
+
"",
|
|
52
|
+
`The test titles ${tests} declares, as this check reads them: ${titles.length === 0 ? "(none)" : titles.map((title) => JSON.stringify(title)).join(", ")}.`,
|
|
53
|
+
"Only the title of a test counts: the first argument, written as a plain string, of it(...) or test(...) imported from \"vitest\" in that file. A describe(...) name does not count, so put the whole name in each test title.",
|
|
54
|
+
]
|
|
55
|
+
: [];
|
|
56
|
+
if (problems.length > 0) { console.error([...problems, ...hint].join("\n")); process.exit(1); }
|
|
48
57
|
process.stdout.write(String(entries.filter((entry) => entry.decision === "feature").length));
|
|
49
58
|
' "$file" "$tests" "$titles")
|
|
50
59
|
[ "$features" -gt 0 ] || exit 0
|
|
@@ -27,7 +27,8 @@ check it against its entry and give it its test here instead of building it a se
|
|
|
27
27
|
|
|
28
28
|
Tests in `test/actions.test.ts`, one per `feature`, each with the entry's `name` in the title of its `it(…)` / `test(…)`
|
|
29
29
|
(`it("books.actions.tidy: summarises", …)`) — with `it` / `test` imported from `vitest` in that file (`import { it } from "vitest"`); the check reads titles only from
|
|
30
|
-
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count
|
|
30
|
+
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count, and neither does a `describe(…)` name (`it("tidy")` inside
|
|
31
|
+
`describe("books.actions")` is not titled `books.actions.tidy`: write the whole name in every test's own title):
|
|
31
32
|
walk the real flow against a temporary database and read back what changed. Never call the network in a test: a model
|
|
32
33
|
call goes through a client the test replaces with a stand-in, and an ingest reads a fixture file kept under
|
|
33
34
|
`test/fixtures/`. The tests must pass with no API key set.
|
|
@@ -31,7 +31,8 @@ check it against its entry and give it its test here instead of building it a se
|
|
|
31
31
|
|
|
32
32
|
Tests in `test/actions.test.ts`, one per `feature`, each with the entry's `name` in the title of its `it(…)` / `test(…)`
|
|
33
33
|
(`it("books.actions.tidy: summarises", …)`) — with `it` / `test` imported from `vitest` in that file (`import { it } from "vitest"`); the check reads titles only from
|
|
34
|
-
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count
|
|
34
|
+
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count, and neither does a `describe(…)` name (`it("tidy")` inside
|
|
35
|
+
`describe("books.actions")` is not titled `books.actions.tidy`: write the whole name in every test's own title):
|
|
35
36
|
walk the real flow through the Worker on the test D1 and read back what changed. Never call the network in a test: a
|
|
36
37
|
model call goes through a client the test replaces with a stand-in, and an ingest job takes the fetch it uses as an
|
|
37
38
|
argument, so the test hands it a fixture instead. The tests must pass with no API key set.
|
|
@@ -27,7 +27,8 @@ check it against its entry and give it its test here instead of building it a se
|
|
|
27
27
|
|
|
28
28
|
Tests in `test/blueprint/actions.spec.ts`, one per `feature`, each with the entry's `name` in the title of its `it(…)` /
|
|
29
29
|
`test(…)` (`it("books.actions.tidy: summarises", …)`) — with `it` / `test` imported from `vitest` in that file (`import { it } from "vitest"`); the check reads titles only from
|
|
30
|
-
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count
|
|
30
|
+
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count, and neither does a `describe(…)` name (`it("tidy")` inside
|
|
31
|
+
`describe("books.actions")` is not titled `books.actions.tidy`: write the whole name in every test's own title) —
|
|
31
32
|
against the emulators: do the action as a signed-in user and read back what changed, and check that someone who must not
|
|
32
33
|
do it is refused. Never call the network in a test: the model call and the fetch go through clients the test replaces
|
|
33
34
|
with stand-ins.
|
|
@@ -30,7 +30,8 @@ check it against its entry and give it its test here instead of building it a se
|
|
|
30
30
|
|
|
31
31
|
Tests in `test/actions.test.ts`, one per `feature`, each with the entry's `name` in the title of its `it(…)` / `test(…)`
|
|
32
32
|
(`it("books.actions.tidy: summarises", …)`) — with `it` / `test` imported from `vitest` in that file (`import { it } from "vitest"`); the check reads titles only from
|
|
33
|
-
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count
|
|
33
|
+
calls to those imports, so a global `it`, a helper of the same name, a comment or a title built at run time does not count, and neither does a `describe(…)` name (`it("tidy")` inside
|
|
34
|
+
`describe("books.actions")` is not titled `books.actions.tidy`: write the whole name in every test's own title):
|
|
34
35
|
walk the real flow against the local stack and read back what changed. Never call the network in a test: a model call
|
|
35
36
|
goes through a client the test replaces with a stand-in, and an ingest job takes the fetch it uses as an argument, so
|
|
36
37
|
the test hands it a fixture instead. The tests must pass with no API key set.
|
|
@@ -8,7 +8,7 @@ description: "Report what became a machine rule, what went to the guide, and wha
|
|
|
8
8
|
Write `.blueprint/style-report.md` for the person, in their language and in plain words:
|
|
9
9
|
|
|
10
10
|
- `## 機械の決まり` / `## Machine rules` — `chaff.yaml`: the genre and language, and each rule you set
|
|
11
|
-
with its reason, in one line each. How to run it: `npx -y chaffjs@0.
|
|
11
|
+
with its reason, in one line each. How to run it: `npx -y chaffjs@0.18 <file or folder>`.
|
|
12
12
|
- `## 手引き` / `## The guide` — what `STYLE.md` asks for that a machine cannot check.
|
|
13
13
|
- `## 規約にしなかったこと` / `## Left out` — what the models do that you did not make a rule, and why;
|
|
14
14
|
any genre chaff lacked; any source that was converted from Word or PDF; counter texts chaff could not see.
|
package/common/appActions.ts
CHANGED
|
@@ -5,9 +5,14 @@ import type { PlanStep } from "./plan.js";
|
|
|
5
5
|
import { currentStep, type BlueprintState } from "./state.js";
|
|
6
6
|
|
|
7
7
|
// Failed checks one step may have before the build stops for a person. Enough for an agent to read
|
|
8
|
-
// its own check output and fix it; small enough that a step it
|
|
9
|
-
// turn. Sessions that stopped to ask are not failures and do not count.
|
|
10
|
-
export const MAX_FAILED_CHECKS =
|
|
8
|
+
// its own check output and fix it, and then for repair attempts that change approach; small enough that a step it
|
|
9
|
+
// cannot fix does not burn turn after turn. Sessions that stopped to ask are not failures and do not count.
|
|
10
|
+
export const MAX_FAILED_CHECKS = 5;
|
|
11
|
+
|
|
12
|
+
// Failed checks in a row after which an attempt is a repair: doing the same again has not worked, so the attempt is
|
|
13
|
+
// told every failure so far and to find why they all failed before changing anything. A person who cannot fix the
|
|
14
|
+
// step either is the last resort, not the next one.
|
|
15
|
+
export const REPAIR_AFTER = 3;
|
|
11
16
|
|
|
12
17
|
// Rounds one repeating step may run before the build moves on regardless. A list that never empties —
|
|
13
18
|
// an agent that keeps finding more, or a `repeatWhile` that cannot say no — must not run forever; what
|
|
@@ -54,3 +59,14 @@ export function nextAction(inputs: ExecutorInputs): ExecutorAction {
|
|
|
54
59
|
if (status === "running") return inputs.sessionActive ? { kind: "wait", stepId: step.id, on: "agent" } : { kind: "spawn", stepId: step.id };
|
|
55
60
|
return forFailed(step.id, inputs);
|
|
56
61
|
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The step a build stopped at because another build was working in its folder, or null. Only that stop is resumed by
|
|
65
|
+
* itself when the folder frees: every other stop waits for something a person or the agent has to change.
|
|
66
|
+
*/
|
|
67
|
+
export function waitsOnBusyFolder(steps: readonly PlanStep[], state: BlueprintState): string | null {
|
|
68
|
+
const step = currentStep(steps, state);
|
|
69
|
+
if (!step) return null;
|
|
70
|
+
const stepState = state.steps[step.id];
|
|
71
|
+
return stepState?.status === "failed" && stepState.lastCheck?.notice?.code === "folder-busy" ? step.id : null;
|
|
72
|
+
}
|
package/common/blueprint/run.ts
CHANGED
|
@@ -21,6 +21,8 @@ export const blueprintRunSchema = z.object({
|
|
|
21
21
|
// Checks that failed for a step since a person last retried it; what stops a failing check from
|
|
22
22
|
// looping forever.
|
|
23
23
|
failedChecks: z.record(z.string(), z.number().int().nonnegative()).default({}),
|
|
24
|
+
// What each of those failed checks printed, oldest first: a repair attempt is shown them all, to see what keeps failing.
|
|
25
|
+
failureOutputs: z.record(z.string(), z.array(z.string())).default({}),
|
|
24
26
|
// The session working on the current step, if one is. Its turn ending is what triggers a check.
|
|
25
27
|
activeSessionId: z.string().nullable().default(null),
|
|
26
28
|
// `answersAtStart`: how many answers the step had when the session began, so an answer that came
|
|
@@ -4,9 +4,12 @@
|
|
|
4
4
|
import type { PlanStep } from "./plan.js";
|
|
5
5
|
import type { StepState } from "./state.js";
|
|
6
6
|
import { personLanguageLine, type PersonLanguage } from "./personLanguage.js";
|
|
7
|
+
import { REPAIR_AFTER } from "./executorPolicy.js";
|
|
7
8
|
|
|
8
9
|
// Enough of a failing check's output to act on; a build log can run far longer.
|
|
9
10
|
export const CHECK_OUTPUT_PROMPT_CHARS = 4000;
|
|
11
|
+
// Each earlier failure's output, shorter: what kept failing, not every line of it.
|
|
12
|
+
export const EARLIER_FAILURE_PROMPT_CHARS = 1500;
|
|
10
13
|
// The person's earlier answers shown to a step, newest kept: a long build with a question every round would otherwise
|
|
11
14
|
// grow every later prompt without end.
|
|
12
15
|
export const EARLIER_ANSWERS_PROMPT_CHARS = 6000;
|
|
@@ -24,6 +27,11 @@ export interface StepPromptInput {
|
|
|
24
27
|
earlierAnswers?: readonly EarlierAnswer[];
|
|
25
28
|
/** The language the person reads, when the build recorded it. */
|
|
26
29
|
language?: PersonLanguage | null;
|
|
30
|
+
/** What the step's earlier failed checks printed, oldest first — the attempts before the last one. */
|
|
31
|
+
earlierFailures?: readonly string[];
|
|
32
|
+
/** How many checks in a row have failed, the last included. A run recorded before the history was kept has the
|
|
33
|
+
* count without the outputs, and is a repair all the same. */
|
|
34
|
+
failedAttempts?: number;
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
/** A question a person answered while an earlier step, or an earlier round of this one, ran — with where it was asked. */
|
|
@@ -105,13 +113,69 @@ function roundSection(step: PlanStep, stepState: StepState | undefined): string[
|
|
|
105
113
|
];
|
|
106
114
|
}
|
|
107
115
|
|
|
108
|
-
|
|
116
|
+
/**
|
|
117
|
+
* The step's check as a shell would run it from the project, with the pack folders written in: a check names them as
|
|
118
|
+
* `$BLUEPRINT_BASE` / `$BLUEPRINT_USECASE` (bare or braced), which only the executor's own run sets.
|
|
119
|
+
*/
|
|
120
|
+
export const resolvedCheck = (check: string, packDirs: { base: string; usecase: string }): string =>
|
|
121
|
+
check.replace(/\$\{?BLUEPRINT_(BASE|USECASE)\}?/gu, (_match, which: string) => (which === "BASE" ? packDirs.base : packDirs.usecase));
|
|
122
|
+
|
|
123
|
+
// A check's output does not always say how to fix what it found, and an agent that cannot tell fails the same way
|
|
124
|
+
// until the retries run out and a person — who cannot fix it either — is left with the build. The check itself is
|
|
125
|
+
// the exact rule, so the agent is pointed at it; reading has no side effects, where running some checks would.
|
|
126
|
+
// The earlier failures, and — once enough attempts in a row have failed — the instruction to stop repeating them.
|
|
127
|
+
function repairLines(earlierFailures: readonly string[], failedAttempts: number): string[] {
|
|
128
|
+
const attempts = Math.max(earlierFailures.length + 1, failedAttempts);
|
|
129
|
+
const earlier =
|
|
130
|
+
earlierFailures.length === 0
|
|
131
|
+
? []
|
|
132
|
+
: [
|
|
133
|
+
"",
|
|
134
|
+
"Earlier attempts failed this check too. What they reported, oldest first:",
|
|
135
|
+
...earlierFailures.flatMap((output, index) => [`Attempt ${index + 1}:`, "```", tail(output, EARLIER_FAILURE_PROMPT_CHARS), "```"]),
|
|
136
|
+
];
|
|
137
|
+
const repair =
|
|
138
|
+
attempts >= REPAIR_AFTER
|
|
139
|
+
? [
|
|
140
|
+
"",
|
|
141
|
+
`This is a repair attempt: ${attempts} attempts in a row have not passed this check, so doing what they did again will not either. Before changing anything, read the check and work out why every attempt still failed — compare what each reported — then fix that cause.`,
|
|
142
|
+
]
|
|
143
|
+
: [];
|
|
144
|
+
return [...earlier, ...repair];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function failureSection(
|
|
148
|
+
step: PlanStep,
|
|
149
|
+
stepState: StepState | undefined,
|
|
150
|
+
packDirs: { base: string; usecase: string },
|
|
151
|
+
earlierFailures: readonly string[],
|
|
152
|
+
failedAttempts: number,
|
|
153
|
+
): string[] {
|
|
109
154
|
const check = stepState?.lastCheck;
|
|
110
155
|
if (!check || check.ok) return [];
|
|
111
|
-
return [
|
|
156
|
+
return [
|
|
157
|
+
...repairLines(earlierFailures, failedAttempts),
|
|
158
|
+
"",
|
|
159
|
+
"The previous attempt did not pass its check. Its output:",
|
|
160
|
+
"```",
|
|
161
|
+
tail(check.output, CHECK_OUTPUT_PROMPT_CHARS),
|
|
162
|
+
"```",
|
|
163
|
+
"Fix what it reports. When the output does not make plain what would satisfy it, read the check to see exactly what it requires — " +
|
|
164
|
+
`it is \`${resolvedCheck(step.check, packDirs)}\`, and the scripts it names are in the pack folders above — then change the work until it would pass. Never change the check or anything in the pack folders.`,
|
|
165
|
+
];
|
|
112
166
|
}
|
|
113
167
|
|
|
114
|
-
export function stepPrompt({
|
|
168
|
+
export function stepPrompt({
|
|
169
|
+
step,
|
|
170
|
+
skillFile,
|
|
171
|
+
packDirs,
|
|
172
|
+
stepState,
|
|
173
|
+
askCommand,
|
|
174
|
+
earlierAnswers: earlier = [],
|
|
175
|
+
language,
|
|
176
|
+
earlierFailures = [],
|
|
177
|
+
failedAttempts = 0,
|
|
178
|
+
}: StepPromptInput): string {
|
|
115
179
|
return [
|
|
116
180
|
`Blueprint step "${step.id}": ${step.title}.`,
|
|
117
181
|
step.description,
|
|
@@ -129,6 +193,6 @@ export function stepPrompt({ step, skillFile, packDirs, stepState, askCommand, e
|
|
|
129
193
|
...roundSection(step, stepState),
|
|
130
194
|
...earlierSection(earlier),
|
|
131
195
|
...answeredSection(stepState),
|
|
132
|
-
...failureSection(stepState),
|
|
196
|
+
...failureSection(step, stepState, packDirs, earlierFailures, failedAttempts),
|
|
133
197
|
].join("\n");
|
|
134
198
|
}
|
package/common/keymap.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as e,t}from"./mermaid-parser.core-
|
|
1
|
+
import{m as e,t}from"./mermaid-parser.core-CA27Zh_E.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-CllyRBe0.js";import"./chunk-O7XYJQB3-Gutmfs0i.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-COevsxgA.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-oKSvAMmn.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-FOHPRMQF-DzxwRta7.js";import{M as e}from"./mermaid-parser.core-CA27Zh_E.js";export{e as createArchitectureServices};
|