@lbruton/spec-workflow-mcp 2.2.4
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/CHANGELOG.md +955 -0
- package/LICENSE +674 -0
- package/README.ar.md +314 -0
- package/README.de.md +314 -0
- package/README.es.md +314 -0
- package/README.fr.md +314 -0
- package/README.it.md +314 -0
- package/README.ja.md +316 -0
- package/README.ko.md +314 -0
- package/README.md +373 -0
- package/README.pt.md +314 -0
- package/README.ru.md +314 -0
- package/README.zh.md +314 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +264 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/index-args.test.d.ts +2 -0
- package/dist/__tests__/index-args.test.d.ts.map +1 -0
- package/dist/__tests__/index-args.test.js +43 -0
- package/dist/__tests__/index-args.test.js.map +1 -0
- package/dist/__tests__/index-entrypoint.test.d.ts +2 -0
- package/dist/__tests__/index-entrypoint.test.d.ts.map +1 -0
- package/dist/__tests__/index-entrypoint.test.js +23 -0
- package/dist/__tests__/index-entrypoint.test.js.map +1 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +188 -0
- package/dist/config.js.map +1 -0
- package/dist/core/__tests__/git-utils.test.d.ts +2 -0
- package/dist/core/__tests__/git-utils.test.d.ts.map +1 -0
- package/dist/core/__tests__/git-utils.test.js +179 -0
- package/dist/core/__tests__/git-utils.test.js.map +1 -0
- package/dist/core/__tests__/mdx-validator.test.d.ts +2 -0
- package/dist/core/__tests__/mdx-validator.test.d.ts.map +1 -0
- package/dist/core/__tests__/mdx-validator.test.js +42 -0
- package/dist/core/__tests__/mdx-validator.test.js.map +1 -0
- package/dist/core/__tests__/path-utils.test.d.ts +2 -0
- package/dist/core/__tests__/path-utils.test.d.ts.map +1 -0
- package/dist/core/__tests__/path-utils.test.js +344 -0
- package/dist/core/__tests__/path-utils.test.js.map +1 -0
- package/dist/core/__tests__/project-registry.test.d.ts +2 -0
- package/dist/core/__tests__/project-registry.test.d.ts.map +1 -0
- package/dist/core/__tests__/project-registry.test.js +62 -0
- package/dist/core/__tests__/project-registry.test.js.map +1 -0
- package/dist/core/__tests__/security-utils.test.d.ts +2 -0
- package/dist/core/__tests__/security-utils.test.d.ts.map +1 -0
- package/dist/core/__tests__/security-utils.test.js +643 -0
- package/dist/core/__tests__/security-utils.test.js.map +1 -0
- package/dist/core/__tests__/task-validator.test.d.ts +2 -0
- package/dist/core/__tests__/task-validator.test.d.ts.map +1 -0
- package/dist/core/__tests__/task-validator.test.js +237 -0
- package/dist/core/__tests__/task-validator.test.js.map +1 -0
- package/dist/core/archive-service.d.ts +10 -0
- package/dist/core/archive-service.d.ts.map +1 -0
- package/dist/core/archive-service.js +99 -0
- package/dist/core/archive-service.js.map +1 -0
- package/dist/core/dashboard-session.d.ts +49 -0
- package/dist/core/dashboard-session.d.ts.map +1 -0
- package/dist/core/dashboard-session.js +132 -0
- package/dist/core/dashboard-session.js.map +1 -0
- package/dist/core/git-utils.d.ts +25 -0
- package/dist/core/git-utils.d.ts.map +1 -0
- package/dist/core/git-utils.js +87 -0
- package/dist/core/git-utils.js.map +1 -0
- package/dist/core/global-dir.d.ts +44 -0
- package/dist/core/global-dir.d.ts.map +1 -0
- package/dist/core/global-dir.js +74 -0
- package/dist/core/global-dir.js.map +1 -0
- package/dist/core/implementation-log-migrator.d.ts +41 -0
- package/dist/core/implementation-log-migrator.d.ts.map +1 -0
- package/dist/core/implementation-log-migrator.js +258 -0
- package/dist/core/implementation-log-migrator.js.map +1 -0
- package/dist/core/mdx-validator.d.ts +14 -0
- package/dist/core/mdx-validator.d.ts.map +1 -0
- package/dist/core/mdx-validator.js +34 -0
- package/dist/core/mdx-validator.js.map +1 -0
- package/dist/core/parser.d.ts +11 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +126 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/path-utils.d.ts +63 -0
- package/dist/core/path-utils.d.ts.map +1 -0
- package/dist/core/path-utils.js +288 -0
- package/dist/core/path-utils.js.map +1 -0
- package/dist/core/project-registry.d.ts +94 -0
- package/dist/core/project-registry.d.ts.map +1 -0
- package/dist/core/project-registry.js +297 -0
- package/dist/core/project-registry.js.map +1 -0
- package/dist/core/security-utils.d.ts +97 -0
- package/dist/core/security-utils.d.ts.map +1 -0
- package/dist/core/security-utils.js +264 -0
- package/dist/core/security-utils.js.map +1 -0
- package/dist/core/task-parser.d.ts +63 -0
- package/dist/core/task-parser.d.ts.map +1 -0
- package/dist/core/task-parser.js +332 -0
- package/dist/core/task-parser.js.map +1 -0
- package/dist/core/task-validator.d.ts +35 -0
- package/dist/core/task-validator.d.ts.map +1 -0
- package/dist/core/task-validator.js +236 -0
- package/dist/core/task-validator.js.map +1 -0
- package/dist/core/workspace-initializer.d.ts +16 -0
- package/dist/core/workspace-initializer.d.ts.map +1 -0
- package/dist/core/workspace-initializer.js +165 -0
- package/dist/core/workspace-initializer.js.map +1 -0
- package/dist/dashboard/__tests__/approval-storage-path-resolution.test.d.ts +2 -0
- package/dist/dashboard/__tests__/approval-storage-path-resolution.test.d.ts.map +1 -0
- package/dist/dashboard/__tests__/approval-storage-path-resolution.test.js +69 -0
- package/dist/dashboard/__tests__/approval-storage-path-resolution.test.js.map +1 -0
- package/dist/dashboard/__tests__/multi-server-approvals-content.test.d.ts +2 -0
- package/dist/dashboard/__tests__/multi-server-approvals-content.test.d.ts.map +1 -0
- package/dist/dashboard/__tests__/multi-server-approvals-content.test.js +116 -0
- package/dist/dashboard/__tests__/multi-server-approvals-content.test.js.map +1 -0
- package/dist/dashboard/__tests__/watcher-error-handling.test.d.ts +2 -0
- package/dist/dashboard/__tests__/watcher-error-handling.test.d.ts.map +1 -0
- package/dist/dashboard/__tests__/watcher-error-handling.test.js +118 -0
- package/dist/dashboard/__tests__/watcher-error-handling.test.js.map +1 -0
- package/dist/dashboard/approval-storage.d.ts +139 -0
- package/dist/dashboard/approval-storage.d.ts.map +1 -0
- package/dist/dashboard/approval-storage.js +586 -0
- package/dist/dashboard/approval-storage.js.map +1 -0
- package/dist/dashboard/execution-history-manager.d.ts +52 -0
- package/dist/dashboard/execution-history-manager.d.ts.map +1 -0
- package/dist/dashboard/execution-history-manager.js +161 -0
- package/dist/dashboard/execution-history-manager.js.map +1 -0
- package/dist/dashboard/implementation-log-manager.d.ts +97 -0
- package/dist/dashboard/implementation-log-manager.d.ts.map +1 -0
- package/dist/dashboard/implementation-log-manager.js +586 -0
- package/dist/dashboard/implementation-log-manager.js.map +1 -0
- package/dist/dashboard/job-scheduler.d.ts +91 -0
- package/dist/dashboard/job-scheduler.d.ts.map +1 -0
- package/dist/dashboard/job-scheduler.js +321 -0
- package/dist/dashboard/job-scheduler.js.map +1 -0
- package/dist/dashboard/multi-server.d.ts +42 -0
- package/dist/dashboard/multi-server.d.ts.map +1 -0
- package/dist/dashboard/multi-server.js +1313 -0
- package/dist/dashboard/multi-server.js.map +1 -0
- package/dist/dashboard/parser.d.ts +18 -0
- package/dist/dashboard/parser.d.ts.map +1 -0
- package/dist/dashboard/parser.js +243 -0
- package/dist/dashboard/parser.js.map +1 -0
- package/dist/dashboard/project-manager.d.ts +82 -0
- package/dist/dashboard/project-manager.d.ts.map +1 -0
- package/dist/dashboard/project-manager.js +257 -0
- package/dist/dashboard/project-manager.js.map +1 -0
- package/dist/dashboard/public/assets/Inter-Bold-CD3Pr7BX.woff2 +0 -0
- package/dist/dashboard/public/assets/Inter-Medium-B_8v_WHh.woff2 +0 -0
- package/dist/dashboard/public/assets/Inter-Regular-DRVdRqcI.woff2 +0 -0
- package/dist/dashboard/public/assets/Inter-SemiBold-CtskMddL.woff2 +0 -0
- package/dist/dashboard/public/assets/JetBrainsMono-Bold-D4WEaHbo.woff2 +0 -0
- package/dist/dashboard/public/assets/JetBrainsMono-Medium-3S3k2nMz.woff2 +0 -0
- package/dist/dashboard/public/assets/JetBrainsMono-Regular-BQaDgvhP.woff2 +0 -0
- package/dist/dashboard/public/assets/Tableau10-B-NsZVaP.js +1 -0
- package/dist/dashboard/public/assets/apl-B4CMkyY2.js +1 -0
- package/dist/dashboard/public/assets/arc-C8LPXB-J.js +1 -0
- package/dist/dashboard/public/assets/array-BKyUJesY.js +1 -0
- package/dist/dashboard/public/assets/asciiarmor-Df11BRmG.js +1 -0
- package/dist/dashboard/public/assets/asn1-EdZsLKOL.js +1 -0
- package/dist/dashboard/public/assets/asterisk-B-8jnY81.js +1 -0
- package/dist/dashboard/public/assets/blockDiagram-c4efeb88-RidjsOEy.js +118 -0
- package/dist/dashboard/public/assets/brainfuck-C4LP7Hcl.js +1 -0
- package/dist/dashboard/public/assets/c4Diagram-c83219d4-CAH3hSpm.js +10 -0
- package/dist/dashboard/public/assets/channel-CmDIZRCD.js +1 -0
- package/dist/dashboard/public/assets/classDiagram-beda092f-Bo46Efmw.js +2 -0
- package/dist/dashboard/public/assets/classDiagram-v2-2358418a-Be57sb3z.js +2 -0
- package/dist/dashboard/public/assets/clike-B9uivgTg.js +1 -0
- package/dist/dashboard/public/assets/clojure-BMjYHr_A.js +1 -0
- package/dist/dashboard/public/assets/clone-BiekPeZp.js +1 -0
- package/dist/dashboard/public/assets/cmake-BQqOBYOt.js +1 -0
- package/dist/dashboard/public/assets/cobol-CWcv1MsR.js +1 -0
- package/dist/dashboard/public/assets/coffeescript-S37ZYGWr.js +1 -0
- package/dist/dashboard/public/assets/commonlisp-DBKNyK5s.js +1 -0
- package/dist/dashboard/public/assets/createText-1719965b-YurEYFNx.js +7 -0
- package/dist/dashboard/public/assets/crystal-SjHAIU92.js +1 -0
- package/dist/dashboard/public/assets/css-BnMrqG3P.js +1 -0
- package/dist/dashboard/public/assets/cypher-C_CwsFkJ.js +1 -0
- package/dist/dashboard/public/assets/d-pRatUO7H.js +1 -0
- package/dist/dashboard/public/assets/diff-DbItnlRl.js +1 -0
- package/dist/dashboard/public/assets/dockerfile-BKs6k2Af.js +1 -0
- package/dist/dashboard/public/assets/dtd-DF_7sFjM.js +1 -0
- package/dist/dashboard/public/assets/dylan-DwRh75JA.js +1 -0
- package/dist/dashboard/public/assets/ebnf-CDyGwa7X.js +1 -0
- package/dist/dashboard/public/assets/ecl-Cabwm37j.js +1 -0
- package/dist/dashboard/public/assets/edges-96097737--BjsAXwD.js +4 -0
- package/dist/dashboard/public/assets/eiffel-CnydiIhH.js +1 -0
- package/dist/dashboard/public/assets/elm-vLlmbW-K.js +1 -0
- package/dist/dashboard/public/assets/erDiagram-0228fc6a-BLGuJz36.js +51 -0
- package/dist/dashboard/public/assets/erlang-BNw1qcRV.js +1 -0
- package/dist/dashboard/public/assets/factor-kuTfRLto.js +1 -0
- package/dist/dashboard/public/assets/fcl-Kvtd6kyn.js +1 -0
- package/dist/dashboard/public/assets/flowDb-c6c81e3f-C8vD2iEO.js +10 -0
- package/dist/dashboard/public/assets/flowDiagram-50d868cf-BhxgVmOU.js +4 -0
- package/dist/dashboard/public/assets/flowDiagram-v2-4f6560a1-DvKCh0ha.js +1 -0
- package/dist/dashboard/public/assets/flowchart-elk-definition-6af322e1-CxOZDcEC.js +139 -0
- package/dist/dashboard/public/assets/forth-Ffai-XNe.js +1 -0
- package/dist/dashboard/public/assets/fortran-DYz_wnZ1.js +1 -0
- package/dist/dashboard/public/assets/ganttDiagram-a2739b55-vP9JOLba.js +257 -0
- package/dist/dashboard/public/assets/gas-Bneqetm1.js +1 -0
- package/dist/dashboard/public/assets/gherkin-heZmZLOM.js +1 -0
- package/dist/dashboard/public/assets/gitGraphDiagram-82fe8481-Cw0sm0i1.js +70 -0
- package/dist/dashboard/public/assets/graph-DKTWMcEG.js +1 -0
- package/dist/dashboard/public/assets/groovy-D9Dt4D0W.js +1 -0
- package/dist/dashboard/public/assets/haskell-Cw1EW3IL.js +1 -0
- package/dist/dashboard/public/assets/haxe-H-WmDvRZ.js +1 -0
- package/dist/dashboard/public/assets/http-DBlCnlav.js +1 -0
- package/dist/dashboard/public/assets/idl-BEugSyMb.js +1 -0
- package/dist/dashboard/public/assets/index-1zJPiVa8.js +3 -0
- package/dist/dashboard/public/assets/index-5325376f-DWs4kCT4.js +1 -0
- package/dist/dashboard/public/assets/index-BITJ9OoM.js +1 -0
- package/dist/dashboard/public/assets/index-C38JlXWp.js +1 -0
- package/dist/dashboard/public/assets/index-CCjPelL2.js +2 -0
- package/dist/dashboard/public/assets/index-CD9WQNmE.js +1 -0
- package/dist/dashboard/public/assets/index-CU7K5Zcb.js +1 -0
- package/dist/dashboard/public/assets/index-CXQVOhJV.js +1 -0
- package/dist/dashboard/public/assets/index-CXcaRrZ2.js +1 -0
- package/dist/dashboard/public/assets/index-ChLAL6g5.css +1 -0
- package/dist/dashboard/public/assets/index-D0o1vVOe.js +7 -0
- package/dist/dashboard/public/assets/index-DCsxqRvu.js +1 -0
- package/dist/dashboard/public/assets/index-DL3iiiRz.js +1 -0
- package/dist/dashboard/public/assets/index-DMv2_K2V.js +1 -0
- package/dist/dashboard/public/assets/index-DX7EEJ21.js +1 -0
- package/dist/dashboard/public/assets/index-Dey_HIH7.js +1 -0
- package/dist/dashboard/public/assets/index-DzDTRLhf.js +1 -0
- package/dist/dashboard/public/assets/index-OePkEWBg.js +1 -0
- package/dist/dashboard/public/assets/index-_d82jdTP.js +1 -0
- package/dist/dashboard/public/assets/index-yCKz4OXA.js +319 -0
- package/dist/dashboard/public/assets/infoDiagram-8eee0895-BRq08fZf.js +7 -0
- package/dist/dashboard/public/assets/init-Gi6I4Gst.js +1 -0
- package/dist/dashboard/public/assets/javascript-iXu5QeM3.js +1 -0
- package/dist/dashboard/public/assets/journeyDiagram-c64418c1-Cf8D2OC8.js +139 -0
- package/dist/dashboard/public/assets/julia-DuME0IfC.js +1 -0
- package/dist/dashboard/public/assets/katex-XbL3y5x-.js +261 -0
- package/dist/dashboard/public/assets/layout-CVdidYA-.js +1 -0
- package/dist/dashboard/public/assets/line-BdckgA27.js +1 -0
- package/dist/dashboard/public/assets/linear-C9Nh3JLa.js +1 -0
- package/dist/dashboard/public/assets/livescript-BwQOo05w.js +1 -0
- package/dist/dashboard/public/assets/lua-BgMRiT3U.js +1 -0
- package/dist/dashboard/public/assets/mathematica-DTrFuWx2.js +1 -0
- package/dist/dashboard/public/assets/mbox-CNhZ1qSd.js +1 -0
- package/dist/dashboard/public/assets/mindmap-definition-8da855dc-CK-y1AmO.js +415 -0
- package/dist/dashboard/public/assets/mirc-CjQqDB4T.js +1 -0
- package/dist/dashboard/public/assets/mllike-CXdrOF99.js +1 -0
- package/dist/dashboard/public/assets/modelica-Dc1JOy9r.js +1 -0
- package/dist/dashboard/public/assets/mscgen-BA5vi2Kp.js +1 -0
- package/dist/dashboard/public/assets/mumps-BT43cFF4.js +1 -0
- package/dist/dashboard/public/assets/nginx-DdIZxoE0.js +1 -0
- package/dist/dashboard/public/assets/nsis-LdVXkNf5.js +1 -0
- package/dist/dashboard/public/assets/ntriples-BfvgReVJ.js +1 -0
- package/dist/dashboard/public/assets/octave-Ck1zUtKM.js +1 -0
- package/dist/dashboard/public/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/dashboard/public/assets/oz-BzwKVEFT.js +1 -0
- package/dist/dashboard/public/assets/pascal--L3eBynH.js +1 -0
- package/dist/dashboard/public/assets/path-CbwjOpE9.js +1 -0
- package/dist/dashboard/public/assets/perl-CdXCOZ3F.js +1 -0
- package/dist/dashboard/public/assets/pieDiagram-a8764435-T8V0JN2R.js +35 -0
- package/dist/dashboard/public/assets/pig-CevX1Tat.js +1 -0
- package/dist/dashboard/public/assets/powershell-CFHJl5sT.js +1 -0
- package/dist/dashboard/public/assets/properties-C78fOPTZ.js +1 -0
- package/dist/dashboard/public/assets/protobuf-ChK-085T.js +1 -0
- package/dist/dashboard/public/assets/pug-DeIclll2.js +1 -0
- package/dist/dashboard/public/assets/puppet-DMA9R1ak.js +1 -0
- package/dist/dashboard/public/assets/python-BuPzkPfP.js +1 -0
- package/dist/dashboard/public/assets/q-pXgVlZs6.js +1 -0
- package/dist/dashboard/public/assets/quadrantDiagram-1e28029f-CmtVsb5L.js +7 -0
- package/dist/dashboard/public/assets/r-B6wPVr8A.js +1 -0
- package/dist/dashboard/public/assets/requirementDiagram-08caed73-BUcTnzDl.js +52 -0
- package/dist/dashboard/public/assets/rpm-CTu-6PCP.js +1 -0
- package/dist/dashboard/public/assets/ruby-B2Rjki9n.js +1 -0
- package/dist/dashboard/public/assets/sankeyDiagram-a04cb91d-FswuxQ9M.js +8 -0
- package/dist/dashboard/public/assets/sas-B4kiWyti.js +1 -0
- package/dist/dashboard/public/assets/scheme-C41bIUwD.js +1 -0
- package/dist/dashboard/public/assets/sequenceDiagram-c5b8d532-BJQ15rhX.js +122 -0
- package/dist/dashboard/public/assets/shell-CjFT_Tl9.js +1 -0
- package/dist/dashboard/public/assets/sieve-C3Gn_uJK.js +1 -0
- package/dist/dashboard/public/assets/simple-mode-GW_nhZxv.js +1 -0
- package/dist/dashboard/public/assets/smalltalk-CnHTOXQT.js +1 -0
- package/dist/dashboard/public/assets/solr-DehyRSwq.js +1 -0
- package/dist/dashboard/public/assets/sparql-DkYu6x3z.js +1 -0
- package/dist/dashboard/public/assets/spreadsheet-BCZA_wO0.js +1 -0
- package/dist/dashboard/public/assets/sql-D0XecflT.js +1 -0
- package/dist/dashboard/public/assets/stateDiagram-1ecb1508-BfyE0DYv.js +1 -0
- package/dist/dashboard/public/assets/stateDiagram-v2-c2b004d7-pcGOYyiW.js +1 -0
- package/dist/dashboard/public/assets/stex-C3f8Ysf7.js +1 -0
- package/dist/dashboard/public/assets/styles-b4e223ce--lUviH7V.js +160 -0
- package/dist/dashboard/public/assets/styles-ca3715f6-BXbrD1Av.js +207 -0
- package/dist/dashboard/public/assets/styles-d45a18b0-GyiMrLKu.js +116 -0
- package/dist/dashboard/public/assets/stylus-B533Al4x.js +1 -0
- package/dist/dashboard/public/assets/svgDrawCommon-b86b1483-DI4Z1GTS.js +1 -0
- package/dist/dashboard/public/assets/swift-BzpIVaGY.js +1 -0
- package/dist/dashboard/public/assets/tcl-DVfN8rqt.js +1 -0
- package/dist/dashboard/public/assets/textile-CnDTJFAw.js +1 -0
- package/dist/dashboard/public/assets/tiddlywiki-DO-Gjzrf.js +1 -0
- package/dist/dashboard/public/assets/tiki-DGYXhP31.js +1 -0
- package/dist/dashboard/public/assets/timeline-definition-faaaa080-B1IgohU4.js +61 -0
- package/dist/dashboard/public/assets/toml-Bm5Em-hy.js +1 -0
- package/dist/dashboard/public/assets/troff-wAsdV37c.js +1 -0
- package/dist/dashboard/public/assets/ttcn-CfJYG6tj.js +1 -0
- package/dist/dashboard/public/assets/ttcn-cfg-B9xdYoR4.js +1 -0
- package/dist/dashboard/public/assets/turtle-B1tBg_DP.js +1 -0
- package/dist/dashboard/public/assets/vb-CmGdzxic.js +1 -0
- package/dist/dashboard/public/assets/vbscript-BuJXcnF6.js +1 -0
- package/dist/dashboard/public/assets/velocity-D8B20fx6.js +1 -0
- package/dist/dashboard/public/assets/verilog-C6RDOZhf.js +1 -0
- package/dist/dashboard/public/assets/vhdl-lSbBsy5d.js +1 -0
- package/dist/dashboard/public/assets/webidl-ZXfAyPTL.js +1 -0
- package/dist/dashboard/public/assets/xquery-DzFWVndE.js +1 -0
- package/dist/dashboard/public/assets/xychartDiagram-f5964ef8-B5oRDe_I.js +7 -0
- package/dist/dashboard/public/assets/yacas-BJ4BC0dw.js +1 -0
- package/dist/dashboard/public/assets/z80-Hz9HOZM7.js +1 -0
- package/dist/dashboard/public/claude-icon-dark.svg +1 -0
- package/dist/dashboard/public/claude-icon.svg +1 -0
- package/dist/dashboard/public/index.html +16 -0
- package/dist/dashboard/settings-manager.d.ts +47 -0
- package/dist/dashboard/settings-manager.d.ts.map +1 -0
- package/dist/dashboard/settings-manager.js +180 -0
- package/dist/dashboard/settings-manager.js.map +1 -0
- package/dist/dashboard/utils.d.ts +31 -0
- package/dist/dashboard/utils.d.ts.map +1 -0
- package/dist/dashboard/utils.js +102 -0
- package/dist/dashboard/utils.js.map +1 -0
- package/dist/dashboard/watcher.d.ts +32 -0
- package/dist/dashboard/watcher.d.ts.map +1 -0
- package/dist/dashboard/watcher.js +173 -0
- package/dist/dashboard/watcher.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +380 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown/templates/design-template.md +96 -0
- package/dist/markdown/templates/product-template.md +51 -0
- package/dist/markdown/templates/requirements-template.md +50 -0
- package/dist/markdown/templates/structure-template.md +145 -0
- package/dist/markdown/templates/tasks-template.md +139 -0
- package/dist/markdown/templates/tech-template.md +99 -0
- package/dist/prompts/create-spec.d.ts +3 -0
- package/dist/prompts/create-spec.d.ts.map +1 -0
- package/dist/prompts/create-spec.js +93 -0
- package/dist/prompts/create-spec.js.map +1 -0
- package/dist/prompts/create-steering-doc.d.ts +3 -0
- package/dist/prompts/create-steering-doc.d.ts.map +1 -0
- package/dist/prompts/create-steering-doc.js +73 -0
- package/dist/prompts/create-steering-doc.js.map +1 -0
- package/dist/prompts/implement-task.d.ts +3 -0
- package/dist/prompts/implement-task.d.ts.map +1 -0
- package/dist/prompts/implement-task.js +173 -0
- package/dist/prompts/implement-task.js.map +1 -0
- package/dist/prompts/index.d.ts +15 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +49 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/inject-spec-workflow-guide.d.ts +3 -0
- package/dist/prompts/inject-spec-workflow-guide.d.ts.map +1 -0
- package/dist/prompts/inject-spec-workflow-guide.js +47 -0
- package/dist/prompts/inject-spec-workflow-guide.js.map +1 -0
- package/dist/prompts/inject-steering-guide.d.ts +3 -0
- package/dist/prompts/inject-steering-guide.d.ts.map +1 -0
- package/dist/prompts/inject-steering-guide.js +51 -0
- package/dist/prompts/inject-steering-guide.js.map +1 -0
- package/dist/prompts/refresh-tasks.d.ts +3 -0
- package/dist/prompts/refresh-tasks.d.ts.map +1 -0
- package/dist/prompts/refresh-tasks.js +224 -0
- package/dist/prompts/refresh-tasks.js.map +1 -0
- package/dist/prompts/spec-status.d.ts +3 -0
- package/dist/prompts/spec-status.d.ts.map +1 -0
- package/dist/prompts/spec-status.js +75 -0
- package/dist/prompts/spec-status.js.map +1 -0
- package/dist/prompts/types.d.ts +13 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +2 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +175 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/__tests__/projectPath.test.d.ts +2 -0
- package/dist/tools/__tests__/projectPath.test.d.ts.map +1 -0
- package/dist/tools/__tests__/projectPath.test.js +187 -0
- package/dist/tools/__tests__/projectPath.test.js.map +1 -0
- package/dist/tools/approvals.d.ts +14 -0
- package/dist/tools/approvals.d.ts.map +1 -0
- package/dist/tools/approvals.js +490 -0
- package/dist/tools/approvals.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +52 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/log-implementation.d.ts +5 -0
- package/dist/tools/log-implementation.d.ts.map +1 -0
- package/dist/tools/log-implementation.js +397 -0
- package/dist/tools/log-implementation.js.map +1 -0
- package/dist/tools/spec-status.d.ts +5 -0
- package/dist/tools/spec-status.d.ts.map +1 -0
- package/dist/tools/spec-status.js +178 -0
- package/dist/tools/spec-status.js.map +1 -0
- package/dist/tools/spec-workflow-guide.d.ts +5 -0
- package/dist/tools/spec-workflow-guide.d.ts.map +1 -0
- package/dist/tools/spec-workflow-guide.js +291 -0
- package/dist/tools/spec-workflow-guide.js.map +1 -0
- package/dist/tools/steering-guide.d.ts +5 -0
- package/dist/tools/steering-guide.d.ts.map +1 -0
- package/dist/tools/steering-guide.js +192 -0
- package/dist/tools/steering-guide.js.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +105 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Validator Module
|
|
3
|
+
* Validates tasks.md format compliance before approval
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validate tasks.md content against required format
|
|
7
|
+
* @param content The markdown content to validate
|
|
8
|
+
* @returns ValidationResult with errors, warnings, and summary
|
|
9
|
+
*/
|
|
10
|
+
export function validateTasksMarkdown(content) {
|
|
11
|
+
const lines = content.split('\n');
|
|
12
|
+
const errors = [];
|
|
13
|
+
const warnings = [];
|
|
14
|
+
let taskCount = 0;
|
|
15
|
+
let validTaskCount = 0;
|
|
16
|
+
// Find all checkbox lines and their ranges (including malformed ones with asterisks)
|
|
17
|
+
const checkboxIndices = [];
|
|
18
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19
|
+
if (lines[i].match(/^\s*[-*]\s*\[/)) {
|
|
20
|
+
checkboxIndices.push(i);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Process each checkbox task
|
|
24
|
+
for (let idx = 0; idx < checkboxIndices.length; idx++) {
|
|
25
|
+
const lineIndex = checkboxIndices[idx];
|
|
26
|
+
const endLine = idx < checkboxIndices.length - 1 ? checkboxIndices[idx + 1] : lines.length;
|
|
27
|
+
const line = lines[lineIndex];
|
|
28
|
+
const lineNum = lineIndex + 1; // 1-based for user-friendly messages
|
|
29
|
+
taskCount++;
|
|
30
|
+
let taskValid = true;
|
|
31
|
+
let taskId;
|
|
32
|
+
// 1. Validate checkbox format: must be "- [ ]", "- [-]", or "- [x]"
|
|
33
|
+
const checkboxMatch = line.match(/^\s*-\s+\[([ x\-])\]\s+(.+)/);
|
|
34
|
+
if (!checkboxMatch) {
|
|
35
|
+
// Check for common malformed patterns
|
|
36
|
+
const malformedPatterns = [
|
|
37
|
+
{ pattern: /^\s*-\s*\[\]\s/, message: 'Empty checkbox brackets', suggestion: 'Use "- [ ]" with a space inside brackets' },
|
|
38
|
+
{ pattern: /^\s*-\s*\[([^x \-])\]/, message: 'Invalid checkbox character', suggestion: 'Use space for pending, x for completed, - for in-progress' },
|
|
39
|
+
{ pattern: /^\s*-\[\s*[x \-]?\s*\]/, message: 'Missing space after hyphen', suggestion: 'Use "- [ ]" with space between - and [' },
|
|
40
|
+
{ pattern: /^\s*\*\s+\[/, message: 'Wrong bullet character', suggestion: 'Use hyphen (-) instead of asterisk (*)' },
|
|
41
|
+
];
|
|
42
|
+
let foundMalformed = false;
|
|
43
|
+
for (const { pattern, message, suggestion } of malformedPatterns) {
|
|
44
|
+
if (line.match(pattern)) {
|
|
45
|
+
errors.push({
|
|
46
|
+
line: lineNum,
|
|
47
|
+
field: 'checkbox',
|
|
48
|
+
message,
|
|
49
|
+
suggestion,
|
|
50
|
+
severity: 'error'
|
|
51
|
+
});
|
|
52
|
+
foundMalformed = true;
|
|
53
|
+
taskValid = false;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!foundMalformed) {
|
|
58
|
+
errors.push({
|
|
59
|
+
line: lineNum,
|
|
60
|
+
field: 'checkbox',
|
|
61
|
+
message: 'Invalid checkbox format',
|
|
62
|
+
suggestion: 'Expected format: "- [ ] 1. Task description"',
|
|
63
|
+
severity: 'error'
|
|
64
|
+
});
|
|
65
|
+
taskValid = false;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const statusChar = checkboxMatch[1];
|
|
70
|
+
const taskText = checkboxMatch[2];
|
|
71
|
+
// 2. Validate task ID: must have numeric ID like "1.", "1.1", "2.3"
|
|
72
|
+
const taskIdMatch = taskText.match(/^(\d+(?:\.\d+)*)\s*\.?\s+(.+)/);
|
|
73
|
+
if (!taskIdMatch) {
|
|
74
|
+
errors.push({
|
|
75
|
+
line: lineNum,
|
|
76
|
+
field: 'taskId',
|
|
77
|
+
message: 'Missing task ID number',
|
|
78
|
+
suggestion: 'Add numeric ID like "1." or "1.1" after checkbox',
|
|
79
|
+
severity: 'error'
|
|
80
|
+
});
|
|
81
|
+
taskValid = false;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
taskId = taskIdMatch[1];
|
|
85
|
+
}
|
|
86
|
+
// 3. Validate metadata in following lines
|
|
87
|
+
let hasRequirements = false;
|
|
88
|
+
let hasLeverage = false;
|
|
89
|
+
let hasPrompt = false;
|
|
90
|
+
let hasFiles = false;
|
|
91
|
+
let promptHasClosingUnderscore = false;
|
|
92
|
+
let promptSections = [];
|
|
93
|
+
for (let lineIdx = lineIndex + 1; lineIdx < endLine; lineIdx++) {
|
|
94
|
+
const contentLine = lines[lineIdx];
|
|
95
|
+
const trimmedLine = contentLine.trim();
|
|
96
|
+
if (!trimmedLine)
|
|
97
|
+
continue;
|
|
98
|
+
// Check for _Requirements:_ format
|
|
99
|
+
if (trimmedLine.includes('Requirements:')) {
|
|
100
|
+
hasRequirements = true;
|
|
101
|
+
// Check for proper underscore delimiters
|
|
102
|
+
if (!trimmedLine.match(/_Requirements:\s*[^_]+_/)) {
|
|
103
|
+
if (trimmedLine.match(/Requirements:\s*\S/) && !trimmedLine.includes('_Requirements:')) {
|
|
104
|
+
warnings.push({
|
|
105
|
+
line: lineIdx + 1,
|
|
106
|
+
taskId,
|
|
107
|
+
field: 'requirements',
|
|
108
|
+
message: 'Requirements field missing underscore delimiters',
|
|
109
|
+
suggestion: 'Use "_Requirements: ..._" format for proper parsing',
|
|
110
|
+
severity: 'warning'
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Check for _Leverage:_ format
|
|
116
|
+
if (trimmedLine.includes('Leverage:')) {
|
|
117
|
+
hasLeverage = true;
|
|
118
|
+
// Check for proper underscore delimiters
|
|
119
|
+
if (!trimmedLine.match(/_Leverage:\s*[^_]+_/)) {
|
|
120
|
+
if (trimmedLine.match(/Leverage:\s*\S/) && !trimmedLine.includes('_Leverage:')) {
|
|
121
|
+
warnings.push({
|
|
122
|
+
line: lineIdx + 1,
|
|
123
|
+
taskId,
|
|
124
|
+
field: 'leverage',
|
|
125
|
+
message: 'Leverage field missing underscore delimiters',
|
|
126
|
+
suggestion: 'Use "_Leverage: ..._" format for proper parsing',
|
|
127
|
+
severity: 'warning'
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Check for Files: field
|
|
133
|
+
if (trimmedLine.match(/Files?:/i)) {
|
|
134
|
+
hasFiles = true;
|
|
135
|
+
}
|
|
136
|
+
// Check for _Prompt:_ format
|
|
137
|
+
if (trimmedLine.includes('_Prompt:')) {
|
|
138
|
+
hasPrompt = true;
|
|
139
|
+
// Check for closing underscore
|
|
140
|
+
if (trimmedLine.match(/_Prompt:\s*.+_$/)) {
|
|
141
|
+
promptHasClosingUnderscore = true;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Check if prompt continues on multiple lines - look for closing underscore
|
|
145
|
+
let foundClosing = false;
|
|
146
|
+
for (let j = lineIdx; j < endLine; j++) {
|
|
147
|
+
if (lines[j].trim().endsWith('_') && !lines[j].trim().match(/^_[A-Z]/)) {
|
|
148
|
+
foundClosing = true;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
promptHasClosingUnderscore = foundClosing;
|
|
153
|
+
}
|
|
154
|
+
// Extract prompt content and check structure
|
|
155
|
+
const promptContent = trimmedLine.replace(/_Prompt:\s*/, '').replace(/_$/, '');
|
|
156
|
+
// Check for required prompt sections: Role, Task, Restrictions, Success
|
|
157
|
+
const requiredSections = ['Role', 'Task', 'Restrictions', 'Success'];
|
|
158
|
+
for (const section of requiredSections) {
|
|
159
|
+
if (promptContent.toLowerCase().includes(section.toLowerCase() + ':')) {
|
|
160
|
+
promptSections.push(section);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Validate prompt requirements
|
|
166
|
+
if (hasPrompt) {
|
|
167
|
+
if (!promptHasClosingUnderscore) {
|
|
168
|
+
warnings.push({
|
|
169
|
+
line: lineNum,
|
|
170
|
+
taskId,
|
|
171
|
+
field: 'prompt',
|
|
172
|
+
message: 'Prompt field may be missing closing underscore',
|
|
173
|
+
suggestion: 'Ensure _Prompt: ..._ ends with underscore',
|
|
174
|
+
severity: 'warning'
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// Check for missing prompt sections
|
|
178
|
+
const requiredSections = ['Role', 'Task', 'Restrictions', 'Success'];
|
|
179
|
+
const missingSections = requiredSections.filter(s => !promptSections.includes(s));
|
|
180
|
+
if (missingSections.length > 0) {
|
|
181
|
+
warnings.push({
|
|
182
|
+
line: lineNum,
|
|
183
|
+
taskId,
|
|
184
|
+
field: 'prompt_structure',
|
|
185
|
+
message: `Prompt missing sections: ${missingSections.join(', ')}`,
|
|
186
|
+
suggestion: 'Format: Role: ... | Task: ... | Restrictions: ... | Success: ...',
|
|
187
|
+
severity: 'warning'
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Track if task is valid (only errors affect validity, not warnings)
|
|
192
|
+
if (taskValid) {
|
|
193
|
+
validTaskCount++;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
valid: errors.length === 0,
|
|
198
|
+
errors,
|
|
199
|
+
warnings,
|
|
200
|
+
summary: {
|
|
201
|
+
totalTasks: taskCount,
|
|
202
|
+
validTasks: validTaskCount,
|
|
203
|
+
invalidTasks: taskCount - validTaskCount
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Format validation errors for display
|
|
209
|
+
* @param result The validation result
|
|
210
|
+
* @returns Formatted string array of errors and warnings
|
|
211
|
+
*/
|
|
212
|
+
export function formatValidationErrors(result) {
|
|
213
|
+
const messages = [];
|
|
214
|
+
if (result.errors.length > 0) {
|
|
215
|
+
messages.push(`Found ${result.errors.length} error(s):`);
|
|
216
|
+
for (const error of result.errors) {
|
|
217
|
+
const taskInfo = error.taskId ? ` (Task ${error.taskId})` : '';
|
|
218
|
+
messages.push(` Line ${error.line}${taskInfo}: ${error.message}`);
|
|
219
|
+
if (error.suggestion) {
|
|
220
|
+
messages.push(` Suggestion: ${error.suggestion}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (result.warnings.length > 0) {
|
|
225
|
+
messages.push(`Found ${result.warnings.length} warning(s):`);
|
|
226
|
+
for (const warning of result.warnings) {
|
|
227
|
+
const taskInfo = warning.taskId ? ` (Task ${warning.taskId})` : '';
|
|
228
|
+
messages.push(` Line ${warning.line}${taskInfo}: ${warning.message}`);
|
|
229
|
+
if (warning.suggestion) {
|
|
230
|
+
messages.push(` Suggestion: ${warning.suggestion}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return messages;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=task-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-validator.js","sourceRoot":"","sources":["../../src/core/task-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class WorkspaceInitializer {
|
|
2
|
+
private projectPath;
|
|
3
|
+
private version;
|
|
4
|
+
constructor(projectPath: string, version: string);
|
|
5
|
+
initializeWorkspace(): Promise<void>;
|
|
6
|
+
private initializeDirectories;
|
|
7
|
+
private initializeTemplates;
|
|
8
|
+
private copyTemplate;
|
|
9
|
+
private createUserTemplatesReadme;
|
|
10
|
+
/**
|
|
11
|
+
* Migrate implementation logs from JSON to Markdown format
|
|
12
|
+
* Runs on server startup to handle automatic migration for existing specs
|
|
13
|
+
*/
|
|
14
|
+
private migrateImplementationLogs;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=workspace-initializer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-initializer.d.ts","sourceRoot":"","sources":["../../src/core/workspace-initializer.ts"],"names":[],"mappings":"AASA,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;gBAEZ,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAK1C,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;YAc5B,qBAAqB;YAkBrB,mBAAmB;YAiBnB,YAAY;YAkBZ,yBAAyB;IA8EvC;;;OAGG;YACW,yBAAyB;CAgBxC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { PathUtils } from './path-utils.js';
|
|
5
|
+
import { ImplementationLogMigrator } from './implementation-log-migrator.js';
|
|
6
|
+
import { getGlobalDir } from './global-dir.js';
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
export class WorkspaceInitializer {
|
|
9
|
+
projectPath;
|
|
10
|
+
version;
|
|
11
|
+
constructor(projectPath, version) {
|
|
12
|
+
this.projectPath = projectPath;
|
|
13
|
+
this.version = version;
|
|
14
|
+
}
|
|
15
|
+
async initializeWorkspace() {
|
|
16
|
+
// Create all necessary directories
|
|
17
|
+
await this.initializeDirectories();
|
|
18
|
+
// Copy template files
|
|
19
|
+
await this.initializeTemplates();
|
|
20
|
+
// Create user templates README
|
|
21
|
+
await this.createUserTemplatesReadme();
|
|
22
|
+
// Migrate implementation logs from JSON to Markdown format
|
|
23
|
+
await this.migrateImplementationLogs();
|
|
24
|
+
}
|
|
25
|
+
async initializeDirectories() {
|
|
26
|
+
const workflowRoot = PathUtils.getWorkflowRoot(this.projectPath);
|
|
27
|
+
const directories = [
|
|
28
|
+
'approvals',
|
|
29
|
+
'archive',
|
|
30
|
+
'specs',
|
|
31
|
+
'steering',
|
|
32
|
+
'templates',
|
|
33
|
+
'user-templates'
|
|
34
|
+
];
|
|
35
|
+
for (const dir of directories) {
|
|
36
|
+
const dirPath = join(workflowRoot, dir);
|
|
37
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async initializeTemplates() {
|
|
41
|
+
const templatesDir = join(PathUtils.getWorkflowRoot(this.projectPath), 'templates');
|
|
42
|
+
const templates = [
|
|
43
|
+
'requirements-template',
|
|
44
|
+
'design-template',
|
|
45
|
+
'tasks-template',
|
|
46
|
+
'product-template',
|
|
47
|
+
'tech-template',
|
|
48
|
+
'structure-template'
|
|
49
|
+
];
|
|
50
|
+
for (const template of templates) {
|
|
51
|
+
await this.copyTemplate(template, templatesDir);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async copyTemplate(templateName, targetDir) {
|
|
55
|
+
// Use simple filename without version
|
|
56
|
+
const targetFileName = `${templateName}.md`;
|
|
57
|
+
const targetPath = join(targetDir, targetFileName);
|
|
58
|
+
const sourcePath = join(__dirname, '..', 'markdown', 'templates', `${templateName}.md`);
|
|
59
|
+
try {
|
|
60
|
+
const content = await fs.readFile(sourcePath, 'utf-8');
|
|
61
|
+
// Always overwrite to ensure latest template version is used
|
|
62
|
+
await fs.writeFile(targetPath, content, 'utf-8');
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
66
|
+
console.error(`Failed to copy template ${templateName}: ${errorMessage}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async createUserTemplatesReadme() {
|
|
70
|
+
const readmePath = join(PathUtils.getWorkflowRoot(this.projectPath), 'user-templates', 'README.md');
|
|
71
|
+
const readmeContent = `# User Templates
|
|
72
|
+
|
|
73
|
+
This directory allows you to create custom templates that override the default Spec Workflow templates.
|
|
74
|
+
|
|
75
|
+
## How to Use Custom Templates
|
|
76
|
+
|
|
77
|
+
1. **Create your custom template file** in this directory with the exact same name as the default template you want to override:
|
|
78
|
+
- \`requirements-template.md\` - Override requirements document template
|
|
79
|
+
- \`design-template.md\` - Override design document template
|
|
80
|
+
- \`tasks-template.md\` - Override tasks document template
|
|
81
|
+
- \`product-template.md\` - Override product steering template
|
|
82
|
+
- \`tech-template.md\` - Override tech steering template
|
|
83
|
+
- \`structure-template.md\` - Override structure steering template
|
|
84
|
+
|
|
85
|
+
2. **Template Loading Priority**:
|
|
86
|
+
- The system first checks this \`user-templates/\` directory
|
|
87
|
+
- If a matching template is found here, it will be used
|
|
88
|
+
- Otherwise, the default template from \`templates/\` will be used
|
|
89
|
+
|
|
90
|
+
## Example Custom Template
|
|
91
|
+
|
|
92
|
+
To create a custom requirements template:
|
|
93
|
+
|
|
94
|
+
1. Create a file named \`requirements-template.md\` in this directory
|
|
95
|
+
2. Add your custom structure, for example:
|
|
96
|
+
|
|
97
|
+
\`\`\`markdown
|
|
98
|
+
# Requirements Document
|
|
99
|
+
|
|
100
|
+
## Executive Summary
|
|
101
|
+
[Your custom section]
|
|
102
|
+
|
|
103
|
+
## Business Requirements
|
|
104
|
+
[Your custom structure]
|
|
105
|
+
|
|
106
|
+
## Technical Requirements
|
|
107
|
+
[Your custom fields]
|
|
108
|
+
|
|
109
|
+
## Custom Sections
|
|
110
|
+
[Add any sections specific to your workflow]
|
|
111
|
+
\`\`\`
|
|
112
|
+
|
|
113
|
+
## Template Variables
|
|
114
|
+
|
|
115
|
+
Templates can include placeholders that will be replaced when documents are created:
|
|
116
|
+
- \`{{projectName}}\` - The name of your project
|
|
117
|
+
- \`{{featureName}}\` - The name of the feature being specified
|
|
118
|
+
- \`{{date}}\` - The current date
|
|
119
|
+
- \`{{author}}\` - The document author
|
|
120
|
+
|
|
121
|
+
## Best Practices
|
|
122
|
+
|
|
123
|
+
1. **Start from defaults**: Copy a default template from \`../templates/\` as a starting point
|
|
124
|
+
2. **Keep structure consistent**: Maintain similar section headers for tool compatibility
|
|
125
|
+
3. **Document changes**: Add comments explaining why sections were added/modified
|
|
126
|
+
4. **Version control**: Track your custom templates in version control
|
|
127
|
+
5. **Test thoroughly**: Ensure custom templates work with the spec workflow tools
|
|
128
|
+
|
|
129
|
+
## Notes
|
|
130
|
+
|
|
131
|
+
- Custom templates are project-specific and not included in the package distribution
|
|
132
|
+
- The \`templates/\` directory contains the default templates which are updated with each version
|
|
133
|
+
- Your custom templates in this directory are preserved during updates
|
|
134
|
+
- If a custom template has errors, the system will fall back to the default template
|
|
135
|
+
`;
|
|
136
|
+
try {
|
|
137
|
+
// Only create if it doesn't exist to avoid overwriting user's README
|
|
138
|
+
await fs.access(readmePath);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// File doesn't exist, create it
|
|
142
|
+
await fs.writeFile(readmePath, readmeContent, 'utf-8');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Migrate implementation logs from JSON to Markdown format
|
|
147
|
+
* Runs on server startup to handle automatic migration for existing specs
|
|
148
|
+
*/
|
|
149
|
+
async migrateImplementationLogs() {
|
|
150
|
+
try {
|
|
151
|
+
const userDataDir = getGlobalDir();
|
|
152
|
+
const specsDir = join(PathUtils.getWorkflowRoot(this.projectPath), 'specs');
|
|
153
|
+
// Create user data directory if it doesn't exist
|
|
154
|
+
await fs.mkdir(userDataDir, { recursive: true });
|
|
155
|
+
const migrator = new ImplementationLogMigrator(userDataDir);
|
|
156
|
+
await migrator.migrateAllSpecs(specsDir);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
160
|
+
console.error(`Implementation log migration failed: ${errorMessage}`);
|
|
161
|
+
// Don't throw - migration failure shouldn't break server startup
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=workspace-initializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-initializer.js","sourceRoot":"","sources":["../../src/core/workspace-initializer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-storage-path-resolution.test.d.ts","sourceRoot":"","sources":["../../../src/dashboard/__tests__/approval-storage-path-resolution.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { ApprovalStorage } from '../approval-storage.js';
|
|
6
|
+
describe('ApprovalStorage path resolution', () => {
|
|
7
|
+
let tempDir;
|
|
8
|
+
let workflowRootPath;
|
|
9
|
+
let workspacePath;
|
|
10
|
+
let storage;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
tempDir = join(tmpdir(), `spec-workflow-approvals-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`);
|
|
13
|
+
workflowRootPath = join(tempDir, 'repo-main');
|
|
14
|
+
workspacePath = join(tempDir, 'repo-feature-worktree');
|
|
15
|
+
await fs.mkdir(workflowRootPath, { recursive: true });
|
|
16
|
+
await fs.mkdir(workspacePath, { recursive: true });
|
|
17
|
+
storage = new ApprovalStorage(workflowRootPath, {
|
|
18
|
+
originalPath: workflowRootPath,
|
|
19
|
+
fileResolutionPath: workspacePath
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
afterEach(async () => {
|
|
23
|
+
await storage.stop();
|
|
24
|
+
try {
|
|
25
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Ignore cleanup errors
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
it('prefers workspace file for snapshots when both workspace and workflow files exist', async () => {
|
|
32
|
+
const relativePath = 'src/feature.ts';
|
|
33
|
+
const workspaceFile = join(workspacePath, relativePath);
|
|
34
|
+
const workflowFile = join(workflowRootPath, relativePath);
|
|
35
|
+
await fs.mkdir(join(workspacePath, 'src'), { recursive: true });
|
|
36
|
+
await fs.mkdir(join(workflowRootPath, 'src'), { recursive: true });
|
|
37
|
+
await fs.writeFile(workspaceFile, 'workspace-version', 'utf-8');
|
|
38
|
+
await fs.writeFile(workflowFile, 'workflow-version', 'utf-8');
|
|
39
|
+
const approvalId = await storage.createApproval('Review feature', relativePath, 'spec', 'test-spec');
|
|
40
|
+
const snapshots = await storage.getSnapshots(approvalId);
|
|
41
|
+
expect(snapshots).toHaveLength(1);
|
|
42
|
+
expect(snapshots[0].content).toBe('workspace-version');
|
|
43
|
+
});
|
|
44
|
+
it('falls back to workflow root when file only exists there', async () => {
|
|
45
|
+
const relativePath = '.spec-workflow/specs/test-spec/requirements.md';
|
|
46
|
+
const workflowFile = join(workflowRootPath, relativePath);
|
|
47
|
+
await fs.mkdir(join(workflowRootPath, '.spec-workflow', 'specs', 'test-spec'), { recursive: true });
|
|
48
|
+
await fs.writeFile(workflowFile, '# Requirements from shared root', 'utf-8');
|
|
49
|
+
const approvalId = await storage.createApproval('Review requirements', relativePath, 'spec', 'test-spec');
|
|
50
|
+
const content = await storage.getCurrentFileContent(approvalId);
|
|
51
|
+
expect(content).toBe('# Requirements from shared root');
|
|
52
|
+
});
|
|
53
|
+
it('writes revisions to workspace file when it exists there', async () => {
|
|
54
|
+
const relativePath = 'src/revision-target.ts';
|
|
55
|
+
const workspaceFile = join(workspacePath, relativePath);
|
|
56
|
+
const workflowFile = join(workflowRootPath, relativePath);
|
|
57
|
+
await fs.mkdir(join(workspacePath, 'src'), { recursive: true });
|
|
58
|
+
await fs.mkdir(join(workflowRootPath, 'src'), { recursive: true });
|
|
59
|
+
await fs.writeFile(workspaceFile, 'workspace-original', 'utf-8');
|
|
60
|
+
await fs.writeFile(workflowFile, 'workflow-original', 'utf-8');
|
|
61
|
+
const approvalId = await storage.createApproval('Review revision target', relativePath, 'spec', 'test-spec');
|
|
62
|
+
await storage.createRevision(approvalId, 'workspace-updated', 'needs update');
|
|
63
|
+
const workspaceContent = await fs.readFile(workspaceFile, 'utf-8');
|
|
64
|
+
const workflowContent = await fs.readFile(workflowFile, 'utf-8');
|
|
65
|
+
expect(workspaceContent).toBe('workspace-updated');
|
|
66
|
+
expect(workflowContent).toBe('workflow-original');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=approval-storage-path-resolution.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-storage-path-resolution.test.js","sourceRoot":"","sources":["../../../src/dashboard/__tests__/approval-storage-path-resolution.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-server-approvals-content.test.d.ts","sourceRoot":"","sources":["../../../src/dashboard/__tests__/multi-server-approvals-content.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import net from 'net';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
|
+
import { MultiProjectDashboardServer } from '../multi-server.js';
|
|
7
|
+
import { ApprovalStorage } from '../approval-storage.js';
|
|
8
|
+
import { ProjectRegistry, generateProjectId } from '../../core/project-registry.js';
|
|
9
|
+
import { SPEC_WORKFLOW_HOME_ENV } from '../../core/global-dir.js';
|
|
10
|
+
async function getFreePort() {
|
|
11
|
+
return await new Promise((resolvePort, reject) => {
|
|
12
|
+
const server = net.createServer();
|
|
13
|
+
server.listen(0, '127.0.0.1', () => {
|
|
14
|
+
const address = server.address();
|
|
15
|
+
if (!address || typeof address === 'string') {
|
|
16
|
+
server.close();
|
|
17
|
+
reject(new Error('Failed to get free port'));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const port = address.port;
|
|
21
|
+
server.close(() => resolvePort(port));
|
|
22
|
+
});
|
|
23
|
+
server.on('error', reject);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
describe('MultiProjectDashboardServer approvals content resolution', () => {
|
|
27
|
+
let tempDir;
|
|
28
|
+
let workspacePath;
|
|
29
|
+
let workflowRootPath;
|
|
30
|
+
let server = null;
|
|
31
|
+
let projectId;
|
|
32
|
+
let realFetch;
|
|
33
|
+
const originalEnv = { ...process.env };
|
|
34
|
+
beforeEach(async () => {
|
|
35
|
+
tempDir = join(tmpdir(), `specwf-multi-server-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
36
|
+
workspacePath = join(tempDir, 'worktrees', 'wt-a');
|
|
37
|
+
workflowRootPath = join(tempDir, 'repo-main');
|
|
38
|
+
await fs.mkdir(workspacePath, { recursive: true });
|
|
39
|
+
await fs.mkdir(workflowRootPath, { recursive: true });
|
|
40
|
+
process.env[SPEC_WORKFLOW_HOME_ENV] = join(tempDir, '.global-state');
|
|
41
|
+
projectId = generateProjectId(workspacePath);
|
|
42
|
+
realFetch = globalThis.fetch;
|
|
43
|
+
const registry = new ProjectRegistry();
|
|
44
|
+
await registry.registerProject(workspacePath, process.pid, { workflowRootPath });
|
|
45
|
+
// Prevent network dependency in package version lookup.
|
|
46
|
+
vi.stubGlobal('fetch', vi.fn(async () => ({
|
|
47
|
+
ok: false,
|
|
48
|
+
json: async () => ({})
|
|
49
|
+
})));
|
|
50
|
+
});
|
|
51
|
+
afterEach(async () => {
|
|
52
|
+
if (server) {
|
|
53
|
+
await server.stop();
|
|
54
|
+
server = null;
|
|
55
|
+
}
|
|
56
|
+
vi.unstubAllGlobals();
|
|
57
|
+
process.env = { ...originalEnv };
|
|
58
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
it('prioritizes workspace path before workflow root for relative approval filePath', async () => {
|
|
61
|
+
const relativePath = 'src/service.ts';
|
|
62
|
+
await fs.mkdir(join(workspacePath, 'src'), { recursive: true });
|
|
63
|
+
await fs.mkdir(join(workflowRootPath, 'src'), { recursive: true });
|
|
64
|
+
await fs.writeFile(join(workspacePath, relativePath), 'workspace-content', 'utf-8');
|
|
65
|
+
await fs.writeFile(join(workflowRootPath, relativePath), 'workflow-content', 'utf-8');
|
|
66
|
+
const approvalStorage = new ApprovalStorage(workflowRootPath, {
|
|
67
|
+
originalPath: workflowRootPath,
|
|
68
|
+
fileResolutionPath: workspacePath
|
|
69
|
+
});
|
|
70
|
+
const approvalId = await approvalStorage.createApproval('Review service', relativePath, 'spec', 'test-spec');
|
|
71
|
+
const port = await getFreePort();
|
|
72
|
+
server = new MultiProjectDashboardServer({ autoOpen: false, port });
|
|
73
|
+
await server.start();
|
|
74
|
+
const response = await realFetch(`http://127.0.0.1:${port}/api/projects/${projectId}/approvals/${approvalId}/content`);
|
|
75
|
+
const body = await response.json();
|
|
76
|
+
expect(response.status).toBe(200);
|
|
77
|
+
expect(body.content).toBe('workspace-content');
|
|
78
|
+
expect(body.filePath).toContain(join('worktrees', 'wt-a', 'src', 'service.ts'));
|
|
79
|
+
});
|
|
80
|
+
it('falls back to workflow root when relative file only exists there', async () => {
|
|
81
|
+
const relativePath = '.spec-workflow/specs/test-spec/requirements.md';
|
|
82
|
+
await fs.mkdir(join(workflowRootPath, '.spec-workflow', 'specs', 'test-spec'), { recursive: true });
|
|
83
|
+
await fs.writeFile(join(workflowRootPath, relativePath), '# Shared requirements', 'utf-8');
|
|
84
|
+
const approvalStorage = new ApprovalStorage(workflowRootPath, {
|
|
85
|
+
originalPath: workflowRootPath,
|
|
86
|
+
fileResolutionPath: workspacePath
|
|
87
|
+
});
|
|
88
|
+
const approvalId = await approvalStorage.createApproval('Review requirements', relativePath, 'spec', 'test-spec');
|
|
89
|
+
const port = await getFreePort();
|
|
90
|
+
server = new MultiProjectDashboardServer({ autoOpen: false, port });
|
|
91
|
+
await server.start();
|
|
92
|
+
const response = await realFetch(`http://127.0.0.1:${port}/api/projects/${projectId}/approvals/${approvalId}/content`);
|
|
93
|
+
const body = await response.json();
|
|
94
|
+
expect(response.status).toBe(200);
|
|
95
|
+
expect(body.content).toBe('# Shared requirements');
|
|
96
|
+
expect(body.filePath).toContain(join('repo-main', '.spec-workflow', 'specs', 'test-spec', 'requirements.md'));
|
|
97
|
+
});
|
|
98
|
+
it('uses absolute approval filePath as-is', async () => {
|
|
99
|
+
const absolutePath = join(tempDir, 'absolute-target.md');
|
|
100
|
+
await fs.writeFile(absolutePath, 'absolute-file-content', 'utf-8');
|
|
101
|
+
const approvalStorage = new ApprovalStorage(workflowRootPath, {
|
|
102
|
+
originalPath: workflowRootPath,
|
|
103
|
+
fileResolutionPath: workspacePath
|
|
104
|
+
});
|
|
105
|
+
const approvalId = await approvalStorage.createApproval('Review absolute path', absolutePath, 'spec', 'test-spec');
|
|
106
|
+
const port = await getFreePort();
|
|
107
|
+
server = new MultiProjectDashboardServer({ autoOpen: false, port });
|
|
108
|
+
await server.start();
|
|
109
|
+
const response = await realFetch(`http://127.0.0.1:${port}/api/projects/${projectId}/approvals/${approvalId}/content`);
|
|
110
|
+
const body = await response.json();
|
|
111
|
+
expect(response.status).toBe(200);
|
|
112
|
+
expect(body.content).toBe('absolute-file-content');
|
|
113
|
+
expect(body.filePath).toBe(absolutePath);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=multi-server-approvals-content.test.js.map
|