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
package/tests/helpers.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_DOCS_DIR,
|
|
10
|
+
getDefaultConfig,
|
|
11
|
+
getProjectConfigPath,
|
|
12
|
+
saveConfig,
|
|
13
|
+
type UseReqConfig,
|
|
14
|
+
} from "../src/core/config.js";
|
|
15
|
+
import { normalizeEnabledPiUsereqTools } from "../src/core/pi-usereq-tools.js";
|
|
16
|
+
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
19
|
+
const TSX_LOADER = require.resolve("tsx", { paths: [ROOT] });
|
|
20
|
+
const ORACLE_VENV_PYTHON = path.join(ROOT, ".venv-oracle", "bin", "python");
|
|
21
|
+
const PYTHON = fs.existsSync(ORACLE_VENV_PYTHON) ? ORACLE_VENV_PYTHON : "python3";
|
|
22
|
+
const ORACLE_SRC = fs.existsSync(path.join(ROOT, "temp", "usereq", "src"))
|
|
23
|
+
? path.join(ROOT, "temp", "usereq", "src")
|
|
24
|
+
: path.join(ROOT, "..", "PI-useReq", "temp", "usereq", "src");
|
|
25
|
+
const FIXTURES_DIR = path.join(ROOT, "tests", "fixtures");
|
|
26
|
+
|
|
27
|
+
export function getFixtureFiles(): string[] {
|
|
28
|
+
return fs
|
|
29
|
+
.readdirSync(FIXTURES_DIR)
|
|
30
|
+
.filter((entry) => entry.startsWith("fixture_"))
|
|
31
|
+
.map((entry) => path.join(FIXTURES_DIR, entry))
|
|
32
|
+
.sort();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @brief Executes the TypeScript CLI in a subprocess.
|
|
37
|
+
* @details Invokes `node --import tsx src/cli.ts` with the supplied arguments, cwd, and environment overrides while preserving the oracle Python interpreter binding. Runtime is dominated by child-process execution. Side effects are limited to subprocess creation.
|
|
38
|
+
* @param[in] args {string[]} CLI arguments forwarded to `src/cli.ts`.
|
|
39
|
+
* @param[in] cwd {string} Working directory for the child process.
|
|
40
|
+
* @param[in] envOverrides {NodeJS.ProcessEnv | undefined} Optional environment additions or overrides.
|
|
41
|
+
* @return {import("node:child_process").SpawnSyncReturns<string>} Captured process result.
|
|
42
|
+
*/
|
|
43
|
+
export function runNodeCli(args: string[], cwd = ROOT, envOverrides?: NodeJS.ProcessEnv) {
|
|
44
|
+
return spawnSync("node", ["--import", TSX_LOADER, path.join(ROOT, "src", "cli.ts"), ...args], {
|
|
45
|
+
cwd,
|
|
46
|
+
encoding: "utf8",
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
PI_USEREQ_PYTHON: PYTHON,
|
|
50
|
+
...envOverrides,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @brief Executes the Python oracle CLI in a subprocess.
|
|
57
|
+
* @details Invokes `python -m usereq.cli` with the supplied arguments, cwd, and environment overrides while preserving the oracle `PYTHONPATH`. Runtime is dominated by child-process execution. Side effects are limited to subprocess creation.
|
|
58
|
+
* @param[in] args {string[]} CLI arguments forwarded to the oracle module.
|
|
59
|
+
* @param[in] cwd {string} Working directory for the child process.
|
|
60
|
+
* @param[in] envOverrides {NodeJS.ProcessEnv | undefined} Optional environment additions or overrides.
|
|
61
|
+
* @return {import("node:child_process").SpawnSyncReturns<string>} Captured process result.
|
|
62
|
+
*/
|
|
63
|
+
export function runPythonCli(args: string[], cwd = ROOT, envOverrides?: NodeJS.ProcessEnv) {
|
|
64
|
+
assert.ok(fs.existsSync(ORACLE_SRC), `Python oracle source not found at ${ORACLE_SRC}`);
|
|
65
|
+
return spawnSync(PYTHON, ["-m", "usereq.cli", ...args], {
|
|
66
|
+
cwd,
|
|
67
|
+
encoding: "utf8",
|
|
68
|
+
env: {
|
|
69
|
+
...process.env,
|
|
70
|
+
PYTHONPATH: ORACLE_SRC,
|
|
71
|
+
...envOverrides,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @brief Executes inline Python code with the oracle module search path.
|
|
78
|
+
* @details Invokes the oracle interpreter with `-c`, preserves `PYTHONPATH` for `usereq` imports, and returns the captured subprocess result. Runtime is dominated by child-process execution. Side effects are limited to subprocess creation.
|
|
79
|
+
* @param[in] code {string} Inline Python program.
|
|
80
|
+
* @param[in] cwd {string} Working directory for the child process.
|
|
81
|
+
* @param[in] envOverrides {NodeJS.ProcessEnv | undefined} Optional environment additions or overrides.
|
|
82
|
+
* @return {import("node:child_process").SpawnSyncReturns<string>} Captured process result.
|
|
83
|
+
*/
|
|
84
|
+
export function runPythonInline(code: string, cwd = ROOT, envOverrides?: NodeJS.ProcessEnv) {
|
|
85
|
+
assert.ok(fs.existsSync(ORACLE_SRC), `Python oracle source not found at ${ORACLE_SRC}`);
|
|
86
|
+
return spawnSync(PYTHON, ["-c", code], {
|
|
87
|
+
cwd,
|
|
88
|
+
encoding: "utf8",
|
|
89
|
+
env: {
|
|
90
|
+
...process.env,
|
|
91
|
+
PYTHONPATH: ORACLE_SRC,
|
|
92
|
+
...envOverrides,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function createTempDir(prefix: string): string {
|
|
98
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @brief Persists the Python oracle configuration mirror for one fixture project.
|
|
103
|
+
* @details Writes `.req/config.json` with the supplied config plus the oracle-specific `guidelines-dir` field so Node and Python parity tests observe the same project metadata. Runtime is O(n) in serialized config size. Side effects include directory creation and file overwrite.
|
|
104
|
+
* @param[in] projectBase {string} Fixture project root.
|
|
105
|
+
* @param[in] config {UseReqConfig} Effective project configuration to mirror.
|
|
106
|
+
* @return {void} No return value.
|
|
107
|
+
*/
|
|
108
|
+
function writeOracleReqConfig(projectBase: string, config: UseReqConfig): void {
|
|
109
|
+
const reqDir = path.join(projectBase, ".req");
|
|
110
|
+
fs.mkdirSync(reqDir, { recursive: true });
|
|
111
|
+
const payload = {
|
|
112
|
+
"guidelines-dir": "guidelines",
|
|
113
|
+
...config,
|
|
114
|
+
};
|
|
115
|
+
fs.writeFileSync(path.join(reqDir, "config.json"), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @brief Persists both Node and Python-oracle project configs for parity tests.
|
|
120
|
+
* @details Writes `.pi-usereq/config.json` for the TypeScript CLI and `.req/config.json` for the Python oracle using the same logical payload. Runtime is O(n) in serialized config size. Side effects include directory creation and file overwrite.
|
|
121
|
+
* @param[in] projectBase {string} Fixture project root.
|
|
122
|
+
* @param[in] config {UseReqConfig} Effective project configuration to persist.
|
|
123
|
+
* @return {void} No return value.
|
|
124
|
+
*/
|
|
125
|
+
export function saveFixtureConfigs(projectBase: string, config: UseReqConfig): void {
|
|
126
|
+
saveConfig(projectBase, config);
|
|
127
|
+
writeOracleReqConfig(projectBase, config);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @brief Reads the raw persisted TypeScript project config JSON.
|
|
132
|
+
* @details Loads `.pi-usereq/config.json` without normalization so tests can inspect merge order and unknown metadata preservation exactly as written. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
|
|
133
|
+
* @param[in] projectBase {string} Fixture project root.
|
|
134
|
+
* @return {Record<string, unknown>} Parsed raw configuration object.
|
|
135
|
+
*/
|
|
136
|
+
export function readProjectConfigJson(projectBase: string): Record<string, unknown> {
|
|
137
|
+
return JSON.parse(fs.readFileSync(getProjectConfigPath(projectBase), "utf8")) as Record<string, unknown>;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @brief Writes one executable shell script for integration tests.
|
|
142
|
+
* @details Creates the parent directory when required, writes UTF-8 content, and marks the file owner-executable. Runtime is O(n) in script size. Side effects include directory creation, file overwrite, and permission changes.
|
|
143
|
+
* @param[in] filePath {string} Absolute destination path for the script.
|
|
144
|
+
* @param[in] content {string} Full script body.
|
|
145
|
+
* @return {string} Absolute script path.
|
|
146
|
+
*/
|
|
147
|
+
export function writeExecutableScript(filePath: string, content: string): string {
|
|
148
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
149
|
+
fs.writeFileSync(filePath, content, "utf8");
|
|
150
|
+
fs.chmodSync(filePath, 0o755);
|
|
151
|
+
return filePath;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function initFixtureRepo(options: {
|
|
155
|
+
fixtures?: string[];
|
|
156
|
+
docs?: Record<string, string>;
|
|
157
|
+
staticCheck?: Record<string, Array<{ module: string; cmd?: string; params?: string[] }>>;
|
|
158
|
+
} = {}): { projectBase: string; config: UseReqConfig } {
|
|
159
|
+
const projectBase = createTempDir("pi-usereq-repo-");
|
|
160
|
+
fs.mkdirSync(path.join(projectBase, "src"), { recursive: true });
|
|
161
|
+
fs.mkdirSync(path.join(projectBase, "tests"), { recursive: true });
|
|
162
|
+
fs.mkdirSync(path.join(projectBase, "guidelines"), { recursive: true });
|
|
163
|
+
fs.mkdirSync(path.join(projectBase, ...DEFAULT_DOCS_DIR.split("/")), { recursive: true });
|
|
164
|
+
fs.mkdirSync(path.join(projectBase, ".pi-usereq"), { recursive: true });
|
|
165
|
+
|
|
166
|
+
for (const fixture of options.fixtures ?? getFixtureFiles()) {
|
|
167
|
+
const destination = path.join(projectBase, "src", path.basename(fixture));
|
|
168
|
+
fs.copyFileSync(fixture, destination);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const docs = options.docs ?? {
|
|
172
|
+
"REQUIREMENTS.md": "# Requirements\n",
|
|
173
|
+
"WORKFLOW.md": "# Workflow\n",
|
|
174
|
+
"REFERENCES.md": "# References\n",
|
|
175
|
+
};
|
|
176
|
+
for (const [name, content] of Object.entries(docs)) {
|
|
177
|
+
fs.writeFileSync(path.join(projectBase, ...DEFAULT_DOCS_DIR.split("/"), name), content, "utf8");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const gitInit = spawnSync("git", ["init"], { cwd: projectBase, encoding: "utf8" });
|
|
181
|
+
assert.equal(gitInit.status, 0, gitInit.stderr);
|
|
182
|
+
spawnSync("git", ["config", "user.name", "pi-usereq"], { cwd: projectBase, encoding: "utf8" });
|
|
183
|
+
spawnSync("git", ["config", "user.email", "pi-usereq@example.com"], { cwd: projectBase, encoding: "utf8" });
|
|
184
|
+
spawnSync("git", ["add", "."], { cwd: projectBase, encoding: "utf8" });
|
|
185
|
+
const commit = spawnSync("git", ["commit", "-m", "init"], { cwd: projectBase, encoding: "utf8" });
|
|
186
|
+
assert.equal(commit.status, 0, commit.stderr);
|
|
187
|
+
const config: UseReqConfig = {
|
|
188
|
+
...getDefaultConfig(projectBase),
|
|
189
|
+
"docs-dir": DEFAULT_DOCS_DIR,
|
|
190
|
+
"tests-dir": "tests",
|
|
191
|
+
"src-dir": ["src"],
|
|
192
|
+
"static-check": options.staticCheck ?? {},
|
|
193
|
+
"enabled-tools": normalizeEnabledPiUsereqTools(undefined),
|
|
194
|
+
};
|
|
195
|
+
saveFixtureConfigs(projectBase, config);
|
|
196
|
+
|
|
197
|
+
const localVenv = path.join(projectBase, ".venv");
|
|
198
|
+
const oracleVenvRoot = path.dirname(path.dirname(ORACLE_VENV_PYTHON));
|
|
199
|
+
if (!fs.existsSync(localVenv) && fs.existsSync(oracleVenvRoot)) {
|
|
200
|
+
fs.symlinkSync(oracleVenvRoot, localVenv, "dir");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { projectBase, config };
|
|
204
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { getProjectConfigPath } from "../src/core/config.js";
|
|
6
|
+
import { LANGUAGE_TAGS } from "../src/core/find-constructs.js";
|
|
7
|
+
import { initFixtureRepo, runNodeCli, runPythonCli } from "./helpers.js";
|
|
8
|
+
|
|
9
|
+
function compareCli(args: string[], cwd: string) {
|
|
10
|
+
const python = runPythonCli(args, cwd);
|
|
11
|
+
const node = runNodeCli(args, cwd);
|
|
12
|
+
assert.equal(node.status, python.status, `exit code mismatch for ${args.join(" ")}`);
|
|
13
|
+
assert.equal(node.stdout, python.stdout, `stdout mismatch for ${args.join(" ")}`);
|
|
14
|
+
assert.equal(node.stderr, python.stderr, `stderr mismatch for ${args.join(" ")}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
test("project-scan commands match the Python oracle on a git-backed fixture repository", async (t) => {
|
|
18
|
+
const { projectBase } = initFixtureRepo({
|
|
19
|
+
staticCheck: {
|
|
20
|
+
Python: [{ module: "Command", cmd: "false" }],
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await t.test("compress", () => compareCli(["--compress"], projectBase));
|
|
25
|
+
await t.test("compress with line numbers", () => compareCli(["--compress", "--enable-line-numbers"], projectBase));
|
|
26
|
+
await t.test("find", () => {
|
|
27
|
+
const tagFilter = [...LANGUAGE_TAGS.python].sort().join("|");
|
|
28
|
+
compareCli(["--find", tagFilter, ".*"], projectBase);
|
|
29
|
+
});
|
|
30
|
+
await t.test("tokens", () => compareCli(["--tokens"], projectBase));
|
|
31
|
+
await t.test("files-static-check", () => compareCli(["--files-static-check", path.join(projectBase, "src", "fixture_python.py")], projectBase));
|
|
32
|
+
await t.test("static-check", () => compareCli(["--static-check"], projectBase));
|
|
33
|
+
await t.test("git-check", () => compareCli(["--git-check"], projectBase));
|
|
34
|
+
await t.test("docs-check", () => compareCli(["--docs-check"], projectBase));
|
|
35
|
+
await t.test("git-path", () => compareCli(["--git-path"], projectBase));
|
|
36
|
+
await t.test("get-base-path", () => compareCli(["--get-base-path"], projectBase));
|
|
37
|
+
await t.test("git-wt-name", () => {
|
|
38
|
+
let matched = false;
|
|
39
|
+
for (let attempt = 0; attempt < 3 && !matched; attempt += 1) {
|
|
40
|
+
const python = runPythonCli(["--git-wt-name"], projectBase);
|
|
41
|
+
const node = runNodeCli(["--git-wt-name"], projectBase);
|
|
42
|
+
if (python.stdout === node.stdout && python.status === node.status && python.stderr === node.stderr) {
|
|
43
|
+
matched = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
assert.ok(matched, "git-wt-name did not match Python oracle within 3 attempts");
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("git worktree create/delete wrappers produce expected worktree side effects", () => {
|
|
51
|
+
const { projectBase } = initFixtureRepo();
|
|
52
|
+
const wtName = "pi-usereq-test-wt";
|
|
53
|
+
|
|
54
|
+
const createResult = runNodeCli(["--git-wt-create", wtName], projectBase);
|
|
55
|
+
assert.equal(createResult.status, 0, createResult.stderr);
|
|
56
|
+
const worktreePath = path.join(path.dirname(projectBase), wtName);
|
|
57
|
+
assert.ok(fs.existsSync(worktreePath), "worktree path was not created");
|
|
58
|
+
assert.ok(fs.existsSync(getProjectConfigPath(worktreePath)), "project config was not copied into worktree");
|
|
59
|
+
|
|
60
|
+
const deleteResult = runNodeCli(["--git-wt-delete", wtName], projectBase);
|
|
61
|
+
assert.equal(deleteResult.status, 0, deleteResult.stderr);
|
|
62
|
+
assert.ok(!fs.existsSync(worktreePath), "worktree path was not removed");
|
|
63
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { LANGUAGE_TAGS } from "../src/core/find-constructs.js";
|
|
5
|
+
import { detectLanguage } from "../src/core/generate-markdown.js";
|
|
6
|
+
import { getFixtureFiles, runNodeCli, runPythonCli } from "./helpers.js";
|
|
7
|
+
|
|
8
|
+
function compareCli(args: string[]) {
|
|
9
|
+
const python = runPythonCli(args);
|
|
10
|
+
const node = runNodeCli(args);
|
|
11
|
+
assert.equal(node.status, python.status, `exit code mismatch for ${args.join(" ")}`);
|
|
12
|
+
assert.equal(node.stdout, python.stdout, `stdout mismatch for ${args.join(" ")}`);
|
|
13
|
+
assert.equal(node.stderr, python.stderr, `stderr mismatch for ${args.join(" ")}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
test("standalone command outputs match the Python oracle for every fixture", async (t) => {
|
|
17
|
+
const fixtures = getFixtureFiles();
|
|
18
|
+
for (const fixture of fixtures) {
|
|
19
|
+
const fileName = path.basename(fixture);
|
|
20
|
+
await t.test(`files-tokens ${fileName}`, () => {
|
|
21
|
+
compareCli(["--files-tokens", fixture]);
|
|
22
|
+
});
|
|
23
|
+
await t.test(`files-compress ${fileName}`, () => {
|
|
24
|
+
compareCli(["--files-compress", fixture]);
|
|
25
|
+
});
|
|
26
|
+
await t.test(`files-compress --enable-line-numbers ${fileName}`, () => {
|
|
27
|
+
compareCli(["--files-compress", fixture, "--enable-line-numbers"]);
|
|
28
|
+
});
|
|
29
|
+
await t.test(`files-find ${fileName}`, () => {
|
|
30
|
+
const language = detectLanguage(fixture);
|
|
31
|
+
assert.ok(language);
|
|
32
|
+
const tagFilter = [...LANGUAGE_TAGS[language!]!].sort().join("|");
|
|
33
|
+
compareCli(["--files-find", tagFilter, ".*", fixture]);
|
|
34
|
+
});
|
|
35
|
+
await t.test(`test-static-check dummy ${fileName}`, () => {
|
|
36
|
+
compareCli(["--test-static-check", "dummy", fixture]);
|
|
37
|
+
});
|
|
38
|
+
await t.test(`test-static-check pylance ${fileName}`, () => {
|
|
39
|
+
compareCli(["--test-static-check", "pylance", fixture]);
|
|
40
|
+
});
|
|
41
|
+
await t.test(`test-static-check ruff ${fileName}`, () => {
|
|
42
|
+
compareCli(["--test-static-check", "ruff", fixture]);
|
|
43
|
+
});
|
|
44
|
+
await t.test(`test-static-check command ${fileName}`, () => {
|
|
45
|
+
compareCli(["--test-static-check", "command", "false", fixture]);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { getDefaultConfig } from "../src/core/config.js";
|
|
7
|
+
import { buildRuntimePathContext, buildRuntimePathFacts } from "../src/core/path-context.js";
|
|
8
|
+
import { renderPrompt } from "../src/core/prompts.js";
|
|
9
|
+
import { ensureBundledResourcesAccessible } from "../src/core/resources.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @brief Escapes regular-expression metacharacters for literal-path assertions.
|
|
13
|
+
* @details Replaces every regex-significant character with an escaped fragment so tests can assert exact rendered path strings without interpreting path punctuation as pattern syntax. Runtime is O(n) in input length. No external state is mutated.
|
|
14
|
+
* @param[in] value {string} Literal string to escape.
|
|
15
|
+
* @return {string} Regex-safe literal fragment.
|
|
16
|
+
*/
|
|
17
|
+
function escapeRegExp(value: string): string {
|
|
18
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("installed bundled resources remain readable from the installation path", () => {
|
|
22
|
+
const resourceRoot = ensureBundledResourcesAccessible();
|
|
23
|
+
assert.ok(fs.existsSync(path.join(resourceRoot, "prompts", "analyze.md")));
|
|
24
|
+
assert.ok(fs.existsSync(path.join(resourceRoot, "templates", "Requirements_Template.md")));
|
|
25
|
+
assert.ok(fs.existsSync(path.join(resourceRoot, "guidelines", "Google_Python_Style_Guide.md")));
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("prompt rendering replaces all dynamic placeholders and adapts req tool references", () => {
|
|
29
|
+
ensureBundledResourcesAccessible();
|
|
30
|
+
const projectBase = process.cwd();
|
|
31
|
+
const config = getDefaultConfig(projectBase);
|
|
32
|
+
config["src-dir"] = ["src", "scripts", ".github/workflows"];
|
|
33
|
+
config["tests-dir"] = "tests";
|
|
34
|
+
const runtimePathFacts = buildRuntimePathFacts(buildRuntimePathContext(projectBase, config));
|
|
35
|
+
const rendered = renderPrompt("write", "Build a CLI parser", projectBase, config);
|
|
36
|
+
assert.match(rendered, /Build a CLI parser/);
|
|
37
|
+
assert.match(rendered, /req\/docs/);
|
|
38
|
+
assert.match(rendered, new RegExp(escapeRegExp(runtimePathFacts.templates_path)));
|
|
39
|
+
assert.match(rendered, /`src\/`, `scripts\/`, `\.github\/workflows\/`/);
|
|
40
|
+
assert.doesNotMatch(rendered, /%%ARGS%%|%%DOC_PATH%%|%%GUIDELINES_FILES%%|%%TEMPLATE_PATH%%|%%SRC_PATHS%%|%%TEST_PATH%%|%%EXECUTION_PATH%%|%%INSTALLATION_PATH%%|%%CONFIG_PATH%%/);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("pi.dev-aware prompts inject manifest conformance rules and API mandates when the manifest exists", () => {
|
|
44
|
+
ensureBundledResourcesAccessible();
|
|
45
|
+
const projectBase = process.cwd();
|
|
46
|
+
const config = getDefaultConfig(projectBase);
|
|
47
|
+
const rendered = renderPrompt("new", "Add pi integration guidance", projectBase, config);
|
|
48
|
+
assert.match(rendered, /docs\/pi\.dev\/agent-document-manifest\.json/);
|
|
49
|
+
assert.match(rendered, /authoritative API contract/);
|
|
50
|
+
assert.match(rendered, /new or modified pi\.dev CLI integrations MUST comply with the APIs it describes\./);
|
|
51
|
+
assert.match(rendered, /Treat manifest document paths as relative to `docs\/pi\.dev\/`/);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("pi.dev-aware prompts stay unchanged when the manifest is absent", () => {
|
|
55
|
+
ensureBundledResourcesAccessible();
|
|
56
|
+
const projectBase = fs.mkdtempSync(path.join(os.tmpdir(), "pi-usereq-prompts-"));
|
|
57
|
+
try {
|
|
58
|
+
const config = getDefaultConfig(projectBase);
|
|
59
|
+
const rendered = renderPrompt("new", "Add pi integration guidance", projectBase, config);
|
|
60
|
+
assert.doesNotMatch(rendered, /docs\/pi\.dev\/agent-document-manifest\.json/);
|
|
61
|
+
assert.doesNotMatch(rendered, /authoritative API contract/);
|
|
62
|
+
assert.doesNotMatch(rendered, /Treat manifest document paths as relative to `docs\/pi\.dev\/`/);
|
|
63
|
+
} finally {
|
|
64
|
+
fs.rmSync(projectBase, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @brief Loads the npm release workflow YAML for structural assertions.
|
|
8
|
+
* @details Resolves the repository-local workflow path from the current process working directory and returns the UTF-8 document unchanged so tests can assert release-gating and publication directives deterministically. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
|
|
9
|
+
* @return {string} Raw workflow YAML text.
|
|
10
|
+
* @satisfies TST-039
|
|
11
|
+
*/
|
|
12
|
+
function readReleaseWorkflow(): string {
|
|
13
|
+
return fs.readFileSync(
|
|
14
|
+
path.join(process.cwd(), ".github", "workflows", "release-npm.yml"),
|
|
15
|
+
"utf8",
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @brief Describes the package manifest fields asserted by npm release tests.
|
|
21
|
+
* @details Constrains the parsed `package.json` shape to the publication identity and provenance metadata required by the release workflow tests. The interface is compile-time only and introduces no runtime side effects.
|
|
22
|
+
*/
|
|
23
|
+
interface PackageManifest {
|
|
24
|
+
name?: unknown;
|
|
25
|
+
repository?: {
|
|
26
|
+
type?: unknown;
|
|
27
|
+
url?: unknown;
|
|
28
|
+
};
|
|
29
|
+
bugs?: {
|
|
30
|
+
url?: unknown;
|
|
31
|
+
};
|
|
32
|
+
homepage?: unknown;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @brief Loads the repository package manifest for npm publication assertions.
|
|
37
|
+
* @details Resolves `package.json` from the current process working directory, parses the UTF-8 JSON document, and returns the manifest object so tests can assert publication identity and provenance metadata deterministically. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
|
|
38
|
+
* @return {PackageManifest} Parsed package manifest.
|
|
39
|
+
* @satisfies TST-042, TST-044
|
|
40
|
+
*/
|
|
41
|
+
function readPackageManifest(): PackageManifest {
|
|
42
|
+
return JSON.parse(
|
|
43
|
+
fs.readFileSync(path.join(process.cwd(), "package.json"), "utf8"),
|
|
44
|
+
) as PackageManifest;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @brief Asserts the fixed npm package name used for publication.
|
|
49
|
+
* @details Loads `package.json` and verifies that the published package name remains `pi-usereq`, preserving the canonical npm package identity. Runtime is O(n) in file size. Side effects are limited to filesystem reads through `readPackageManifest`.
|
|
50
|
+
* @return {void} No return value.
|
|
51
|
+
* @satisfies TST-042
|
|
52
|
+
*/
|
|
53
|
+
function assertFixedPackageName(): void {
|
|
54
|
+
const manifest = readPackageManifest();
|
|
55
|
+
|
|
56
|
+
assert.equal(manifest.name, "pi-usereq");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @brief Asserts canonical GitHub provenance metadata in `package.json`.
|
|
61
|
+
* @details Loads `package.json` and verifies that repository, issues, and homepage URLs remain aligned to the canonical GitHub repository required by npm provenance validation. Runtime is O(n) in file size. Side effects are limited to filesystem reads through `readPackageManifest`.
|
|
62
|
+
* @return {void} No return value.
|
|
63
|
+
* @satisfies TST-044
|
|
64
|
+
*/
|
|
65
|
+
function assertCanonicalPackageProvenanceMetadata(): void {
|
|
66
|
+
const manifest = readPackageManifest();
|
|
67
|
+
|
|
68
|
+
assert.deepEqual(manifest.repository, {
|
|
69
|
+
type: "git",
|
|
70
|
+
url: "git+https://github.com/Ogekuri/PI-useReq.git",
|
|
71
|
+
});
|
|
72
|
+
assert.deepEqual(manifest.bugs, {
|
|
73
|
+
url: "https://github.com/Ogekuri/PI-useReq/issues",
|
|
74
|
+
});
|
|
75
|
+
assert.equal(manifest.homepage, "https://github.com/Ogekuri/PI-useReq#readme");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
test(
|
|
79
|
+
"release workflow keeps the current tag trigger and gates release work on origin/master ancestry",
|
|
80
|
+
() => {
|
|
81
|
+
const workflow = readReleaseWorkflow();
|
|
82
|
+
|
|
83
|
+
assert.match(workflow, /name:\s+Release \(npm\)/);
|
|
84
|
+
assert.match(workflow, /tags:\s*\n\s*-\s*'v\[0-9\]\+\.\[0-9\]\+\.\[0-9\]\+'/);
|
|
85
|
+
assert.ok(workflow.includes("check-branch:"));
|
|
86
|
+
assert.ok(workflow.includes("is_master: ${{ steps.check.outputs.is_master }}"));
|
|
87
|
+
assert.ok(workflow.includes("git fetch origin master"));
|
|
88
|
+
assert.ok(workflow.includes('grep -q "origin/master"'));
|
|
89
|
+
assert.ok(
|
|
90
|
+
workflow.includes("if: needs.check-branch.outputs.is_master == 'true'"),
|
|
91
|
+
);
|
|
92
|
+
assert.ok(workflow.includes("build-release:"));
|
|
93
|
+
},
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
test(
|
|
97
|
+
"release workflow installs dependencies, publishes to npm, and creates the GitHub release",
|
|
98
|
+
() => {
|
|
99
|
+
const workflow = readReleaseWorkflow();
|
|
100
|
+
|
|
101
|
+
assert.ok(workflow.includes("uses: actions/setup-node@v4"));
|
|
102
|
+
assert.ok(workflow.includes("registry-url: 'https://registry.npmjs.org'"));
|
|
103
|
+
assert.ok(workflow.includes("run: npm ci"));
|
|
104
|
+
assert.ok(workflow.includes("run: npm pkg delete private"));
|
|
105
|
+
assert.ok(
|
|
106
|
+
workflow.includes("run: npm publish --provenance --access public"),
|
|
107
|
+
);
|
|
108
|
+
assert.ok(workflow.includes("NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}"));
|
|
109
|
+
assert.ok(
|
|
110
|
+
workflow.includes(
|
|
111
|
+
"uses: mikepenz/release-changelog-builder-action@v6",
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
assert.ok(workflow.includes("uses: softprops/action-gh-release@v2"));
|
|
115
|
+
assert.ok(workflow.includes("draft: false"));
|
|
116
|
+
assert.ok(workflow.includes("prerelease: false"));
|
|
117
|
+
assert.ok(
|
|
118
|
+
workflow.includes(
|
|
119
|
+
"body: ${{ steps.build_changelog.outputs.changelog }}",
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
test(
|
|
126
|
+
"package manifest keeps the npm publication name fixed to pi-usereq",
|
|
127
|
+
assertFixedPackageName,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
test(
|
|
131
|
+
"package manifest keeps canonical repository, bugs, and homepage metadata for npm provenance",
|
|
132
|
+
assertCanonicalPackageProvenanceMetadata,
|
|
133
|
+
);
|