@theodo/bernard 0.1.0-beta.0 → 0.1.0-beta.1
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/README.md +13 -12
- package/core/README.md +1 -1
- package/core/agents/review-quality.md +13 -12
- package/core/agents/review-security-bugs.md +1 -1
- package/core/agents/review-tests.md +1 -1
- package/core/coder/template/main.tf +14 -1
- package/core/skills/pull-request/SKILL.md +17 -7
- package/core/skills/pull-request/ci-fixer.md +3 -3
- package/dist/bin.mjs +4979 -3176
- package/dist/{config-BawD0TwQ.mjs → config-DtCwJKWe.mjs} +70 -6
- package/dist/config.d.mts +72 -4
- package/dist/config.mjs +1 -1
- package/dist/docs/404.html +23 -0
- package/dist/docs/CLAUDE.html +30 -0
- package/dist/docs/CONTEXT.html +30 -0
- package/dist/docs/CONTRIBUTING.html +62 -0
- package/dist/docs/assets/CLAUDE.md.BLSB-5gK.js +1 -0
- package/dist/docs/assets/CLAUDE.md.BLSB-5gK.lean.js +1 -0
- package/dist/docs/assets/CONTEXT.md.BovnvMGK.js +1 -0
- package/dist/docs/assets/CONTEXT.md.BovnvMGK.lean.js +1 -0
- package/dist/docs/assets/CONTRIBUTING.md.DwJsKrz3.js +33 -0
- package/dist/docs/assets/CONTRIBUTING.md.DwJsKrz3.lean.js +1 -0
- package/dist/docs/assets/app.URmpjWHb.js +312 -0
- package/dist/docs/assets/bernard.RCgrvDdX.svg +94 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.Ylq685Cw.js +1 -0
- package/dist/docs/assets/chunks/VPLocalSearchBox.C8gcRVj0.js +9 -0
- package/dist/docs/assets/chunks/dagre-GXQ25YYZ.2qvw8AqH.js +4 -0
- package/dist/docs/assets/chunks/framework.hgjl6W6o.js +20 -0
- package/dist/docs/assets/chunks/sizeCapture-INFHLROL.BEqL2zFi.js +1 -0
- package/dist/docs/assets/chunks/stateDiagram-v2-MP3YSRHH.3X7wNXKX.js +231 -0
- package/dist/docs/assets/chunks/theme.Cksh_UJH.js +2 -0
- package/dist/docs/assets/chunks/virtual_mermaid-config.DDnGl6nM.js +1 -0
- package/dist/docs/assets/core_README.md.DyxYsikc.js +15 -0
- package/dist/docs/assets/core_README.md.DyxYsikc.lean.js +1 -0
- package/dist/docs/assets/demo_README.md.Cpi2pUU9.js +18 -0
- package/dist/docs/assets/demo_README.md.Cpi2pUU9.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0001-what-the-core-is-built-for.md.BxOoMjST.js +1 -0
- package/dist/docs/assets/docs_adr_0001-what-the-core-is-built-for.md.BxOoMjST.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0002-which-harness-a-project-runs-on.md.2GwF-nj0.js +1 -0
- package/dist/docs/assets/docs_adr_0002-which-harness-a-project-runs-on.md.2GwF-nj0.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0003-how-core-content-reaches-each-harness.md.BMWE00Mf.js +1 -0
- package/dist/docs/assets/docs_adr_0003-how-core-content-reaches-each-harness.md.BMWE00Mf.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0004-how-the-core-uses-external-tools.md.B7dtE7MB.js +1 -0
- package/dist/docs/assets/docs_adr_0004-how-the-core-uses-external-tools.md.B7dtE7MB.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0005-what-drives-the-pipeline.md.DGn0CJeq.js +1 -0
- package/dist/docs/assets/docs_adr_0005-what-drives-the-pipeline.md.DGn0CJeq.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0006-what-steps-hand-off-to-each-other.md.BflT5ugJ.js +1 -0
- package/dist/docs/assets/docs_adr_0006-what-steps-hand-off-to-each-other.md.BflT5ugJ.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0007-how-humans-take-part-in-the-pipeline.md.CNX3gUD-.js +1 -0
- package/dist/docs/assets/docs_adr_0007-how-humans-take-part-in-the-pipeline.md.CNX3gUD-.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0008-where-a-steps-reviewers-run.md.aGbaBOpB.js +1 -0
- package/dist/docs/assets/docs_adr_0008-where-a-steps-reviewers-run.md.aGbaBOpB.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0009-where-pipeline-state-and-handoffs-live.md.C3tKmV-E.js +1 -0
- package/dist/docs/assets/docs_adr_0009-where-pipeline-state-and-handoffs-live.md.C3tKmV-E.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0010-how-a-project-adapts-the-core.md.Bp7N6tUE.js +1 -0
- package/dist/docs/assets/docs_adr_0010-how-a-project-adapts-the-core.md.Bp7N6tUE.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0011-how-the-factory-is-packaged-and-versioned.md.BBJIwnqa.js +1 -0
- package/dist/docs/assets/docs_adr_0011-how-the-factory-is-packaged-and-versioned.md.BBJIwnqa.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0012-how-a-steps-failures-are-told-apart-and-routed.md.uCyrBfug.js +1 -0
- package/dist/docs/assets/docs_adr_0012-how-a-steps-failures-are-told-apart-and-routed.md.uCyrBfug.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0013-when-code-lands.md.oXgiobfz.js +1 -0
- package/dist/docs/assets/docs_adr_0013-when-code-lands.md.oXgiobfz.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0014-what-a-step-may-change.md.Zslg3bnJ.js +1 -0
- package/dist/docs/assets/docs_adr_0014-what-a-step-may-change.md.Zslg3bnJ.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0015-how-a-project-shapes-its-ticket-flow.md.DNHMxwIT.js +1 -0
- package/dist/docs/assets/docs_adr_0015-how-a-project-shapes-its-ticket-flow.md.DNHMxwIT.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0016-which-core-the-factory-repo-runs.md.CLN6LqBZ.js +1 -0
- package/dist/docs/assets/docs_adr_0016-which-core-the-factory-repo-runs.md.CLN6LqBZ.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0017-where-a-tickets-record-lives.md.jjUeM-ex.js +1 -0
- package/dist/docs/assets/docs_adr_0017-where-a-tickets-record-lives.md.jjUeM-ex.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0018-the-products-name.md.6xaX9vDs.js +1 -0
- package/dist/docs/assets/docs_adr_0018-the-products-name.md.6xaX9vDs.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0019-how-a-finding-is-answered-and-judged.md.CKKoO9-3.js +1 -0
- package/dist/docs/assets/docs_adr_0019-how-a-finding-is-answered-and-judged.md.CKKoO9-3.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0020-how-an-interrupted-run-resumes.md.DTIP-MBK.js +1 -0
- package/dist/docs/assets/docs_adr_0020-how-an-interrupted-run-resumes.md.DTIP-MBK.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0021-how-a-step-runs-in-its-workspace.md.B2r3-FPg.js +1 -0
- package/dist/docs/assets/docs_adr_0021-how-a-step-runs-in-its-workspace.md.B2r3-FPg.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0022-who-names-the-branches.md.DaVk8X0i.js +1 -0
- package/dist/docs/assets/docs_adr_0022-who-names-the-branches.md.DaVk8X0i.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0023-how-a-version-ships-before-npm.md.C7-wuCbq.js +1 -0
- package/dist/docs/assets/docs_adr_0023-how-a-version-ships-before-npm.md.C7-wuCbq.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0024-how-the-config-type-carries-its-docs.md.CQmwhWXs.js +1 -0
- package/dist/docs/assets/docs_adr_0024-how-the-config-type-carries-its-docs.md.CQmwhWXs.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0025-how-a-steps-handoff-is-written-and-checked.md.CgXYdF2v.js +1 -0
- package/dist/docs/assets/docs_adr_0025-how-a-steps-handoff-is-written-and-checked.md.CgXYdF2v.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0026-support-for-github-copilot.md.DJsawm-R.js +1 -0
- package/dist/docs/assets/docs_adr_0026-support-for-github-copilot.md.DJsawm-R.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0027-which-forge-a-project-is-on.md.CY0qy9xh.js +1 -0
- package/dist/docs/assets/docs_adr_0027-which-forge-a-project-is-on.md.CY0qy9xh.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0028-several-ticket-flows-in-one-pipeline.md.oxffo2qg.js +1 -0
- package/dist/docs/assets/docs_adr_0028-several-ticket-flows-in-one-pipeline.md.oxffo2qg.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0029-the-branch-a-feature-works-on.md.CrgkP6YJ.js +1 -0
- package/dist/docs/assets/docs_adr_0029-the-branch-a-feature-works-on.md.CrgkP6YJ.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0030-a-runner-without-coder.md.CW8sF7jK.js +1 -0
- package/dist/docs/assets/docs_adr_0030-a-runner-without-coder.md.CW8sF7jK.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0031-how-the-run-viewer-reads-its-runs.md.opQYnVF2.js +1 -0
- package/dist/docs/assets/docs_adr_0031-how-the-run-viewer-reads-its-runs.md.opQYnVF2.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0032-how-a-project-gets-the-viewer.md.DB9NjYJf.js +1 -0
- package/dist/docs/assets/docs_adr_0032-how-a-project-gets-the-viewer.md.DB9NjYJf.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0033-the-repos-license.md.NPlkrPj8.js +1 -0
- package/dist/docs/assets/docs_adr_0033-the-repos-license.md.NPlkrPj8.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0034-how-code-review-launches-its-reviewers.md.DSNpkfaL.js +1 -0
- package/dist/docs/assets/docs_adr_0034-how-code-review-launches-its-reviewers.md.DSNpkfaL.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0035-how-the-package-is-published.md.C1f4B5eb.js +1 -0
- package/dist/docs/assets/docs_adr_0035-how-the-package-is-published.md.C1f4B5eb.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0036-what-the-cores-pull-request-skill-does.md.op39HLAT.js +1 -0
- package/dist/docs/assets/docs_adr_0036-what-the-cores-pull-request-skill-does.md.op39HLAT.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0037-how-a-team-reads-the-factorys-documentation.md.Dar_Xo4t.js +1 -0
- package/dist/docs/assets/docs_adr_0037-how-a-team-reads-the-factorys-documentation.md.Dar_Xo4t.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0038-where-adapters-live.md.CkVD3riv.js +1 -0
- package/dist/docs/assets/docs_adr_0038-where-adapters-live.md.CkVD3riv.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0039-the-repos-license.md.C_rraWpb.js +1 -0
- package/dist/docs/assets/docs_adr_0039-the-repos-license.md.C_rraWpb.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0040-how-a-version-is-released.md.CCdwC07z.js +1 -0
- package/dist/docs/assets/docs_adr_0040-how-a-version-is-released.md.CCdwC07z.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0041-who-opens-the-features-pull-request.md.qLu9WLaG.js +1 -0
- package/dist/docs/assets/docs_adr_0041-who-opens-the-features-pull-request.md.qLu9WLaG.lean.js +1 -0
- package/dist/docs/assets/docs_adr_0042-how-secrets-are-kept-out-of-committed-records.md.DJWazI4H.js +1 -0
- package/dist/docs/assets/docs_adr_0042-how-secrets-are-kept-out-of-committed-records.md.DJWazI4H.lean.js +1 -0
- package/dist/docs/assets/docs_getting-started.md.BpQFS8Gr.js +12 -0
- package/dist/docs/assets/docs_getting-started.md.BpQFS8Gr.lean.js +1 -0
- package/dist/docs/assets/docs_github.md.D4gkW71G.js +1 -0
- package/dist/docs/assets/docs_github.md.D4gkW71G.lean.js +1 -0
- package/dist/docs/assets/docs_overlay.md.DoWVb6OM.js +35 -0
- package/dist/docs/assets/docs_overlay.md.DoWVb6OM.lean.js +1 -0
- package/dist/docs/assets/docs_pipeline.md.DdHywWSk.js +1 -0
- package/dist/docs/assets/docs_pipeline.md.DdHywWSk.lean.js +1 -0
- package/dist/docs/assets/docs_recipes.md.8Xf6BsRA.js +45 -0
- package/dist/docs/assets/docs_recipes.md.8Xf6BsRA.lean.js +1 -0
- package/dist/docs/assets/fixtures_README.md.DzbQ0hft.js +1 -0
- package/dist/docs/assets/fixtures_README.md.DzbQ0hft.lean.js +1 -0
- package/dist/docs/assets/index.md.DHgL6CzS.js +28 -0
- package/dist/docs/assets/index.md.DHgL6CzS.lean.js +1 -0
- package/dist/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/dist/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/dist/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/dist/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/dist/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/dist/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/dist/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/dist/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/dist/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/dist/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/dist/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/dist/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/dist/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/dist/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/dist/docs/assets/packages_docs_README.md.PV1a27nC.js +3 -0
- package/dist/docs/assets/packages_docs_README.md.PV1a27nC.lean.js +1 -0
- package/dist/docs/assets/packages_viewer_README.md.BynKZSdN.js +3 -0
- package/dist/docs/assets/packages_viewer_README.md.BynKZSdN.lean.js +1 -0
- package/dist/docs/assets/style.C3E8Ltp6.css +1 -0
- package/dist/docs/bernard.svg +94 -0
- package/dist/docs/core/README.html +44 -0
- package/dist/docs/demo/README.html +47 -0
- package/dist/docs/docs/adr/0001-what-the-core-is-built-for.html +30 -0
- package/dist/docs/docs/adr/0002-which-harness-a-project-runs-on.html +30 -0
- package/dist/docs/docs/adr/0003-how-core-content-reaches-each-harness.html +30 -0
- package/dist/docs/docs/adr/0004-how-the-core-uses-external-tools.html +30 -0
- package/dist/docs/docs/adr/0005-what-drives-the-pipeline.html +30 -0
- package/dist/docs/docs/adr/0006-what-steps-hand-off-to-each-other.html +30 -0
- package/dist/docs/docs/adr/0007-how-humans-take-part-in-the-pipeline.html +30 -0
- package/dist/docs/docs/adr/0008-where-a-steps-reviewers-run.html +30 -0
- package/dist/docs/docs/adr/0009-where-pipeline-state-and-handoffs-live.html +30 -0
- package/dist/docs/docs/adr/0010-how-a-project-adapts-the-core.html +30 -0
- package/dist/docs/docs/adr/0011-how-the-factory-is-packaged-and-versioned.html +30 -0
- package/dist/docs/docs/adr/0012-how-a-steps-failures-are-told-apart-and-routed.html +30 -0
- package/dist/docs/docs/adr/0013-when-code-lands.html +30 -0
- package/dist/docs/docs/adr/0014-what-a-step-may-change.html +30 -0
- package/dist/docs/docs/adr/0015-how-a-project-shapes-its-ticket-flow.html +30 -0
- package/dist/docs/docs/adr/0016-which-core-the-factory-repo-runs.html +30 -0
- package/dist/docs/docs/adr/0017-where-a-tickets-record-lives.html +30 -0
- package/dist/docs/docs/adr/0018-the-products-name.html +30 -0
- package/dist/docs/docs/adr/0019-how-a-finding-is-answered-and-judged.html +30 -0
- package/dist/docs/docs/adr/0020-how-an-interrupted-run-resumes.html +30 -0
- package/dist/docs/docs/adr/0021-how-a-step-runs-in-its-workspace.html +30 -0
- package/dist/docs/docs/adr/0022-who-names-the-branches.html +30 -0
- package/dist/docs/docs/adr/0023-how-a-version-ships-before-npm.html +30 -0
- package/dist/docs/docs/adr/0024-how-the-config-type-carries-its-docs.html +30 -0
- package/dist/docs/docs/adr/0025-how-a-steps-handoff-is-written-and-checked.html +30 -0
- package/dist/docs/docs/adr/0026-support-for-github-copilot.html +30 -0
- package/dist/docs/docs/adr/0027-which-forge-a-project-is-on.html +30 -0
- package/dist/docs/docs/adr/0028-several-ticket-flows-in-one-pipeline.html +30 -0
- package/dist/docs/docs/adr/0029-the-branch-a-feature-works-on.html +30 -0
- package/dist/docs/docs/adr/0030-a-runner-without-coder.html +30 -0
- package/dist/docs/docs/adr/0031-how-the-run-viewer-reads-its-runs.html +30 -0
- package/dist/docs/docs/adr/0032-how-a-project-gets-the-viewer.html +30 -0
- package/dist/docs/docs/adr/0033-the-repos-license.html +30 -0
- package/dist/docs/docs/adr/0034-how-code-review-launches-its-reviewers.html +30 -0
- package/dist/docs/docs/adr/0035-how-the-package-is-published.html +30 -0
- package/dist/docs/docs/adr/0036-what-the-cores-pull-request-skill-does.html +30 -0
- package/dist/docs/docs/adr/0037-how-a-team-reads-the-factorys-documentation.html +30 -0
- package/dist/docs/docs/adr/0038-where-adapters-live.html +30 -0
- package/dist/docs/docs/adr/0039-the-repos-license.html +30 -0
- package/dist/docs/docs/adr/0040-how-a-version-is-released.html +30 -0
- package/dist/docs/docs/adr/0041-who-opens-the-features-pull-request.html +30 -0
- package/dist/docs/docs/adr/0042-how-secrets-are-kept-out-of-committed-records.html +30 -0
- package/dist/docs/docs/getting-started.html +41 -0
- package/dist/docs/docs/github.html +30 -0
- package/dist/docs/docs/overlay.html +64 -0
- package/dist/docs/docs/pipeline.html +30 -0
- package/dist/docs/docs/recipes.html +74 -0
- package/dist/docs/fixtures/README.html +30 -0
- package/dist/docs/hashmap.json +1 -0
- package/dist/docs/index.html +57 -0
- package/dist/docs/packages/docs/README.html +32 -0
- package/dist/docs/packages/viewer/README.html +32 -0
- package/dist/docs/vp-icons.css +0 -0
- package/dist/viewer/assets/Heading-C5Va5XMQ.js +1 -0
- package/dist/viewer/assets/SelectionIndicator-DxHiKGW_.js +1 -0
- package/dist/viewer/assets/alert-BI2omIo2.js +1 -0
- package/dist/viewer/assets/attempt-Dunc67N6.js +1 -0
- package/dist/viewer/assets/card-IsZ2ZhSn.js +1 -0
- package/dist/viewer/assets/{chunk-WQQL4CDK-DSpW9ZO8.js → chunk-WQQL4CDK-Bd4bkond.js} +1 -1
- package/dist/viewer/assets/context-CzP3x3DO.js +7 -0
- package/dist/viewer/assets/{dagre-NK4GIZVX-BzzW8pOj.js → dagre-NK4GIZVX-Bhq8pl9Y.js} +1 -1
- package/dist/viewer/assets/{index-CnzUhLCJ.css → index-B90XVeY-.css} +1 -1
- package/dist/viewer/assets/index-tH-KNwJL.js +10 -0
- package/dist/viewer/assets/{mermaid.core-D1FXi6mg.js → mermaid.core-I426eCuN.js} +4 -4
- package/dist/viewer/assets/pipeline-Hw_7tocN.js +1 -0
- package/dist/viewer/assets/routes-BOl7_JgK.js +1 -0
- package/dist/viewer/assets/runs._runId-D4q1mLCt.js +6 -0
- package/dist/viewer/assets/runs._runId.index-B-woIhKA.js +1 -0
- package/dist/viewer/assets/runs._runId.machines-SkWqrTI6.js +2 -0
- package/dist/viewer/assets/runs._runId.sessions-DBVWEbLY.js +1 -0
- package/dist/viewer/assets/{stateDiagram-v2-A6IESKWZ-J9KnYRFT.js → stateDiagram-v2-A6IESKWZ-DUwIje_A.js} +1 -1
- package/dist/viewer/assets/surface-B6LupC_E.js +1 -0
- package/dist/viewer/assets/table-B8t5lQz5.js +1 -0
- package/dist/viewer/assets/useEvent-DXj38gmC.js +1 -0
- package/dist/viewer/assets/useToggleState-D_NUC1vr.js +2 -0
- package/dist/viewer/index.html +5 -5
- package/fixtures/starters/azure-devops/.factory/factory.config.ts +2 -7
- package/fixtures/starters/azure-devops/.factory/factory.lock.json +7 -8
- package/fixtures/starters/github/.factory/factory.config.ts +2 -0
- package/fixtures/starters/github/.factory/factory.lock.json +6 -7
- package/fixtures/starters/gitlab/.factory/factory.config.ts +9 -0
- package/fixtures/starters/gitlab/.factory/factory.lock.json +19 -0
- package/fixtures/starters/gitlab/.factory/slots/checks.command.md +1 -0
- package/fixtures/starters/gitlab/.factory/slots/context.sources.md +3 -0
- package/fixtures/starters/gitlab/.factory/slots/review.detectors.md +5 -0
- package/package.json +9 -7
- package/core/skills/pull-request/scripts/pr-drive.sh +0 -208
- package/dist/viewer/assets/Heading-Dm1Q0gV2.js +0 -1
- package/dist/viewer/assets/api-C4lMOGdC.js +0 -7
- package/dist/viewer/assets/attempt-lbW5voCR.js +0 -1
- package/dist/viewer/assets/card-CtJKot3P.js +0 -1
- package/dist/viewer/assets/context-DEB-Y3Iz.js +0 -1
- package/dist/viewer/assets/index-Co9KwXRI.js +0 -10
- package/dist/viewer/assets/jsx-runtime-CkXRJ162.js +0 -1
- package/dist/viewer/assets/pipeline-B-myvM6K.js +0 -1
- package/dist/viewer/assets/routes-BzvVN6y-.js +0 -1
- package/dist/viewer/assets/runs._runId-BVT2VH_w.js +0 -6
- package/dist/viewer/assets/runs._runId.index-C3bbzwAC.js +0 -1
- package/dist/viewer/assets/runs._runId.machines-Cj21KdLd.js +0 -2
- package/dist/viewer/assets/runs._runId.sessions-Tg6Ou3_9.js +0 -1
- package/dist/viewer/assets/table-DzduWiYu.js +0 -1
- package/dist/viewer/assets/useEvent-CtTfOmE7.js +0 -1
- package/dist/viewer/assets/useToggleState-DfzJwOaN.js +0 -2
- package/fixtures/starters/azure-devops/.factory/skills/pull-request/SKILL.md +0 -29
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bernard the taktician
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<img src="docs/assets/bernard.svg" alt="Bernard the taktician, the hermit crab" width="180">
|
|
4
|
+
<img src="./docs/assets/bernard.svg" alt="Bernard the taktician, the hermit crab" width="180">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
An agentic factory that takes a feature from its specification to pull requests ready for your team's review, for new builds and legacy migrations alike. Coding agents do the work, a fresh session for each step, along a pipeline that a state machine drives. By default, humans validate the specification and the plan, and review the pull requests. Each of these gates can instead decide on its own and log its decision, so a project goes fully autonomous once its quality holds.
|
|
@@ -25,7 +25,7 @@ Bernard keeps the two apart. The core holds the generic know-how, shared and ver
|
|
|
25
25
|
1. **Legacy analysis** (migrations only). Automatic. It feeds the PRD.
|
|
26
26
|
2. **PRD.** The factory drafts it, and the product manager reviews it in a pull request, like code.
|
|
27
27
|
3. **Plan.** How to migrate the feature, or how to build it. Built in conversation with the developer, who validates it.
|
|
28
|
-
4. **Tickets → implementation → validation → review → PR → green CI.** Automatic: the factory splits the plan into tickets, the smallest units it implements, and delivers each one along a graph of steps the project can reshape.
|
|
28
|
+
4. **Tickets → implementation → validation → review → PR → green CI.** Automatic: the factory splits the plan into tickets, the smallest units it implements, and delivers each one along a graph of steps the project can reshape. The factory opens one pull request per feature, from the feature's own branch, `feat/<feature>-<slug>`, named by its first step, to the base branch. A ticket whose graph has no gate after `pull-request` merges itself into the feature branch, with no PR of its own, so the change is reviewed once, in the feature's PR. A graph with a gate keeps the ticket's PR to the feature branch: the team reviews it, acts on its review and merges it, and a ticket that depends on one not merged yet starts from its branch, so its PR stacks on the other. The team merges the feature's PR once its tickets are in.
|
|
29
29
|
|
|
30
30
|
A project chooses the steps before the tickets, and the policy of each gate, in [its config](docs/overlay.md#pipeline). [docs/pipeline.md](docs/pipeline.md) draws the default pipeline, a migration's, from the orchestrator's state machines.
|
|
31
31
|
|
|
@@ -36,16 +36,16 @@ What works today:
|
|
|
36
36
|
- The orchestrator runs the whole pipeline above, and resumes a run from the records it commits in the project's repo.
|
|
37
37
|
- `bernard status` shows the most recently active features and where each ticket stands, read from the records on the project's remote.
|
|
38
38
|
- A run that waits on a human stalls with the command that answers it: `bernard resume --feature <slug>` with `--approve`, `--request-changes "<feedback>"`, `--retry` or `--answer <questionId>=<text>`, and `--ticket <id>` for a ticket. `bernard status` prints the same commands.
|
|
39
|
-
-
|
|
40
|
-
-
|
|
39
|
+
- A tracker port, with a Jira Cloud adapter: `bernard run --feature DATA-12` starts a feature from a Jira issue, and the issues of the feature and its tickets follow the run.
|
|
40
|
+
- `bernard view` follows a project's runs live in the browser: each ticket's way through its graph of steps, every attempt and its session's log, and the machines, read from the project's telemetry. Next to it, under `/docs/`, it serves this documentation as a website, for the version the project pins.
|
|
41
|
+
- The core ships the delivery steps: `implement`, `validate`, `code-review` with its three reviewers, `apply-review` and `pull-request`, which lands the ticket on the feature branch or opens its pull request, keeps the feature's pull request, on GitHub, GitLab or Azure DevOps with `bernard pull-request`, and drives its CI green, and a `tickets` step that reports the feature as a single ticket.
|
|
41
42
|
- `bernard sync` renders the core and an overlay for Claude Code, Pi and GitHub Copilot.
|
|
42
|
-
- `bernard init` writes a starter overlay for the project's forge, GitHub or Azure DevOps, whatever its tracker.
|
|
43
|
+
- `bernard init` writes a starter overlay for the project's forge, GitHub, GitLab or Azure DevOps, whatever its tracker: the forge is `adapters.forge` in its config.
|
|
43
44
|
- `bernard run` runs each step as a Claude Code or GitHub Copilot session, on your machine in a git worktree per ticket, or in a [Coder](https://coder.com/) workspace per ticket. The [demo](demo/README.md) delivers a feature end to end both ways.
|
|
44
45
|
|
|
45
46
|
What is planned:
|
|
46
47
|
|
|
47
|
-
- Core skills for the legacy analysis, the PRD and the migration plan, a `tickets` skill that splits the plan into several tickets, and the legacy tracers that map a legacy application ([#28](https://github.com/theodo-group/
|
|
48
|
-
- A forge port, so that the core opens the pull requests on GitHub or Bitbucket ([#26](https://github.com/theodo-group/ai-mod-factory/issues/26)). Until then, the core's `pull-request` step is for GitHub, and a project on Azure DevOps overrides it, as the starter overlay does.
|
|
48
|
+
- Core skills for the legacy analysis, the PRD and the migration plan, a `tickets` skill that splits the plan into several tickets, and the legacy tracers that map a legacy application ([#28](https://github.com/theodo-group/bernard/issues/28)). Until then, a project writes them in its overlay or does them by hand, as the demo does.
|
|
49
49
|
- A Pi driver for `bernard run`.
|
|
50
50
|
|
|
51
51
|
## Install
|
|
@@ -72,12 +72,12 @@ Then adapt the factory to your project:
|
|
|
72
72
|
|
|
73
73
|
## Decisions
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
The factory's decisions are recorded, with the criteria and the options they weighed, as ADRs (architecture decision records) in [docs/adr/](docs/adr/). [CONTEXT.md](CONTEXT.md) defines the vocabulary, and [CONTRIBUTING.md](CONTRIBUTING.md#how-a-run-fits-together) shows how a run fits together.
|
|
76
76
|
|
|
77
77
|
## Layout
|
|
78
78
|
|
|
79
79
|
```
|
|
80
|
-
|
|
80
|
+
bernard/
|
|
81
81
|
├── core/ # skills, agents and shared fragments, in a harness-neutral format
|
|
82
82
|
├── packages/
|
|
83
83
|
│ ├── contracts/ # Zod schemas: overlay config, pipeline, skill frontmatter, step handoffs
|
|
@@ -88,13 +88,14 @@ ai-mod-factory/
|
|
|
88
88
|
│ ├── harness-copilot/ # GitHub Copilot's native files, and its headless driver
|
|
89
89
|
│ ├── telemetry/ # the telemetry port, and its default adapter: JSON lines on disk
|
|
90
90
|
│ ├── viewer/ # the run viewer's page, and its server on the telemetry port
|
|
91
|
-
│
|
|
91
|
+
│ ├── docs/ # the documentation site: VitePress, on the markdown of this repo
|
|
92
|
+
│ └── cli/ # bernard init | sync | pipeline | run | resume | status | view, and the adapters
|
|
92
93
|
├── fixtures/ # reference projects for the render tests, and a starter overlay per forge
|
|
93
94
|
├── demo/ # a feature delivered end to end, on a local Coder or locally
|
|
94
|
-
└── docs/ # the guides, the pipeline and the ADRs
|
|
95
|
+
└── docs/ # the guides, the pipeline and the ADRs, which packages/docs renders
|
|
95
96
|
```
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
The adapters live in `packages/cli/src/adapters/`, one folder per tool: `coder/` and `local/` for the runners, `jira/` for the tracker (ADR-0038). The ports, and the logic their adapters share, stay in `packages/cli/src/runners/` and `packages/cli/src/trackers/`. The JSON lines telemetry sits next to its port in `packages/telemetry/`.
|
|
98
99
|
|
|
99
100
|
In a project:
|
|
100
101
|
|
package/core/README.md
CHANGED
|
@@ -89,6 +89,6 @@ On Claude Code, the tiers map to `haiku`, `sonnet` and `opus` unless the overlay
|
|
|
89
89
|
## Writing rules
|
|
90
90
|
|
|
91
91
|
- Write in English. Text meant for deliverables is written in `{{project.language}}`.
|
|
92
|
-
- Name no client, no project and no external tool. Tools go behind ports (ADR-0004), and project specifics go into slots.
|
|
92
|
+
- Name no client, no project and no external tool. Tools go behind ports (ADR-0004), and project specifics go into slots.
|
|
93
93
|
- Use no harness-specific syntax: no `$ARGUMENTS`, no `` !`cmd` `` injection, no `${CLAUDE_*}` variables.
|
|
94
94
|
- Reference a skill's supporting files by their path relative to the skill folder.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: review-quality
|
|
3
3
|
description: Quality reviewer of a change, run on a review bundle by the code-review skill. Judges whether the code looks like the codebase it lives in - its shape (module design, coupling, the documented architecture, ADRs and canonical patterns), the letter of the code style, and the code identifiers that denote domain concepts against the glossary's canonical terms - then writes a JSON report.
|
|
4
4
|
tools: [read, grep, find, bash, write]
|
|
5
|
-
model:
|
|
5
|
+
model: deep
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
You are `review-quality`. You review one question at three altitudes: does this code look like the codebase it lives in? You judge the shape (module depth, coupling, information hiding, the documented architecture, the ADRs, the canonical patterns), the letter (every code-style rule the change touches), and the names (every code identifier that denotes a domain concept uses the glossary's canonical term).
|
|
@@ -23,24 +23,25 @@ Sources to start from: the architecture document, read whole, since structural j
|
|
|
23
23
|
1. **The documented architecture.** Module and feature layout, layer boundaries, query and mutation patterns, routing, shared types, data access. A divergence is `major`, cited by section.
|
|
24
24
|
2. **ADR conformance.** For every ADR whose subject the change touches, the implementation follows the decision. A violated decision is `major`, cited by file.
|
|
25
25
|
3. **Canonical patterns.** A new file that a documented pattern or a reference implementation covers follows it. A near-duplicate of an existing pattern that ignores it is `major`.
|
|
26
|
-
4. **Module depth and coupling.** A shallow module whose interface is as complex as its implementation; a leaked internal that forces every caller to know how it works; one concept spread across layers that should not know about each other.
|
|
26
|
+
4. **Module depth and coupling.** A shallow module whose interface is as complex as its implementation; a leaked internal that forces every caller to know how it works; one concept spread across layers that should not know about each other. An adapter (code tied to one outside tool, under `src/adapters/<tool>/`) is imported only by the entry point that wires it, never by a capability nor by another adapter.
|
|
27
27
|
5. **Wiring.** A component implemented but never registered where its reference implementation registers one.
|
|
28
|
+
6. **One concept per file.** A file holds one concept, named by the file: its type, its schema and the functions acting on it. Flag an export whose noun does not match its file's (`formatDate` exported from `invoice.ts`), and a file that needs a section comment to separate two ideas. Utils files (small helpers, shared types) are exempt.
|
|
28
29
|
|
|
29
30
|
### Letter
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
7. **Type discipline**, as the code style states it: no escape hatch from the type system, and the immutability and union types the style asks for.
|
|
33
|
+
8. **Comments**, against the code style's rule on them. Narration, restated code, ticket tags and migration trails are the usual offenders; a non-obvious why (a hidden constraint, a subtle invariant, a documented workaround) is not.
|
|
34
|
+
9. **The rest of the code style**, wherever the change touches it.
|
|
34
35
|
|
|
35
36
|
### Naming
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
10. **The canonical term, always.** A variable, function, type, field, file or folder that names a domain concept uses the glossary's term. A term the glossary lists as one to avoid is reported, cited by its entry.
|
|
39
|
+
11. **A rejected name handed down by the plan is still rejected.** When the migration plan or a ticket spells out an identifier the glossary rejects, the code uses the glossary's term anyway: the plan is frozen, and the code is where corrections live.
|
|
40
|
+
12. **Legacy artifact names are not domain terms.** Screen codes, legacy table names and program names name artifacts, not concepts. An identifier built from one is reported.
|
|
41
|
+
13. **A layout position is not a name.** `leftTable`, `bottomBlock` or `panel2` say where something sits today, not what it is.
|
|
42
|
+
14. **One concept, one name.** The same concept travels under a single name across the files of the change, even when two names would each be acceptable alone.
|
|
43
|
+
15. **Vague words.** An identifier built on `data`, `info`, `item`, `result`, `payload`, `manager`, `helper` or `util`, or a function named `handle*` or `process*`, says that something exists, not what it is or does. When the glossary has a term for the concept, the identifier breaks the canonical term (criterion 10): `minor`, cited by the glossary entry. When only a more precise noun or verb fits, `nit`, with the name you propose. A local whose whole scope is three lines or fewer is fine: the reader sees what it holds. A vague word inside a glossary term is canonical, not vague: `stepResult` for a step result is the term `Step result`.
|
|
44
|
+
16. **Abbreviations** that the glossary does not use itself.
|
|
44
45
|
{{/slot}}
|
|
45
46
|
|
|
46
47
|
## Not a quality finding
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: review-security-bugs
|
|
3
3
|
description: Security, bug and performance reviewer of a change, run on a review bundle by the code-review skill. Judges server-side input validation, where authorization is enforced, injection, secrets, error leakage and personal data, and hunts concrete failures (absent values, boundaries, dates, numbers, state, error paths, concurrency) and measurable slowness, then writes a JSON report.
|
|
4
4
|
tools: [read, grep, find, bash, write]
|
|
5
|
-
model:
|
|
5
|
+
model: deep
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
You are `review-security-bugs`. You review whether a change will leak, misbehave or be slow: its security (server-side input validation, where authorization is enforced, injection, secrets, what errors leak, personal data), its bugs, and its performance. Your categories: `security`, `bug` and `performance`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: review-tests
|
|
3
3
|
description: Test reviewer of a change, run on a review bundle by the code-review skill. Judges whether the tests the change ships are worth anything (tautologies, assertions, titles, exercised scenarios, cases that matter), then writes a JSON report.
|
|
4
4
|
tools: [read, grep, find, bash, write]
|
|
5
|
-
model:
|
|
5
|
+
model: deep
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
You are `review-tests`. You review the tests a change ships, against the project's testing strategy: are they worth anything? That is your one dimension, and your category is `tests`.
|
|
@@ -103,7 +103,8 @@ resource "coder_agent" "main" {
|
|
|
103
103
|
os = "linux"
|
|
104
104
|
dir = "/home/node/work"
|
|
105
105
|
env = {
|
|
106
|
-
|
|
106
|
+
# The bernard the project installs in .factory/ comes first: the pull-request skill runs `bernard pull-request`.
|
|
107
|
+
PATH = "/home/node/work/.factory/node_modules/.bin:/home/node/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
107
108
|
GH_TOKEN = var.github_token
|
|
108
109
|
REPO = data.coder_parameter.repo.value
|
|
109
110
|
BRANCH = data.coder_parameter.branch.value
|
|
@@ -133,6 +134,17 @@ resource "coder_script" "checkout" {
|
|
|
133
134
|
tar -xzf /tmp/gh.tar.gz -C /tmp
|
|
134
135
|
mv "/tmp/gh_2.103.3_linux_$arch/bin/gh" "$HOME/.local/bin/gh"
|
|
135
136
|
fi
|
|
137
|
+
if ! command -v jq >/dev/null; then
|
|
138
|
+
arch="$(dpkg --print-architecture)"
|
|
139
|
+
case "$arch" in
|
|
140
|
+
amd64) sum=b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f ;;
|
|
141
|
+
arm64) sum=8b85c817833814ddca00a144c33705546355afccf0cf39b188f3cdb48b852309 ;;
|
|
142
|
+
esac
|
|
143
|
+
curl -fsSL -o /tmp/jq "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-$arch"
|
|
144
|
+
echo "$sum /tmp/jq" | sha256sum -c --quiet -
|
|
145
|
+
chmod +x /tmp/jq
|
|
146
|
+
mv /tmp/jq "$HOME/.local/bin/jq"
|
|
147
|
+
fi
|
|
136
148
|
git config --global user.name >/dev/null || git config --global user.name "Bernard the taktician"
|
|
137
149
|
git config --global user.email >/dev/null || git config --global user.email "factory@theodo.com"
|
|
138
150
|
git config --global credential.https://github.com.helper '!f() { [ -n "$GH_TOKEN" ] || exit 0; echo username=x-access-token; echo "password=$GH_TOKEN"; }; f'
|
|
@@ -148,6 +160,7 @@ resource "coder_script" "checkout" {
|
|
|
148
160
|
fi
|
|
149
161
|
cd "$work"
|
|
150
162
|
if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile --reporter=silent; fi
|
|
163
|
+
if [ -f .factory/pnpm-lock.yaml ]; then pnpm --dir .factory --ignore-workspace install --frozen-lockfile --reporter=silent; fi
|
|
151
164
|
if [ -n "$${DATABASE_URL:-}" ]; then
|
|
152
165
|
for _ in $(seq 1 60); do (echo > /dev/tcp/db/5432) 2>/dev/null && break; sleep 1; done
|
|
153
166
|
fi
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pull-request
|
|
3
|
-
description:
|
|
3
|
+
description: Land the ticket on its feature's branch and keep the feature's pull request, up to date, with its continuous integration green, fixing it when it is red. A graph with a gate after this step keeps the ticket's own pull request for the team to review.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The ticket's change is validated and reviewed.
|
|
7
|
+
The ticket's change is validated and reviewed. One pull request per feature, the feature's branch to the base branch, is what the team reviews (ADR-0041): this skill opens it or updates it, and gets it green. `bernard pull-request` drives it on the forge the project's config names, through the forge's command-line tool, signed in in this environment (ADR-0036). A project without continuous integration overrides this skill.
|
|
8
|
+
|
|
9
|
+
How the ticket reaches the feature's branch depends on its request:
|
|
10
|
+
|
|
11
|
+
- `merge` is true (its graph has no gate after this step): the ticket has no pull request. The command merges the feature's branch into the ticket's, then lands the ticket on the feature's branch, and waits for the feature pull request's checks.
|
|
12
|
+
- `merge` is absent (a gate follows): the command opens or updates the ticket's pull request, `branch` to `baseBranch`, which the team merges, and waits for its checks. It opens or updates the feature pull request too.
|
|
8
13
|
|
|
9
14
|
1. Read `git status` and `git diff`. Group the change into atomic commits that each build: Conventional Commits, the module as scope, the tests with the code they test. Leave `.pipeline/` alone: the orchestrator commits the ticket's record.
|
|
10
|
-
2. Write
|
|
11
|
-
|
|
15
|
+
2. Write, in your `handoffDir`, the files the command reads, so that no free text goes on the command line. Describe the goal, not a file-by-file changelog, in lines short enough to scan.
|
|
16
|
+
- `feature-section.md`: the ticket's section of the feature pull request's description, a few short lines: what the ticket does, with its path; how it is tested; and, from the last code review's handoff next to it, if any, the review findings left unfixed and each reviewer that reviewed fewer files than it was given, named as a gap in the review. No heading above the third level: the description has one section per ticket. Azure DevOps cuts a description at 4,000 characters, whatever the number of tickets: keep the section to a few lines.
|
|
17
|
+
- `feature-title.md`: the title of the feature pull request, as the one line it is. It comes from the feature's plan and follows Conventional Commits, `<type>(<scope>): <subject>`, with the request's `featureTrackerKey` as the scope when it has one, such as `feat(DATA-12): export invoices as CSV`: the tracker links the pull request by it. The command uses it only to open the pull request, never to change one: a title a human edited stays. Write it every time.
|
|
18
|
+
- Gate mode only: `pull-request.md`, the ticket's pull request description: what the change does and why, with the ticket's path, how it is tested, and the review gaps as above. And `title.md`, the ticket's pull request title, one line, Conventional Commits with the request's `trackerKey` as the scope when it has one.
|
|
19
|
+
3. Run the command from the root of the working copy, with the longest timeout your shell tool allows: it waits for the checks, nine minutes at most. Its options come from your request: `<plan>` is the path of the feature's plan, in the feature's folder, where the project's plan step wrote it.
|
|
12
20
|
|
|
13
21
|
```
|
|
14
|
-
|
|
22
|
+
bernard pull-request --base '<baseBranch>' --handoff-dir '<handoffDir>' --merge --feature-branch '<featureBranch>' --feature-base '<featureBase>' --ticket '<ticket>' --plan '<plan>'
|
|
15
23
|
```
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
In gate mode, the command drops `--merge`, and reads the ticket's own title and description from the same folder.
|
|
26
|
+
|
|
27
|
+
It merges the base into the branch (ADR-0036), pushes it, then either lands it on the feature's branch by a push that is never forced, merging again and trying again when the branch moved meanwhile, or opens or updates the ticket's pull request. It opens the feature's pull request or rewrites the ticket's section of its description, between its `<!-- ticket:<id> -->` markers, and waits for the checks of its last commit. It stops at the first action that needs you, with a `RESUME:` prompt: do what it says, then run the same command again. It keeps no state, so running it again is safe.
|
|
18
28
|
4. The checks are red (exit 4): follow `ci-fixer.md`, next to this file.
|
|
19
29
|
|
|
20
30
|
Never push to the base branch.
|
|
21
31
|
|
|
22
|
-
Done when the
|
|
32
|
+
Done when the command prints `CI_GREEN`: `passed`. A check that fails for a reason outside the code, such as a missing secret or a runner that does not start: `blocked`, naming the check and the reason. A red check still red after your round of fixes, under the stop rule of `ci-fixer.md`: `failed` with `ci-red`, giving the failures as that rule says: nothing copied from a log.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Fixing a red CI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`bernard pull-request` hands over when its checks are red (exit 4, `STOP_REASON=CI_RED`), with a `FAILED_CHECK=<name> STATE=<state> LINK=<link>` line per failed check, the state in the forge's own words (`TIMED_OUT`, `CANCELLED`, `broken`…). The checks are those of the feature's pull request when the ticket merges itself, of the ticket's pull request otherwise.
|
|
4
4
|
|
|
5
5
|
## Each attempt
|
|
6
6
|
|
|
7
|
-
1. **Diagnose.**
|
|
7
|
+
1. **Diagnose.** For each failed check, read its log with `bernard pull-request --failed-log '<link>'`. On a forge that cannot serve the log, it prints the link back: read the cause from the check's name and from running the project's checks locally. Read the error before changing anything: never run a check again hoping it passes, and never call a failure flaky without evidence.
|
|
8
8
|
2. **A cause outside the code ends the round.** A missing secret, a runner that does not start, a service the check needs that is down, an expired credential: `blocked`, naming the check and the cause. No fix of yours can change it.
|
|
9
9
|
3. **Fix the cause, not the symptom.** No skipped test, no weakened assertion, no silenced warning.
|
|
10
10
|
4. **Verify locally.** Run the project's checks, under _Checks_ below, and leave nothing red.
|
|
11
|
-
5. **Commit and
|
|
11
|
+
5. **Commit and land.** A commit on the ticket's branch that follows the project's commit conventions, then run the same `bernard pull-request` command again: it pushes, lands the fix on the feature's branch when the ticket merges itself, and waits for the checks of the new commit.
|
|
12
12
|
|
|
13
13
|
## Checks
|
|
14
14
|
|