pi-usereq 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.g.conf +20 -0
- package/.github/workflows/release-npm.yml +131 -0
- package/.gitignore +270 -0
- package/CHANGELOG.md +221 -0
- package/LICENSE +674 -0
- package/README.md +260 -0
- package/TODO.md +20 -0
- package/docs/pi.dev/agent-document-manifest.json +6399 -0
- package/docs/pi.dev/coding-agent-docs/compaction.md +394 -0
- package/docs/pi.dev/coding-agent-docs/custom-provider.md +596 -0
- package/docs/pi.dev/coding-agent-docs/development.md +71 -0
- package/docs/pi.dev/coding-agent-docs/extensions.md +2262 -0
- package/docs/pi.dev/coding-agent-docs/images/doom-extension.png +0 -0
- package/docs/pi.dev/coding-agent-docs/images/exy.png +0 -0
- package/docs/pi.dev/coding-agent-docs/images/interactive-mode.png +0 -0
- package/docs/pi.dev/coding-agent-docs/images/tree-view.png +0 -0
- package/docs/pi.dev/coding-agent-docs/json.md +82 -0
- package/docs/pi.dev/coding-agent-docs/keybindings.md +175 -0
- package/docs/pi.dev/coding-agent-docs/models.md +392 -0
- package/docs/pi.dev/coding-agent-docs/packages.md +218 -0
- package/docs/pi.dev/coding-agent-docs/prompt-templates.md +67 -0
- package/docs/pi.dev/coding-agent-docs/providers.md +195 -0
- package/docs/pi.dev/coding-agent-docs/rpc.md +1377 -0
- package/docs/pi.dev/coding-agent-docs/sdk.md +1124 -0
- package/docs/pi.dev/coding-agent-docs/session.md +412 -0
- package/docs/pi.dev/coding-agent-docs/settings.md +247 -0
- package/docs/pi.dev/coding-agent-docs/shell-aliases.md +13 -0
- package/docs/pi.dev/coding-agent-docs/skills.md +232 -0
- package/docs/pi.dev/coding-agent-docs/terminal-setup.md +106 -0
- package/docs/pi.dev/coding-agent-docs/termux.md +127 -0
- package/docs/pi.dev/coding-agent-docs/themes.md +295 -0
- package/docs/pi.dev/coding-agent-docs/tmux.md +61 -0
- package/docs/pi.dev/coding-agent-docs/tree.md +231 -0
- package/docs/pi.dev/coding-agent-docs/tui.md +887 -0
- package/docs/pi.dev/coding-agent-docs/windows.md +17 -0
- package/docs/pi.dev/mom-docs/artifacts-server.md +475 -0
- package/docs/pi.dev/mom-docs/events.md +307 -0
- package/docs/pi.dev/mom-docs/new.md +970 -0
- package/docs/pi.dev/mom-docs/sandbox.md +153 -0
- package/docs/pi.dev/mom-docs/slack-bot-minimal-guide.md +399 -0
- package/docs/pi.dev/mom-docs/v86.md +319 -0
- package/docs/pi.dev/pods-docs/gml-4.5.md +189 -0
- package/docs/pi.dev/pods-docs/gpt-oss.md +233 -0
- package/docs/pi.dev/pods-docs/implementation-plan.md +183 -0
- package/docs/pi.dev/pods-docs/kimi-k2.md +197 -0
- package/docs/pi.dev/pods-docs/models.md +116 -0
- package/docs/pi.dev/pods-docs/plan.md +166 -0
- package/docs/pi.dev/pods-docs/qwen3-coder.md +132 -0
- package/images/flowchart-bw.png +0 -0
- package/images/flowchart-bw.svg +102 -0
- package/images/flowchart.md +100 -0
- package/images/flowchart.png +0 -0
- package/images/flowchart.svg +3 -0
- package/package.json +46 -0
- package/req/docs/REFERENCES.md +4554 -0
- package/req/docs/REQUIREMENTS.md +475 -0
- package/req/docs/WORKFLOW.md +1059 -0
- package/scripts/debug-extension.ts +497 -0
- package/scripts/lib/extension-debug-harness.ts +450 -0
- package/scripts/lib/recording-extension-api.ts +786 -0
- package/scripts/lib/sdk-smoke.ts +503 -0
- package/scripts/pi-usereq-debug.sh +330 -0
- package/scripts/tool-args-to-params.ts +208 -0
- package/src/cli.ts +349 -0
- package/src/core/agent-tool-json.ts +621 -0
- package/src/core/compress-files.ts +72 -0
- package/src/core/compress-payload.ts +648 -0
- package/src/core/compress.ts +464 -0
- package/src/core/config.ts +272 -0
- package/src/core/doxygen-parser.ts +318 -0
- package/src/core/errors.ts +31 -0
- package/src/core/extension-status.ts +660 -0
- package/src/core/find-constructs.ts +319 -0
- package/src/core/find-payload.ts +915 -0
- package/src/core/generate-markdown.ts +120 -0
- package/src/core/path-context.ts +196 -0
- package/src/core/pi-notify.ts +430 -0
- package/src/core/pi-usereq-tools.ts +140 -0
- package/src/core/prompts.ts +184 -0
- package/src/core/reference-payload.ts +818 -0
- package/src/core/resources.ts +63 -0
- package/src/core/runtime-project-paths.ts +99 -0
- package/src/core/settings-menu.ts +233 -0
- package/src/core/source-analyzer.ts +1721 -0
- package/src/core/static-check.ts +674 -0
- package/src/core/token-counter.ts +729 -0
- package/src/core/tool-runner.ts +717 -0
- package/src/core/utils.ts +185 -0
- package/src/index.ts +2209 -0
- package/src/resources/guidelines/Google_C++_Style_Guide.md +3711 -0
- package/src/resources/guidelines/Google_Python_Style_Guide.md +3709 -0
- package/src/resources/prompts/analyze.md +130 -0
- package/src/resources/prompts/change.md +227 -0
- package/src/resources/prompts/check.md +139 -0
- package/src/resources/prompts/cover.md +219 -0
- package/src/resources/prompts/create.md +104 -0
- package/src/resources/prompts/fix.md +221 -0
- package/src/resources/prompts/flowchart.md +220 -0
- package/src/resources/prompts/implement.md +163 -0
- package/src/resources/prompts/new.md +226 -0
- package/src/resources/prompts/readme.md +182 -0
- package/src/resources/prompts/recreate.md +213 -0
- package/src/resources/prompts/refactor.md +213 -0
- package/src/resources/prompts/references.md +100 -0
- package/src/resources/prompts/renumber.md +119 -0
- package/src/resources/prompts/workflow.md +202 -0
- package/src/resources/prompts/write.md +99 -0
- package/src/resources/sounds/Machine-alert-beep-sound-effect.mp3 +0 -0
- package/src/resources/sounds/Soft-high-tech-notification-sound-effect.mp3 +0 -0
- package/src/resources/templates/Document_Source_Code_in_Doxygen_Style.md +130 -0
- package/src/resources/templates/HDT_Test_Authoring_Guide.md +318 -0
- package/src/resources/templates/Requirements_Template.md +78 -0
- package/tests/attended-results-scenarios.ts +758 -0
- package/tests/attended-results.test.ts +39 -0
- package/tests/cli-command-option-parity.test.ts +815 -0
- package/tests/debug-extension-harness.test.ts +463 -0
- package/tests/extension-registration.test.ts +2006 -0
- package/tests/fixtures/fixture_c.c +361 -0
- package/tests/fixtures/fixture_cpp.cpp +407 -0
- package/tests/fixtures/fixture_csharp.cs +411 -0
- package/tests/fixtures/fixture_elixir.ex +409 -0
- package/tests/fixtures/fixture_go.go +341 -0
- package/tests/fixtures/fixture_haskell.hs +250 -0
- package/tests/fixtures/fixture_java.java +430 -0
- package/tests/fixtures/fixture_javascript.js +383 -0
- package/tests/fixtures/fixture_kotlin.kt +451 -0
- package/tests/fixtures/fixture_lua.lua +276 -0
- package/tests/fixtures/fixture_perl.pl +310 -0
- package/tests/fixtures/fixture_php.php +433 -0
- package/tests/fixtures/fixture_python.py +502 -0
- package/tests/fixtures/fixture_ruby.rb +345 -0
- package/tests/fixtures/fixture_rust.rs +380 -0
- package/tests/fixtures/fixture_scala.scala +398 -0
- package/tests/fixtures/fixture_shell.sh +276 -0
- package/tests/fixtures/fixture_swift.swift +397 -0
- package/tests/fixtures/fixture_typescript.ts +434 -0
- package/tests/fixtures/fixture_zig.zig +295 -0
- package/tests/fixtures_attended_results/project/compress-line-numbers.json +5 -0
- package/tests/fixtures_attended_results/project/compress.json +5 -0
- package/tests/fixtures_attended_results/project/enable-static-check-invalid-command.json +5 -0
- package/tests/fixtures_attended_results/project/enable-static-check-valid.json +5 -0
- package/tests/fixtures_attended_results/project/files-static-check.json +5 -0
- package/tests/fixtures_attended_results/project/find-line-numbers.json +5 -0
- package/tests/fixtures_attended_results/project/find.json +5 -0
- package/tests/fixtures_attended_results/project/get-base-path.json +5 -0
- package/tests/fixtures_attended_results/project/git-check-clean.json +5 -0
- package/tests/fixtures_attended_results/project/git-check-dirty.json +5 -0
- package/tests/fixtures_attended_results/project/git-path.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-create-invalid.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-create-valid.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-delete-nonexistent.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-delete-valid.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-name.json +5 -0
- package/tests/fixtures_attended_results/project/references.json +5 -0
- package/tests/fixtures_attended_results/project/static-check.json +5 -0
- package/tests/fixtures_attended_results/project/tokens.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_zig.zig.json +5 -0
- package/tests/helpers.ts +204 -0
- package/tests/oracle-project.test.ts +63 -0
- package/tests/oracle-standalone.test.ts +48 -0
- package/tests/prompt-rendering.test.ts +66 -0
- package/tests/release-workflow.test.ts +133 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Loads, normalizes, and persists pi-usereq project configuration.
|
|
4
|
+
* @details Defines the configuration schema, default directory conventions, JSON serialization helpers, and prompt placeholder expansion paths. Runtime is dominated by filesystem reads and writes plus linear normalization over configured entries. Side effects include config-file persistence under `.pi-usereq`.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { ReqError } from "./errors.js";
|
|
10
|
+
import {
|
|
11
|
+
buildRuntimePathContext,
|
|
12
|
+
buildRuntimePathFacts,
|
|
13
|
+
formatRuntimePathForDisplay,
|
|
14
|
+
getConfigPath,
|
|
15
|
+
} from "./path-context.js";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_PI_NOTIFY_SOUND_HIGH_CMD,
|
|
18
|
+
DEFAULT_PI_NOTIFY_SOUND_LOW_CMD,
|
|
19
|
+
DEFAULT_PI_NOTIFY_SOUND_MID_CMD,
|
|
20
|
+
DEFAULT_PI_NOTIFY_SOUND_TOGGLE_SHORTCUT,
|
|
21
|
+
normalizePiNotifyCommand,
|
|
22
|
+
normalizePiNotifyShortcut,
|
|
23
|
+
normalizePiNotifySoundLevel,
|
|
24
|
+
} from "./pi-notify.js";
|
|
25
|
+
import { normalizeEnabledPiUsereqTools } from "./pi-usereq-tools.js";
|
|
26
|
+
import { makeRelativeIfContainsProject } from "./utils.js";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @brief Describes one static-check module configuration entry.
|
|
30
|
+
* @details Each record identifies the checker module and optional command or parameter list used during per-language static analysis dispatch. The interface is type-only and has no runtime cost.
|
|
31
|
+
*/
|
|
32
|
+
export interface StaticCheckEntry {
|
|
33
|
+
module: string;
|
|
34
|
+
cmd?: string;
|
|
35
|
+
params?: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @brief Defines the persisted pi-usereq project configuration schema.
|
|
40
|
+
* @details Captures documentation paths, source/test directory selection, static-check configuration, enabled startup tools, and notification settings while excluding runtime-derived path metadata. The interface is compile-time only and introduces no runtime side effects.
|
|
41
|
+
*/
|
|
42
|
+
export interface UseReqConfig {
|
|
43
|
+
"docs-dir": string;
|
|
44
|
+
"tests-dir": string;
|
|
45
|
+
"src-dir": string[];
|
|
46
|
+
"static-check": Record<string, StaticCheckEntry[]>;
|
|
47
|
+
"enabled-tools": string[];
|
|
48
|
+
"notify-beep-on-end": boolean;
|
|
49
|
+
"notify-beep-on-esc": boolean;
|
|
50
|
+
"notify-beep-on-error": boolean;
|
|
51
|
+
"notify-sound": "none" | "low" | "mid" | "high";
|
|
52
|
+
"notify-sound-toggle-shortcut": string;
|
|
53
|
+
PI_NOTIFY_SOUND_LOW_CMD: string;
|
|
54
|
+
PI_NOTIFY_SOUND_MID_CMD: string;
|
|
55
|
+
PI_NOTIFY_SOUND_HIGH_CMD: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @brief Defines the default documentation directory relative to the project root.
|
|
60
|
+
* @details Used when no persisted `docs-dir` value exists or normalization yields an empty string. Lookup complexity is O(1).
|
|
61
|
+
* @satisfies CTN-001
|
|
62
|
+
*/
|
|
63
|
+
export const DEFAULT_DOCS_DIR = "pi-usereq/docs";
|
|
64
|
+
/**
|
|
65
|
+
* @brief Defines the default tests directory relative to the project root.
|
|
66
|
+
* @details Used when no persisted `tests-dir` value exists or normalization yields an empty string. Lookup complexity is O(1).
|
|
67
|
+
*/
|
|
68
|
+
export const DEFAULT_TESTS_DIR = "tests";
|
|
69
|
+
/**
|
|
70
|
+
* @brief Defines the default set of source directories relative to the project root.
|
|
71
|
+
* @details The array seeds newly created configs and repairs invalid persisted source selections. Access complexity is O(1).
|
|
72
|
+
*/
|
|
73
|
+
export const DEFAULT_SRC_DIRS = ["src"];
|
|
74
|
+
/**
|
|
75
|
+
* @brief Computes the per-project config file path.
|
|
76
|
+
* @details Joins the project base with `.pi-usereq/config.json`, producing the canonical persistence location used by CLI and extension code. Time complexity is O(1). No I/O side effects occur.
|
|
77
|
+
* @param[in] projectBase {string} Absolute project root path.
|
|
78
|
+
* @return {string} Absolute config file path.
|
|
79
|
+
*/
|
|
80
|
+
export function getProjectConfigPath(projectBase: string): string {
|
|
81
|
+
return getConfigPath(projectBase);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @brief Builds the default project configuration.
|
|
86
|
+
* @details Populates canonical docs/test/source directories, the default startup tool set, and default pi-notify fields while excluding runtime-derived path metadata. Time complexity is O(n) in default tool count. No filesystem side effects occur.
|
|
87
|
+
* @param[in] projectBase {string} Absolute project root path.
|
|
88
|
+
* @return {UseReqConfig} Fresh default configuration object.
|
|
89
|
+
* @satisfies CTN-001, CTN-012, REQ-066, REQ-146
|
|
90
|
+
*/
|
|
91
|
+
export function getDefaultConfig(_projectBase: string): UseReqConfig {
|
|
92
|
+
return {
|
|
93
|
+
"docs-dir": DEFAULT_DOCS_DIR,
|
|
94
|
+
"tests-dir": DEFAULT_TESTS_DIR,
|
|
95
|
+
"src-dir": [...DEFAULT_SRC_DIRS],
|
|
96
|
+
"static-check": {},
|
|
97
|
+
"enabled-tools": normalizeEnabledPiUsereqTools(undefined),
|
|
98
|
+
"notify-beep-on-end": false,
|
|
99
|
+
"notify-beep-on-esc": false,
|
|
100
|
+
"notify-beep-on-error": false,
|
|
101
|
+
"notify-sound": "none",
|
|
102
|
+
"notify-sound-toggle-shortcut": DEFAULT_PI_NOTIFY_SOUND_TOGGLE_SHORTCUT,
|
|
103
|
+
PI_NOTIFY_SOUND_LOW_CMD: DEFAULT_PI_NOTIFY_SOUND_LOW_CMD,
|
|
104
|
+
PI_NOTIFY_SOUND_MID_CMD: DEFAULT_PI_NOTIFY_SOUND_MID_CMD,
|
|
105
|
+
PI_NOTIFY_SOUND_HIGH_CMD: DEFAULT_PI_NOTIFY_SOUND_HIGH_CMD,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @brief Loads and sanitizes the persisted project configuration.
|
|
111
|
+
* @details Returns defaults when the config file does not exist. Otherwise parses JSON, validates directory and static-check field shapes, normalizes enabled tool names and pi-notify fields, and ignores removed or runtime-derived path metadata. Runtime is O(n) in config size. Side effects are limited to filesystem reads.
|
|
112
|
+
* @param[in] projectBase {string} Absolute project root path.
|
|
113
|
+
* @return {UseReqConfig} Sanitized effective configuration.
|
|
114
|
+
* @throws {ReqError} Throws with exit code `11` when the config file contains invalid JSON or a non-object payload.
|
|
115
|
+
* @satisfies CTN-012, REQ-066, REQ-146
|
|
116
|
+
*/
|
|
117
|
+
export function loadConfig(projectBase: string): UseReqConfig {
|
|
118
|
+
const configPath = getProjectConfigPath(projectBase);
|
|
119
|
+
if (!fs.existsSync(configPath)) {
|
|
120
|
+
return getDefaultConfig(projectBase);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let payload: unknown;
|
|
124
|
+
try {
|
|
125
|
+
payload = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
126
|
+
} catch (error) {
|
|
127
|
+
throw new ReqError(`Error: invalid ${configPath}`, 11);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!payload || typeof payload !== "object") {
|
|
131
|
+
throw new ReqError(`Error: invalid ${configPath}`, 11);
|
|
132
|
+
}
|
|
133
|
+
const data = payload as Record<string, unknown>;
|
|
134
|
+
const docsDir = typeof data["docs-dir"] === "string" && data["docs-dir"].trim() ? data["docs-dir"] : DEFAULT_DOCS_DIR;
|
|
135
|
+
const testsDir = typeof data["tests-dir"] === "string" && data["tests-dir"].trim() ? data["tests-dir"] : DEFAULT_TESTS_DIR;
|
|
136
|
+
const srcDir = Array.isArray(data["src-dir"]) && data["src-dir"].every((item) => typeof item === "string" && item.trim())
|
|
137
|
+
? (data["src-dir"] as string[])
|
|
138
|
+
: [...DEFAULT_SRC_DIRS];
|
|
139
|
+
const staticCheck = typeof data["static-check"] === "object" && data["static-check"] !== null
|
|
140
|
+
? (data["static-check"] as Record<string, StaticCheckEntry[]>)
|
|
141
|
+
: {};
|
|
142
|
+
const enabledTools = normalizeEnabledPiUsereqTools(data["enabled-tools"]);
|
|
143
|
+
const notifyBeepOnEnd = data["notify-beep-on-end"] === true;
|
|
144
|
+
const notifyBeepOnEsc = data["notify-beep-on-esc"] === true;
|
|
145
|
+
const notifyBeepOnError = data["notify-beep-on-error"] === true;
|
|
146
|
+
const notifySound = normalizePiNotifySoundLevel(data["notify-sound"]);
|
|
147
|
+
const notifySoundToggleShortcut = normalizePiNotifyShortcut(data["notify-sound-toggle-shortcut"]);
|
|
148
|
+
const lowSoundCommand = normalizePiNotifyCommand(data.PI_NOTIFY_SOUND_LOW_CMD, DEFAULT_PI_NOTIFY_SOUND_LOW_CMD);
|
|
149
|
+
const midSoundCommand = normalizePiNotifyCommand(data.PI_NOTIFY_SOUND_MID_CMD, DEFAULT_PI_NOTIFY_SOUND_MID_CMD);
|
|
150
|
+
const highSoundCommand = normalizePiNotifyCommand(data.PI_NOTIFY_SOUND_HIGH_CMD, DEFAULT_PI_NOTIFY_SOUND_HIGH_CMD);
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
"docs-dir": docsDir,
|
|
154
|
+
"tests-dir": testsDir,
|
|
155
|
+
"src-dir": srcDir,
|
|
156
|
+
"static-check": staticCheck,
|
|
157
|
+
"enabled-tools": enabledTools,
|
|
158
|
+
"notify-beep-on-end": notifyBeepOnEnd,
|
|
159
|
+
"notify-beep-on-esc": notifyBeepOnEsc,
|
|
160
|
+
"notify-beep-on-error": notifyBeepOnError,
|
|
161
|
+
"notify-sound": notifySound,
|
|
162
|
+
"notify-sound-toggle-shortcut": notifySoundToggleShortcut,
|
|
163
|
+
PI_NOTIFY_SOUND_LOW_CMD: lowSoundCommand,
|
|
164
|
+
PI_NOTIFY_SOUND_MID_CMD: midSoundCommand,
|
|
165
|
+
PI_NOTIFY_SOUND_HIGH_CMD: highSoundCommand,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @brief Builds the persisted configuration payload that excludes runtime-derived fields.
|
|
171
|
+
* @details Copies only the canonical persisted configuration keys into a fresh object so runtime-derived metadata such as `base-path` and `git-path` can never be written to disk. Runtime is O(n) in config size. No external state is mutated.
|
|
172
|
+
* @param[in] config {UseReqConfig} Effective configuration object.
|
|
173
|
+
* @return {UseReqConfig} Persistable configuration payload.
|
|
174
|
+
* @satisfies CTN-012, REQ-146
|
|
175
|
+
*/
|
|
176
|
+
function buildPersistedConfig(config: UseReqConfig): UseReqConfig {
|
|
177
|
+
return {
|
|
178
|
+
"docs-dir": config["docs-dir"],
|
|
179
|
+
"tests-dir": config["tests-dir"],
|
|
180
|
+
"src-dir": [...config["src-dir"]],
|
|
181
|
+
"static-check": Object.fromEntries(
|
|
182
|
+
Object.entries(config["static-check"]).map(([language, entries]) => [
|
|
183
|
+
language,
|
|
184
|
+
entries.map((entry) => ({
|
|
185
|
+
module: entry.module,
|
|
186
|
+
...(entry.cmd ? { cmd: entry.cmd } : {}),
|
|
187
|
+
...(entry.params ? { params: [...entry.params] } : {}),
|
|
188
|
+
})),
|
|
189
|
+
]),
|
|
190
|
+
),
|
|
191
|
+
"enabled-tools": [...config["enabled-tools"]],
|
|
192
|
+
"notify-beep-on-end": config["notify-beep-on-end"],
|
|
193
|
+
"notify-beep-on-esc": config["notify-beep-on-esc"],
|
|
194
|
+
"notify-beep-on-error": config["notify-beep-on-error"],
|
|
195
|
+
"notify-sound": config["notify-sound"],
|
|
196
|
+
"notify-sound-toggle-shortcut": config["notify-sound-toggle-shortcut"],
|
|
197
|
+
PI_NOTIFY_SOUND_LOW_CMD: config.PI_NOTIFY_SOUND_LOW_CMD,
|
|
198
|
+
PI_NOTIFY_SOUND_MID_CMD: config.PI_NOTIFY_SOUND_MID_CMD,
|
|
199
|
+
PI_NOTIFY_SOUND_HIGH_CMD: config.PI_NOTIFY_SOUND_HIGH_CMD,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @brief Persists the project configuration to disk.
|
|
205
|
+
* @details Creates the parent `.pi-usereq` directory when necessary, strips runtime-derived fields from the serialized payload, and writes formatted JSON terminated by a newline. Runtime is O(n) in serialized config size. Side effects include directory creation and file overwrite.
|
|
206
|
+
* @param[in] projectBase {string} Absolute project root path.
|
|
207
|
+
* @param[in] config {UseReqConfig} Configuration object to persist.
|
|
208
|
+
* @return {void} No return value.
|
|
209
|
+
* @satisfies CTN-012, REQ-146
|
|
210
|
+
*/
|
|
211
|
+
export function saveConfig(projectBase: string, config: UseReqConfig): void {
|
|
212
|
+
const configPath = getProjectConfigPath(projectBase);
|
|
213
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
214
|
+
fs.writeFileSync(configPath, `${JSON.stringify(buildPersistedConfig(config), null, 2)}\n`, "utf8");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @brief Normalizes persisted directory fields to project-relative forms.
|
|
219
|
+
* @details Rewrites docs, tests, and source directories using project containment heuristics, strips trailing separators, and restores defaults for empty results. Runtime is O(n) in configured path count plus path-length processing. No filesystem writes occur.
|
|
220
|
+
* @param[in] projectBase {string} Absolute project root path.
|
|
221
|
+
* @param[in] config {UseReqConfig} Configuration object to normalize.
|
|
222
|
+
* @return {UseReqConfig} Normalized configuration copy.
|
|
223
|
+
*/
|
|
224
|
+
export function normalizeConfigPaths(projectBase: string, config: UseReqConfig): UseReqConfig {
|
|
225
|
+
const docsDir = makeRelativeIfContainsProject(config["docs-dir"], projectBase).replace(/[/\\]+$/, "") || DEFAULT_DOCS_DIR;
|
|
226
|
+
const testsDir = makeRelativeIfContainsProject(config["tests-dir"], projectBase).replace(/[/\\]+$/, "") || DEFAULT_TESTS_DIR;
|
|
227
|
+
const srcDirs = config["src-dir"].map((value) => makeRelativeIfContainsProject(value, projectBase).replace(/[/\\]+$/, "")).filter(Boolean);
|
|
228
|
+
return {
|
|
229
|
+
...config,
|
|
230
|
+
"docs-dir": docsDir,
|
|
231
|
+
"tests-dir": testsDir,
|
|
232
|
+
"src-dir": srcDirs.length > 0 ? srcDirs : [...DEFAULT_SRC_DIRS],
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @brief Builds placeholder replacements for bundled prompt rendering.
|
|
238
|
+
* @details Computes runtime path context from the execution path, derives installation-owned template and guideline paths, enumerates visible guideline files from the installed resource tree, and returns the token map consumed by prompt templates. Runtime is O(g log g + s) where g is guideline count and s is source-directory count. Side effects are limited to filesystem reads.
|
|
239
|
+
* @param[in] projectBase {string} Absolute project root path.
|
|
240
|
+
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
241
|
+
* @return {Record<string, string>} Placeholder-to-string replacement map including runtime path tokens.
|
|
242
|
+
* @satisfies REQ-002, REQ-103, REQ-106, REQ-107, CTN-011
|
|
243
|
+
*/
|
|
244
|
+
export function buildPromptReplacementPaths(projectBase: string, config: UseReqConfig): Record<string, string> {
|
|
245
|
+
const runtimePathContext = buildRuntimePathContext(projectBase, config);
|
|
246
|
+
const runtimePathFacts = buildRuntimePathFacts(runtimePathContext);
|
|
247
|
+
const guidelineEntries = fs.existsSync(runtimePathContext.guidelinesPath)
|
|
248
|
+
? fs.readdirSync(runtimePathContext.guidelinesPath)
|
|
249
|
+
.filter((entry) => !entry.startsWith("."))
|
|
250
|
+
.map((entry) => formatRuntimePathForDisplay(path.join(runtimePathContext.guidelinesPath, entry)))
|
|
251
|
+
.sort((left, right) => left.localeCompare(right))
|
|
252
|
+
: [];
|
|
253
|
+
|
|
254
|
+
const srcValue = config["src-dir"].map((value) => `\`${value.replace(/[/\\]+$/, "")}/\``).join(", ");
|
|
255
|
+
const testValue = `\`${config["tests-dir"].replace(/[/\\]+$/, "")}/\``;
|
|
256
|
+
const guidelinesValue = guidelineEntries.length > 0
|
|
257
|
+
? guidelineEntries.map((entry) => `\`${entry}\``).join(", ")
|
|
258
|
+
: `\`${runtimePathFacts.guidelines_path}/\``;
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
"%%DOC_PATH%%": config["docs-dir"].replace(/[/\\]+$/, ""),
|
|
262
|
+
"%%GUIDELINES_FILES%%": guidelinesValue,
|
|
263
|
+
"%%GUIDELINES_PATH%%": runtimePathFacts.guidelines_path,
|
|
264
|
+
"%%TEMPLATE_PATH%%": runtimePathFacts.templates_path,
|
|
265
|
+
"%%SRC_PATHS%%": srcValue,
|
|
266
|
+
"%%TEST_PATH%%": testValue,
|
|
267
|
+
"%%PROJECT_BASE%%": runtimePathFacts.base_path,
|
|
268
|
+
"%%EXECUTION_PATH%%": runtimePathFacts.execution_path,
|
|
269
|
+
"%%INSTALLATION_PATH%%": runtimePathFacts.installation_path,
|
|
270
|
+
"%%CONFIG_PATH%%": runtimePathFacts.config_path,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Parses repository-approved Doxygen tags and renders them as markdown bullets.
|
|
4
|
+
* @details Implements a constrained Doxygen grammar used by the source analyzer and construct finder. Parsing cost is linear in comment length. The module is pure and performs no I/O.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @brief Defines the ordered repository Doxygen tag taxonomy.
|
|
9
|
+
* @details The array is reused for validation, parsing precedence, and markdown serialization order. Lookup by index is O(1); scans are O(n) in tag count. The list is immutable after module load.
|
|
10
|
+
*/
|
|
11
|
+
export const DOXYGEN_TAGS = [
|
|
12
|
+
"brief",
|
|
13
|
+
"details",
|
|
14
|
+
"param",
|
|
15
|
+
"param[in]",
|
|
16
|
+
"param[out]",
|
|
17
|
+
"param[in,out]",
|
|
18
|
+
"return",
|
|
19
|
+
"retval",
|
|
20
|
+
"exception",
|
|
21
|
+
"throws",
|
|
22
|
+
"warning",
|
|
23
|
+
"deprecated",
|
|
24
|
+
"note",
|
|
25
|
+
"see",
|
|
26
|
+
"sa",
|
|
27
|
+
"satisfies",
|
|
28
|
+
"pre",
|
|
29
|
+
"post",
|
|
30
|
+
] as const;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @brief Lists supported tags that are not parameter variants.
|
|
34
|
+
* @details Derived once from `DOXYGEN_TAGS` to simplify regex construction for parsers that need to discriminate `@param` forms from all other tags. Construction complexity is O(n).
|
|
35
|
+
*/
|
|
36
|
+
const NON_PARAM_TAGS = DOXYGEN_TAGS.filter(
|
|
37
|
+
(tag) => !["param", "param[in]", "param[in,out]", "param[out]"].includes(tag),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @brief Builds the escaped alternation fragment for non-parameter tags.
|
|
42
|
+
* @details Sorts longer tags first to preserve greedy matching semantics in the main parser regex. Construction complexity is O(n log n) due to sorting. The resulting string is immutable.
|
|
43
|
+
*/
|
|
44
|
+
const NON_PARAM_TAG_ALTERNATION = [...NON_PARAM_TAGS]
|
|
45
|
+
.sort((a, b) => b.length - a.length)
|
|
46
|
+
.map((tag) => tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
47
|
+
.join("|");
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @brief Matches repository-supported Doxygen tags inside comment text.
|
|
51
|
+
* @details Captures `@param` plus optional direction modifiers separately from all other approved tags so downstream parsing can normalize them into deterministic keys. Regex evaluation is linear in comment size under expected inputs.
|
|
52
|
+
*/
|
|
53
|
+
const DOXYGEN_TAG_PATTERN = new RegExp(
|
|
54
|
+
String.raw`[@\\](?:(param)(\[[^\]]+\])?|(${NON_PARAM_TAG_ALTERNATION}))`,
|
|
55
|
+
"g",
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @brief Represents parsed Doxygen fields grouped by normalized tag name.
|
|
60
|
+
* @details Each key maps to one or more textual payloads because the same tag may appear multiple times in a single comment. The alias is compile-time only and adds no runtime cost.
|
|
61
|
+
*/
|
|
62
|
+
export type DoxygenFieldMap = Record<string, string[]>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @brief Enumerates supported structured parameter directions.
|
|
66
|
+
* @details Normalizes `@param` direction modifiers into one small closed set so agents can branch on parameter flow without reparsing raw tag names. The alias is compile-time only and introduces no runtime cost.
|
|
67
|
+
*/
|
|
68
|
+
export type StructuredDoxygenParamDirection = "in" | "out" | "in,out" | "unspecified";
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @brief Describes one structured Doxygen parameter field.
|
|
72
|
+
* @details Separates parameter direction, optional parameter name, optional declared type, and residual text so agents can access argument contracts without reparsing monolithic tag strings. The interface is compile-time only and introduces no runtime cost.
|
|
73
|
+
*/
|
|
74
|
+
export interface StructuredDoxygenParameterEntry {
|
|
75
|
+
direction: StructuredDoxygenParamDirection;
|
|
76
|
+
parameter_name?: string;
|
|
77
|
+
value_type?: string;
|
|
78
|
+
description?: string;
|
|
79
|
+
text?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @brief Describes the structured Doxygen field contract used by LLM-oriented JSON payloads.
|
|
84
|
+
* @details Converts repeated raw tag strings into tag-specific arrays and specialized parameter records while keeping unsplittable residual text local to the affected field. The interface is compile-time only and introduces no runtime cost.
|
|
85
|
+
*/
|
|
86
|
+
export interface StructuredDoxygenFields {
|
|
87
|
+
brief?: string[];
|
|
88
|
+
details?: string[];
|
|
89
|
+
params?: StructuredDoxygenParameterEntry[];
|
|
90
|
+
returns?: string[];
|
|
91
|
+
retvals?: string[];
|
|
92
|
+
exceptions?: string[];
|
|
93
|
+
throws?: string[];
|
|
94
|
+
warnings?: string[];
|
|
95
|
+
deprecated?: string[];
|
|
96
|
+
notes?: string[];
|
|
97
|
+
see_also?: string[];
|
|
98
|
+
satisfies_requirement_ids?: string[];
|
|
99
|
+
preconditions?: string[];
|
|
100
|
+
postconditions?: string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @brief Parses repository-approved Doxygen fields from one comment block.
|
|
105
|
+
* @details Normalizes line endings, strips comment delimiters, locates supported tags, and accumulates tag payloads in declaration order. Unsupported content is ignored. Runtime is O(n) in comment length. No side effects occur.
|
|
106
|
+
* @param[in] commentText {string} Raw comment text including delimiters.
|
|
107
|
+
* @return {DoxygenFieldMap} Parsed tag payloads keyed by normalized tag name.
|
|
108
|
+
*/
|
|
109
|
+
export function parseDoxygenComment(commentText: string): DoxygenFieldMap {
|
|
110
|
+
if (!commentText?.trim()) {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const result: DoxygenFieldMap = {};
|
|
115
|
+
const text = stripCommentDelimiters(commentText.replace(/\r\n/g, "\n").replace(/\r/g, "\n"));
|
|
116
|
+
const matches = [...text.matchAll(DOXYGEN_TAG_PATTERN)];
|
|
117
|
+
if (matches.length === 0) {
|
|
118
|
+
return {};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
matches.forEach((match, index) => {
|
|
122
|
+
const paramTag = match[1];
|
|
123
|
+
const direction = match[2] ?? "";
|
|
124
|
+
const nonParamTag = match[3];
|
|
125
|
+
const normalizedTag = paramTag ? `param${direction}` : nonParamTag;
|
|
126
|
+
if (!normalizedTag) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const startPos = match.index! + match[0].length;
|
|
131
|
+
const endPos = index + 1 < matches.length ? matches[index + 1]!.index! : text.length;
|
|
132
|
+
const content = normalizeWhitespace(text.slice(startPos, endPos).trim());
|
|
133
|
+
if (!content) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
result[normalizedTag] ??= [];
|
|
138
|
+
result[normalizedTag].push(content);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @brief Removes language comment delimiters from raw comment text.
|
|
146
|
+
* @details Drops standalone opening and closing markers, strips leading comment prefixes on each line, and preserves semantic payload lines only. Runtime is O(n) in line count. No external state is mutated.
|
|
147
|
+
* @param[in] text {string} Raw comment text.
|
|
148
|
+
* @return {string} Cleaned multi-line payload without delimiter syntax.
|
|
149
|
+
*/
|
|
150
|
+
export function stripCommentDelimiters(text: string): string {
|
|
151
|
+
const cleanedLines: string[] = [];
|
|
152
|
+
for (const line of text.split("\n")) {
|
|
153
|
+
let stripped = line.trim();
|
|
154
|
+
if (["/**", "/*", "*/", '"""', "'''", "/*!", "///", "//!"].includes(stripped)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
stripped = stripped.replace(/^[/*#]+\s*/, "");
|
|
158
|
+
stripped = stripped.replace(/^\*\s*/, "");
|
|
159
|
+
stripped = stripped.replace(/^\/\/\/?!?\s*/, "");
|
|
160
|
+
stripped = stripped.replace(/^#+\s*/, "");
|
|
161
|
+
if (stripped) {
|
|
162
|
+
cleanedLines.push(stripped);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return cleanedLines.join("\n");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @brief Collapses redundant whitespace while preserving paragraph boundaries.
|
|
170
|
+
* @details Converts repeated spaces to single spaces, trims each line, and reduces multiple blank lines to one blank separator. Runtime is O(n) in text length. No side effects occur.
|
|
171
|
+
* @param[in] text {string} Input text to normalize.
|
|
172
|
+
* @return {string} Canonically spaced text.
|
|
173
|
+
*/
|
|
174
|
+
export function normalizeWhitespace(text: string): string {
|
|
175
|
+
const lines = text.replace(/ +/g, " ").split("\n").map((line) => line.trim());
|
|
176
|
+
const normalized: string[] = [];
|
|
177
|
+
let prevBlank = false;
|
|
178
|
+
for (const line of lines) {
|
|
179
|
+
if (!line) {
|
|
180
|
+
if (!prevBlank) {
|
|
181
|
+
normalized.push(line);
|
|
182
|
+
}
|
|
183
|
+
prevBlank = true;
|
|
184
|
+
} else {
|
|
185
|
+
normalized.push(line);
|
|
186
|
+
prevBlank = false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return normalized.join("\n").trim();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @brief Serializes parsed Doxygen fields into markdown bullet lines.
|
|
194
|
+
* @details Iterates over `DOXYGEN_TAGS` in canonical order and emits one `- @tag value` line for every stored payload. Runtime is O(t + v) where t is tag count and v is total values. No side effects occur.
|
|
195
|
+
* @param[in] doxygenFields {DoxygenFieldMap} Parsed Doxygen field map.
|
|
196
|
+
* @return {string[]} Ordered markdown bullet lines.
|
|
197
|
+
*/
|
|
198
|
+
export function formatDoxygenFieldsAsMarkdown(doxygenFields: DoxygenFieldMap): string[] {
|
|
199
|
+
const lines: string[] = [];
|
|
200
|
+
for (const tag of DOXYGEN_TAGS) {
|
|
201
|
+
const values = doxygenFields[tag] ?? [];
|
|
202
|
+
for (const value of values) {
|
|
203
|
+
lines.push(`- @${tag} ${value}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return lines;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @brief Counts the total number of parsed Doxygen field values.
|
|
211
|
+
* @details Sums the value-array lengths across all tags so payload builders can expose aggregate Doxygen density as a numeric fact. Runtime is O(t) in tag count. No side effects occur.
|
|
212
|
+
* @param[in] doxygenFields {DoxygenFieldMap} Parsed Doxygen fields.
|
|
213
|
+
* @return {number} Total stored Doxygen value count.
|
|
214
|
+
*/
|
|
215
|
+
export function countDoxygenFieldValues(doxygenFields: DoxygenFieldMap): number {
|
|
216
|
+
return Object.values(doxygenFields).reduce((sum, values) => sum + values.length, 0);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @brief Parses one raw Doxygen parameter value into structured fields.
|
|
221
|
+
* @details Supports the repository-preferred `name {type} description` form, the alternate `{type} name description` form, and a residual-text fallback when no safe split is possible. Runtime is O(n) in value length. No side effects occur.
|
|
222
|
+
* @param[in] value {string} Raw Doxygen parameter value.
|
|
223
|
+
* @param[in] direction {StructuredDoxygenParamDirection} Normalized parameter direction.
|
|
224
|
+
* @return {StructuredDoxygenParameterEntry} Structured parameter record.
|
|
225
|
+
*/
|
|
226
|
+
function structureDoxygenParameterValue(value: string, direction: StructuredDoxygenParamDirection): StructuredDoxygenParameterEntry {
|
|
227
|
+
const trimmed = value.trim();
|
|
228
|
+
const preferredMatch = trimmed.match(/^([^\s{}]+)(?:\s+\{([^}]+)\})?(?:\s+(.+))?$/);
|
|
229
|
+
if (preferredMatch) {
|
|
230
|
+
const [, parameterName, valueType, description] = preferredMatch;
|
|
231
|
+
if (parameterName) {
|
|
232
|
+
return {
|
|
233
|
+
direction,
|
|
234
|
+
parameter_name: parameterName,
|
|
235
|
+
value_type: valueType,
|
|
236
|
+
description: description?.trim() || undefined,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const alternateMatch = trimmed.match(/^\{([^}]+)\}\s+([^\s{}]+)(?:\s+(.+))?$/);
|
|
242
|
+
if (alternateMatch) {
|
|
243
|
+
const [, valueType, parameterName, description] = alternateMatch;
|
|
244
|
+
return {
|
|
245
|
+
direction,
|
|
246
|
+
parameter_name: parameterName,
|
|
247
|
+
value_type: valueType,
|
|
248
|
+
description: description?.trim() || undefined,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
direction,
|
|
254
|
+
text: trimmed,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @brief Splits comma-delimited Doxygen value strings into normalized items.
|
|
260
|
+
* @details Trims surrounding whitespace, drops empty segments, and preserves original declaration order. Runtime is O(n) in aggregate text length. No side effects occur.
|
|
261
|
+
* @param[in] values {string[] | undefined} Raw Doxygen value strings.
|
|
262
|
+
* @return {string[]} Normalized item list.
|
|
263
|
+
*/
|
|
264
|
+
function splitCommaSeparatedDoxygenValues(values: string[] | undefined): string[] {
|
|
265
|
+
return (values ?? [])
|
|
266
|
+
.flatMap((value) => value.split(","))
|
|
267
|
+
.map((value) => value.trim())
|
|
268
|
+
.filter(Boolean);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @brief Extracts normalized requirement IDs from raw `@satisfies` values.
|
|
273
|
+
* @details Matches repository requirement ID prefixes directly from the raw value text so agents receive requirement links as a dedicated string array. Runtime is O(n) in aggregate text length. No side effects occur.
|
|
274
|
+
* @param[in] values {string[] | undefined} Raw `@satisfies` values.
|
|
275
|
+
* @return {string[]} Normalized requirement IDs in declaration order.
|
|
276
|
+
*/
|
|
277
|
+
function extractSatisfiedRequirementIds(values: string[] | undefined): string[] {
|
|
278
|
+
const matches = (values ?? []).flatMap((value) => value.match(/\b(?:PRJ|CTN|DES|REQ|TST)-\d+\b/g) ?? []);
|
|
279
|
+
return [...new Set(matches)];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @brief Converts raw parsed Doxygen fields into the structured JSON contract.
|
|
284
|
+
* @details Reorders raw tags into tag-specific arrays, structures parameter fields, normalizes `@see` aliases, and extracts requirement IDs from `@satisfies`. Runtime is O(t + v) where t is tag count and v is total value count. No side effects occur.
|
|
285
|
+
* @param[in] doxygenFields {DoxygenFieldMap} Raw parsed Doxygen field map.
|
|
286
|
+
* @return {StructuredDoxygenFields} Structured Doxygen fields.
|
|
287
|
+
* @satisfies REQ-078
|
|
288
|
+
*/
|
|
289
|
+
export function structureDoxygenFields(doxygenFields: DoxygenFieldMap): StructuredDoxygenFields {
|
|
290
|
+
const params = [
|
|
291
|
+
...(doxygenFields["param"] ?? []).map((value) => structureDoxygenParameterValue(value, "unspecified")),
|
|
292
|
+
...(doxygenFields["param[in]"] ?? []).map((value) => structureDoxygenParameterValue(value, "in")),
|
|
293
|
+
...(doxygenFields["param[out]"] ?? []).map((value) => structureDoxygenParameterValue(value, "out")),
|
|
294
|
+
...(doxygenFields["param[in,out]"] ?? []).map((value) => structureDoxygenParameterValue(value, "in,out")),
|
|
295
|
+
];
|
|
296
|
+
const seeAlso = [
|
|
297
|
+
...splitCommaSeparatedDoxygenValues(doxygenFields["see"]),
|
|
298
|
+
...splitCommaSeparatedDoxygenValues(doxygenFields["sa"]),
|
|
299
|
+
];
|
|
300
|
+
const satisfiesRequirementIds = extractSatisfiedRequirementIds(doxygenFields["satisfies"]);
|
|
301
|
+
const structured: StructuredDoxygenFields = {};
|
|
302
|
+
|
|
303
|
+
if (doxygenFields["brief"]?.length) structured.brief = [...doxygenFields["brief"]];
|
|
304
|
+
if (doxygenFields["details"]?.length) structured.details = [...doxygenFields["details"]];
|
|
305
|
+
if (params.length) structured.params = params;
|
|
306
|
+
if (doxygenFields["return"]?.length) structured.returns = [...doxygenFields["return"]];
|
|
307
|
+
if (doxygenFields["retval"]?.length) structured.retvals = [...doxygenFields["retval"]];
|
|
308
|
+
if (doxygenFields["exception"]?.length) structured.exceptions = [...doxygenFields["exception"]];
|
|
309
|
+
if (doxygenFields["throws"]?.length) structured.throws = [...doxygenFields["throws"]];
|
|
310
|
+
if (doxygenFields["warning"]?.length) structured.warnings = [...doxygenFields["warning"]];
|
|
311
|
+
if (doxygenFields["deprecated"]?.length) structured.deprecated = [...doxygenFields["deprecated"]];
|
|
312
|
+
if (doxygenFields["note"]?.length) structured.notes = [...doxygenFields["note"]];
|
|
313
|
+
if (seeAlso.length) structured.see_also = seeAlso;
|
|
314
|
+
if (satisfiesRequirementIds.length) structured.satisfies_requirement_ids = satisfiesRequirementIds;
|
|
315
|
+
if (doxygenFields["pre"]?.length) structured.preconditions = [...doxygenFields["pre"]];
|
|
316
|
+
if (doxygenFields["post"]?.length) structured.postconditions = [...doxygenFields["post"]];
|
|
317
|
+
return structured;
|
|
318
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Defines the repository-specific error class used by CLI and extension workflows.
|
|
4
|
+
* @details Centralizes deterministic failure signaling by pairing an error message with a numeric exit code. The module is pure and performs no I/O. Access complexity is O(1).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @brief Represents a useReq failure with a stable numeric exit code.
|
|
9
|
+
* @details Extends `Error` so callers can propagate human-readable diagnostics together with process-style status codes. Construction and property access are O(1). State mutation is limited to the created instance.
|
|
10
|
+
*/
|
|
11
|
+
export class ReqError extends Error {
|
|
12
|
+
/**
|
|
13
|
+
* @brief Stores the process-style exit code associated with the failure.
|
|
14
|
+
* @details Downstream CLI and extension handlers read this field to decide the final command status. Access complexity is O(1). The field is assigned during construction.
|
|
15
|
+
*/
|
|
16
|
+
code: number;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @brief Initializes a ReqError instance.
|
|
20
|
+
* @details Assigns the inherited error message, normalizes the runtime name to `ReqError`, and stores the provided numeric exit code. Time complexity is O(1). Side effects are limited to instance field mutation.
|
|
21
|
+
* @param[in] message {string} Human-readable failure description.
|
|
22
|
+
* @param[in] code {number} Process exit code associated with the failure. Defaults to `1`.
|
|
23
|
+
* @post `this.name === "ReqError"`.
|
|
24
|
+
* @post `this.code === code`.
|
|
25
|
+
*/
|
|
26
|
+
constructor(message: string, code = 1) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "ReqError";
|
|
29
|
+
this.code = code;
|
|
30
|
+
}
|
|
31
|
+
}
|