better-dsh 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cordis.patch.yml +1 -1
- package/docs/50_test-reports/2026-09-06-write/345/267/245/345/205/267sandbox/345/215/207/347/272/247/351/200/217/344/274/240bug/345/244/215/345/217/221/345/217/212/346/214/202/350/265/267-/344/272/213/344/273/266/346/212/245/345/221/212.md +176 -0
- package/docs/50_test-reports/2026-09-08-hashline-edit-E_RANGE_UNVERIFIED/350/267/250/350/275/256/344/274/232/350/257/235/351/224/256/345/244/261/346/225/210-/350/257/212/346/226/255/346/212/245/345/221/212.md +226 -0
- package/docs/50_test-reports/2026-09-11-control-prompt-into-eval-description/345/256/236/346/265/213/346/212/245/345/221/212.md +222 -0
- package/docs/50_test-reports/2026-09-12-fs-scheme-resolution-/345/256/236/346/265/213/346/212/245/345/221/212.md +81 -0
- package/docs/50_test-reports/2026-09-12-url-schemes-grammar-matrix/344/270/216catalog-centralize-/345/256/236/346/265/213/346/212/245/345/221/212.md +234 -0
- package/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-design/351/252/214/350/257/201/346/212/245/345/221/212.md +160 -0
- package/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-/345/256/236/346/265/213/345/211/247/346/234/254.md +44 -0
- package/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-/345/256/236/346/265/213/346/212/245/345/221/212.md +89 -0
- package/docs/50_test-reports/2026-09-12-url-schemes-/345/205/255scheme/345/206/222/347/203/237/344/270/216/350/276/271/347/225/214/345/256/236/346/265/213/346/212/245/345/221/212.md +198 -0
- package/docs/50_test-reports/2026-09-13-hashline-off/344/270/213scheme/345/217/257/350/276/276/346/200/247/345/267/245/345/205/267/351/235/242/344/270/215/345/257/271/347/247/260-/345/256/236/346/265/213/346/212/245/345/221/212.md +246 -0
- package/docs/50_test-reports/2026-09-13-preact-ui-shell/345/256/236/346/265/213/346/212/245/345/221/212.md +50 -0
- package/docs/50_test-reports/2026-09-14-4999-skill/346/270/205/345/215/225/344/270/216lsp-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +63 -0
- package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-local-test-report.md +44 -0
- package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-report.md +110 -0
- package/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
- package/docs/50_test-reports/v0.2.3b-hashline-content-locator/345/256/236/346/265/213/346/212/245/345/221/212.md +73 -0
- package/docs/50_test-reports/v0.2.3c-mobile-wave/345/256/236/346/265/213/346/212/245/345/221/212.md +47 -0
- package/docs/50_test-reports/v0.2.4-ios-focus-zoom-suppression/345/256/236/346/265/213/346/212/245/345/221/212.md +158 -0
- package/docs/specs/agent/spec.md +54 -0
- package/docs/specs/ast/spec.md +34 -0
- package/docs/specs/compaction-recall/spec.md +46 -0
- package/docs/specs/ctx/spec.md +107 -0
- package/docs/specs/dsh/spec.md +47 -0
- package/docs/specs/dvc/spec.md +87 -0
- package/docs/specs/escalation-guidance/spec.md +44 -0
- package/docs/specs/fs-scheme-resolution/spec.md +37 -0
- package/docs/specs/hash-edit/spec.md +41 -0
- package/docs/specs/http-read/spec.md +73 -0
- package/docs/specs/kernel-provisioning/spec.md +53 -0
- package/docs/specs/lsp/spec.md +121 -0
- package/docs/specs/mobile-layout/spec.md +108 -0
- package/docs/specs/model-failover/spec.md +20 -0
- package/docs/specs/preact-ui-shell/spec.md +22 -0
- package/docs/specs/repl-dispatch-resilience/spec.md +21 -0
- package/docs/specs/skill/spec.md +58 -0
- package/docs/specs/tool-surface/spec.md +222 -0
- package/docs/specs/url-schema/spec.md +148 -0
- package/docs/specs/web-trust-fence/spec.md +43 -0
- package/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
- package/dsh-docs/AGENTS.md +75 -0
- package/dsh-docs/agent-lifecycle.md +84 -0
- package/dsh-docs/agent-lifecycle.zh.md +86 -0
- package/dsh-docs/api-gateway.md +164 -0
- package/dsh-docs/api-gateway.zh.md +164 -0
- package/dsh-docs/architecture.md +150 -0
- package/dsh-docs/architecture.zh.md +154 -0
- package/dsh-docs/capability-seams.md +543 -0
- package/dsh-docs/capability-seams.zh.md +545 -0
- package/dsh-docs/config-catalog.md +3473 -0
- package/dsh-docs/config-catalog.zh.md +3474 -0
- package/dsh-docs/cookbook/adding-a-package.md +117 -0
- package/dsh-docs/cookbook/adding-a-package.zh.md +119 -0
- package/dsh-docs/cookbook/adding-a-remote-api.md +197 -0
- package/dsh-docs/cookbook/adding-a-remote-api.zh.md +197 -0
- package/dsh-docs/cookbook/adding-a-session-format-version.md +109 -0
- package/dsh-docs/cookbook/adding-a-session-format-version.zh.md +109 -0
- package/dsh-docs/cookbook/adding-a-settings-card.md +102 -0
- package/dsh-docs/cookbook/adding-a-settings-card.zh.md +102 -0
- package/dsh-docs/cookbook/adding-a-tool.md +101 -0
- package/dsh-docs/cookbook/adding-a-tool.zh.md +103 -0
- package/dsh-docs/cookbook/adding-a-vendored-package.md +59 -0
- package/dsh-docs/cookbook/adding-a-vendored-package.zh.md +59 -0
- package/dsh-docs/cookbook/adding-an-llm-adapter.md +43 -0
- package/dsh-docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
- package/dsh-docs/cookbook/extension-cookbook.md +132 -0
- package/dsh-docs/cookbook/extension-cookbook.zh.md +136 -0
- package/dsh-docs/cookbook/maintaining-dsh-code-review.md +64 -0
- package/dsh-docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
- package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
- package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
- package/dsh-docs/cordis-api/context.md +364 -0
- package/dsh-docs/cordis-api/context.zh.md +366 -0
- package/dsh-docs/cordis-api/events.md +207 -0
- package/dsh-docs/cordis-api/events.zh.md +209 -0
- package/dsh-docs/cordis-api/fiber.md +375 -0
- package/dsh-docs/cordis-api/fiber.zh.md +377 -0
- package/dsh-docs/cordis-api/inherited.md +39 -0
- package/dsh-docs/cordis-api/registry.md +152 -0
- package/dsh-docs/cordis-api/registry.zh.md +154 -0
- package/dsh-docs/cordis-api/service.md +102 -0
- package/dsh-docs/cordis-api/service.zh.md +104 -0
- package/dsh-docs/cordis-primer.md +45 -0
- package/dsh-docs/cordis-primer.zh.md +51 -0
- package/dsh-docs/cordis-tutorial/01-first-plugin.md +95 -0
- package/dsh-docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
- package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
- package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
- package/dsh-docs/cordis-tutorial/03-services.md +98 -0
- package/dsh-docs/cordis-tutorial/03-services.zh.md +98 -0
- package/dsh-docs/cordis-tutorial/04-events.md +144 -0
- package/dsh-docs/cordis-tutorial/04-events.zh.md +144 -0
- package/dsh-docs/cordis-tutorial/05-config.md +84 -0
- package/dsh-docs/cordis-tutorial/05-config.zh.md +84 -0
- package/dsh-docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
- package/dsh-docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
- package/dsh-docs/cordis-tutorial/07-into-the-harness.md +108 -0
- package/dsh-docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
- package/dsh-docs/cordis-tutorial/index.md +60 -0
- package/dsh-docs/cordis-tutorial/index.zh.md +62 -0
- package/dsh-docs/deepseek-llm-api-wire-extensions.md +163 -0
- package/dsh-docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
- package/dsh-docs/defensive-patterns.md +33 -0
- package/dsh-docs/defensive-patterns.zh.md +35 -0
- package/dsh-docs/development.md +167 -0
- package/dsh-docs/development.zh.md +173 -0
- package/dsh-docs/event-producer-consumer.md +86 -0
- package/dsh-docs/event-producer-consumer.zh.md +88 -0
- package/dsh-docs/glossary.md +45 -0
- package/dsh-docs/glossary.zh.md +45 -0
- package/dsh-docs/graph-atlas.md +22 -0
- package/dsh-docs/graph-atlas.zh.md +24 -0
- package/dsh-docs/i18n/README.md +60 -0
- package/dsh-docs/i18n/README.zh.md +62 -0
- package/dsh-docs/i18n/style-samples.md +87 -0
- package/dsh-docs/i18n/terminology.md +214 -0
- package/dsh-docs/i18n/translation-prompt.md +263 -0
- package/dsh-docs/i18n/translation-rules.md +69 -0
- package/dsh-docs/i18n/translation-rules.zh.md +69 -0
- package/dsh-docs/module-graph.md +1411 -0
- package/dsh-docs/module-graph.zh.md +1413 -0
- package/dsh-docs/persistence-catalog.md +1075 -0
- package/dsh-docs/persistence-catalog.zh.md +1077 -0
- package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
- package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
- package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
- package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
- package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
- package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
- package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
- package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
- package/dsh-docs/postmortem/README.md +18 -0
- package/dsh-docs/postmortem/README.zh.md +18 -0
- package/dsh-docs/rescope.md +53 -0
- package/dsh-docs/rescope.zh.md +53 -0
- package/dsh-docs/session-format-status.md +47 -0
- package/dsh-docs/session-format-status.zh.md +47 -0
- package/dsh-docs/subsystems/README.md +61 -0
- package/dsh-docs/subsystems/README.zh.md +61 -0
- package/dsh-docs/subsystems/agent-team.md +207 -0
- package/dsh-docs/subsystems/agent-team.zh.md +207 -0
- package/dsh-docs/subsystems/approval.md +170 -0
- package/dsh-docs/subsystems/approval.zh.md +170 -0
- package/dsh-docs/subsystems/attachment.md +351 -0
- package/dsh-docs/subsystems/attachment.zh.md +351 -0
- package/dsh-docs/subsystems/client-modules.md +168 -0
- package/dsh-docs/subsystems/client-modules.zh.md +168 -0
- package/dsh-docs/subsystems/client-resources.md +91 -0
- package/dsh-docs/subsystems/client-resources.zh.md +91 -0
- package/dsh-docs/subsystems/code-runtime.md +195 -0
- package/dsh-docs/subsystems/code-runtime.zh.md +195 -0
- package/dsh-docs/subsystems/commands.md +219 -0
- package/dsh-docs/subsystems/commands.zh.md +219 -0
- package/dsh-docs/subsystems/compaction.md +238 -0
- package/dsh-docs/subsystems/compaction.zh.md +238 -0
- package/dsh-docs/subsystems/conversation.md +258 -0
- package/dsh-docs/subsystems/conversation.zh.md +258 -0
- package/dsh-docs/subsystems/core.md +1209 -0
- package/dsh-docs/subsystems/core.zh.md +1219 -0
- package/dsh-docs/subsystems/credentials.md +329 -0
- package/dsh-docs/subsystems/credentials.zh.md +329 -0
- package/dsh-docs/subsystems/extensions.md +382 -0
- package/dsh-docs/subsystems/extensions.zh.md +382 -0
- package/dsh-docs/subsystems/feedback.md +266 -0
- package/dsh-docs/subsystems/feedback.zh.md +266 -0
- package/dsh-docs/subsystems/filesystem.md +505 -0
- package/dsh-docs/subsystems/filesystem.zh.md +505 -0
- package/dsh-docs/subsystems/goal.md +277 -0
- package/dsh-docs/subsystems/goal.zh.md +277 -0
- package/dsh-docs/subsystems/invariants.md +88 -0
- package/dsh-docs/subsystems/invariants.zh.md +88 -0
- package/dsh-docs/subsystems/jobs.md +290 -0
- package/dsh-docs/subsystems/jobs.zh.md +290 -0
- package/dsh-docs/subsystems/llm-streaming.md +1080 -0
- package/dsh-docs/subsystems/llm-streaming.zh.md +1086 -0
- package/dsh-docs/subsystems/lsp.md +202 -0
- package/dsh-docs/subsystems/lsp.zh.md +202 -0
- package/dsh-docs/subsystems/permission-presets.md +131 -0
- package/dsh-docs/subsystems/permission-presets.zh.md +131 -0
- package/dsh-docs/subsystems/persistence.md +395 -0
- package/dsh-docs/subsystems/persistence.zh.md +395 -0
- package/dsh-docs/subsystems/plan.md +87 -0
- package/dsh-docs/subsystems/plan.zh.md +87 -0
- package/dsh-docs/subsystems/sandbox.md +220 -0
- package/dsh-docs/subsystems/sandbox.zh.md +220 -0
- package/dsh-docs/subsystems/schedule.md +192 -0
- package/dsh-docs/subsystems/schedule.zh.md +192 -0
- package/dsh-docs/subsystems/scope.md +59 -0
- package/dsh-docs/subsystems/scope.zh.md +59 -0
- package/dsh-docs/subsystems/session-projection.md +354 -0
- package/dsh-docs/subsystems/session-projection.zh.md +354 -0
- package/dsh-docs/subsystems/session-query.md +509 -0
- package/dsh-docs/subsystems/session-query.zh.md +509 -0
- package/dsh-docs/subsystems/session-reference.md +219 -0
- package/dsh-docs/subsystems/session-reference.zh.md +219 -0
- package/dsh-docs/subsystems/session-telemetry.md +194 -0
- package/dsh-docs/subsystems/session-telemetry.zh.md +194 -0
- package/dsh-docs/subsystems/session-title.md +204 -0
- package/dsh-docs/subsystems/session-title.zh.md +204 -0
- package/dsh-docs/subsystems/session.md +1155 -0
- package/dsh-docs/subsystems/session.zh.md +1159 -0
- package/dsh-docs/subsystems/settings.md +405 -0
- package/dsh-docs/subsystems/settings.zh.md +405 -0
- package/dsh-docs/subsystems/shell.md +303 -0
- package/dsh-docs/subsystems/shell.zh.md +303 -0
- package/dsh-docs/subsystems/sidebar-right.md +148 -0
- package/dsh-docs/subsystems/sidebar-right.zh.md +148 -0
- package/dsh-docs/subsystems/skills.md +354 -0
- package/dsh-docs/subsystems/skills.zh.md +354 -0
- package/dsh-docs/subsystems/slots.md +175 -0
- package/dsh-docs/subsystems/slots.zh.md +175 -0
- package/dsh-docs/subsystems/spill.md +117 -0
- package/dsh-docs/subsystems/spill.zh.md +117 -0
- package/dsh-docs/subsystems/storage.md +260 -0
- package/dsh-docs/subsystems/storage.zh.md +260 -0
- package/dsh-docs/subsystems/subagent.md +766 -0
- package/dsh-docs/subsystems/subagent.zh.md +770 -0
- package/dsh-docs/subsystems/subprocess.md +324 -0
- package/dsh-docs/subsystems/subprocess.zh.md +324 -0
- package/dsh-docs/subsystems/system-prompt.md +220 -0
- package/dsh-docs/subsystems/system-prompt.zh.md +220 -0
- package/dsh-docs/subsystems/terminal.md +184 -0
- package/dsh-docs/subsystems/terminal.zh.md +184 -0
- package/dsh-docs/subsystems/todo.md +32 -0
- package/dsh-docs/subsystems/todo.zh.md +32 -0
- package/dsh-docs/subsystems/token-meter.md +105 -0
- package/dsh-docs/subsystems/token-meter.zh.md +105 -0
- package/dsh-docs/subsystems/tools.md +720 -0
- package/dsh-docs/subsystems/tools.zh.md +720 -0
- package/dsh-docs/subsystems/typert.md +343 -0
- package/dsh-docs/subsystems/typert.zh.md +343 -0
- package/dsh-docs/subsystems/user-questions.md +178 -0
- package/dsh-docs/subsystems/user-questions.zh.md +178 -0
- package/dsh-docs/subsystems/web-client.md +95 -0
- package/dsh-docs/subsystems/web-client.zh.md +95 -0
- package/dsh-docs/subsystems/web-server.md +154 -0
- package/dsh-docs/subsystems/web-server.zh.md +154 -0
- package/dsh-docs/subsystems/web.md +206 -0
- package/dsh-docs/subsystems/web.zh.md +206 -0
- package/dsh-docs/subsystems/webhook.md +70 -0
- package/dsh-docs/subsystems/webhook.zh.md +70 -0
- package/dsh-docs/subsystems/workflow.md +278 -0
- package/dsh-docs/subsystems/workflow.zh.md +278 -0
- package/dsh-docs/subsystems/workspace.md +321 -0
- package/dsh-docs/subsystems/workspace.zh.md +321 -0
- package/dsh-docs/testing.md +54 -0
- package/dsh-docs/testing.zh.md +54 -0
- package/dsh-docs/tool-catalog.md +2225 -0
- package/dsh-docs/tool-catalog.zh.md +2233 -0
- package/dsh-docs/tool-execution-pipeline.md +62 -0
- package/dsh-docs/tool-execution-pipeline.zh.md +64 -0
- package/dsh-docs/user/develop/basic/config.md +106 -0
- package/dsh-docs/user/develop/basic/config.zh.md +106 -0
- package/dsh-docs/user/develop/basic/index.md +144 -0
- package/dsh-docs/user/develop/basic/index.zh.md +144 -0
- package/dsh-docs/user/develop/basic/publish.md +183 -0
- package/dsh-docs/user/develop/basic/publish.zh.md +183 -0
- package/dsh-docs/user/develop/basic/tool.md +52 -0
- package/dsh-docs/user/develop/basic/tool.zh.md +52 -0
- package/dsh-docs/user/develop/framework/events.md +143 -0
- package/dsh-docs/user/develop/framework/events.zh.md +143 -0
- package/dsh-docs/user/develop/framework/index.md +137 -0
- package/dsh-docs/user/develop/framework/index.zh.md +137 -0
- package/dsh-docs/user/develop/framework/service.md +148 -0
- package/dsh-docs/user/develop/framework/service.zh.md +150 -0
- package/dsh-docs/user/develop/practice/dynamic-cordis.md +15 -0
- package/dsh-docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
- package/dsh-docs/user/develop/practice/index.md +155 -0
- package/dsh-docs/user/develop/practice/index.zh.md +155 -0
- package/dsh-docs/user/develop/practice/llm-adapter.md +189 -0
- package/dsh-docs/user/develop/practice/llm-adapter.zh.md +189 -0
- package/dsh-docs/user/guide/github-review.md +102 -0
- package/dsh-docs/user/guide/github-review.zh.md +102 -0
- package/dsh-docs/user/guide/index.md +30 -0
- package/dsh-docs/user/guide/index.zh.md +30 -0
- package/dsh-docs/user/guide/mcp-memory.md +101 -0
- package/dsh-docs/user/guide/mcp-memory.zh.md +101 -0
- package/dsh-docs/user/guide/network-proxy.md +85 -0
- package/dsh-docs/user/guide/network-proxy.zh.md +85 -0
- package/dsh-docs/user/guide/providers.md +190 -0
- package/dsh-docs/user/guide/providers.zh.md +190 -0
- package/dsh-docs/user/guide/python-sdk.md +150 -0
- package/dsh-docs/user/guide/python-sdk.zh.md +150 -0
- package/dsh-docs/user/guide/schedule.md +21 -0
- package/dsh-docs/user/guide/schedule.zh.md +21 -0
- package/dsh-docs/user/index.md +11 -0
- package/dsh-docs/user/index.zh.md +11 -0
- package/dsh-docs/web-styling.md +29 -0
- package/dsh-docs/web-styling.zh.md +29 -0
- package/eval-description.md +33 -0
- package/lib/client/index.js +327 -88
- package/lib/fs-aware/sandbox-plugin.d.ts +71 -0
- package/lib/fs-aware/sandbox-plugin.js +249 -0
- package/lib/index.d.ts +22 -22
- package/lib/index.js +3095 -3204
- package/lib/lsp-server-registry-DkaYmTwt.js +972 -0
- package/lib/lsp-server-registry-_hk-Wcia.js +3 -0
- package/lib/py-sdk-Chvy92MB.js +178 -0
- package/lib/py-sdk.d.ts +19 -2
- package/lib/py-sdk.js +2 -2
- package/lib/wrap-JFjcWwZf.js +747 -0
- package/package.json +9 -3
- package/url-schemes-instruction.md +22 -0
- package/control-prompt.md +0 -37
- package/docs/50_test-reports/v0.1.8d_artifacts/README.md +0 -138
- package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
- package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +0 -592
- package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
- package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
- package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +0 -5
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
- package/docs/60_exploration-and-research/cordis-research.md +0 -350
- package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +0 -186
- package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +0 -310
- package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +0 -300
- package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +0 -324
- package/docs/60_exploration-and-research/web-frontend-composability-research.md +0 -191
- package/docs/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +0 -110
- package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +0 -14
- package/docs/adr/0002-masking-is-presentation-only.md +0 -15
- package/docs/plans/A2A-messaging-channel-test-archive.md +0 -256
- package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +0 -137
- package/docs/plans/dashr-blueprint-review.md +0 -201
- package/docs/plans/dashr-blueprint.md +0 -561
- package/docs/plans/dashr-compaction-window-and-archive.md +0 -307
- package/docs/plans/dashr-profile-layer-feasibility.md +0 -367
- package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +0 -171
- package/docs/plans/dashr-security-sandbox-analysis.md +0 -187
- package/docs/plans/dashr-surface-invariant-and-omp-imports.md +0 -97
- package/docs/plans/ipython-kernel-interactive-interface-test-report.md +0 -152
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +0 -146
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +0 -50
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +0 -79
- package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +0 -138
- package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +0 -161
- package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +0 -109
- package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +0 -50
- package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +0 -113
- package/docs/plans/recallable-compaction.md +0 -147
- package/docs/plans/spike-tag-repro.mjs +0 -102
- package/docs/plans/upstream-analysis.md +0 -128
- package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -142
- package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -193
- package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -96
- package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -127
- package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -150
- package/docs/v0.1.8d_artifacts/README.md +0 -138
- package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
- package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
- package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
- package/docs/v0.1.8d_artifacts/functions.json +0 -592
- package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
- package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
- package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
- package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
- package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
- package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -224
- package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -168
- package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -123
- package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
- package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
- package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
- package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
- package/docs/v0.2.0b_artifacts/hashline-probe.md +0 -5
- package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
- package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
- package/docs/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
- package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
- package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -110
- package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -86
- package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -66
- package/lib/py-sdk-BCaOGYz7.d.ts +0 -125
- package/lib/py-sdk-CbgYiX8O.js +0 -691
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# ctx Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Let the model read a curated, read-only snapshot of its calling environment via `ctx://` URLs — small, static, agent-derived facts (who am I, what model, what cwd) addressable like any other resource. This replaces the v0.1.8c design that mapped `ctx://` onto persistent-kernel variables; see design.md D4 for why that semantics was wrong (the kernel namespace is the model's own REPL scratchpad, not its environment).
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
### Requirement: Curated snapshot keys
|
|
10
|
+
The system SHALL resolve `ctx://session` as the recallable-context statistics snapshot: the prepared default face SHALL carry the session header (absorbing the former identity fields `id`/`status`/`origin`/`delegationDepth`), storage facts, totals using native DSH field names, per-compaction segments plus a `live` tail segment, the inline compactions manifest (label, checkpoint_seq, compactionId, shadowedRange, shadowedItems, shadowedTokenCount, `replaces_checkpoint`, and an 8-section × ≤100-char summary preview per episode), and a `system_prompt` info card. The canonical face (see `:raw`) SHALL be the full session transcript. The first-level keys `model` and `cwd` SHALL be removed — their information SHALL appear only as info-card fields inside the snapshot. Any other first-level key SHALL return the structured `CTX_UNKNOWN_KEY` error listing the known keys and sub-paths.
|
|
11
|
+
|
|
12
|
+
#### Scenario: Reading session identity
|
|
13
|
+
- **WHEN** the model reads `ctx://session` from a delegated subagent session
|
|
14
|
+
- **THEN** the snapshot header carries the agent id, status, origin, and delegation depth
|
|
15
|
+
|
|
16
|
+
#### Scenario: Reading the model configuration
|
|
17
|
+
- **WHEN** the model reads `ctx://session`
|
|
18
|
+
- **THEN** the snapshot info card carries the provider, model, and maxTokens of the calling agent's request options
|
|
19
|
+
|
|
20
|
+
#### Scenario: Reading the working directory
|
|
21
|
+
- **WHEN** the model reads `ctx://session`
|
|
22
|
+
- **THEN** the session's creation working directory appears as an info-card field, not as a separate key
|
|
23
|
+
|
|
24
|
+
#### Scenario: Unknown key
|
|
25
|
+
- **WHEN** the model reads `ctx://<other key>`
|
|
26
|
+
- **THEN** the system returns the structured `CTX_UNKNOWN_KEY` error naming the known keys and sub-paths
|
|
27
|
+
|
|
28
|
+
### Requirement: Bare listing
|
|
29
|
+
The system SHALL let bare `ctx://` return the roster of available resources and usage entry points (one per line), including the `session` root, the sub-path grammar pointer (naming the composite `:raw:N-M` form), and the `transcript`/`compactions`/`user_prompts`/`tool_calls`/`agent_responses`/`thinking`/`system`/`injections` sub-paths; the static portion SHALL not require a live agent, and the roster SHALL stay within its line budget (its previous size plus the three collection entries).
|
|
30
|
+
|
|
31
|
+
#### Scenario: Listing keys
|
|
32
|
+
- **WHEN** the model reads bare `ctx://`
|
|
33
|
+
- **THEN** the system returns the roster naming `session`, its sub-paths (including `thinking` and `system`), and the addressing-grammar pointer
|
|
34
|
+
|
|
35
|
+
### Requirement: Snapshot requires a live agent
|
|
36
|
+
The system SHALL read every snapshot value from the calling agent supplied in the resolver env; an env with no live agent returns the structured `CTX_NO_AGENT` error on any value read.
|
|
37
|
+
|
|
38
|
+
#### Scenario: No agent in the context
|
|
39
|
+
- **WHEN** a ctx:// value read runs with no live agent in the resolver env
|
|
40
|
+
- **THEN** the system returns the structured `CTX_NO_AGENT` error
|
|
41
|
+
|
|
42
|
+
### Requirement: ctx is strictly read-only
|
|
43
|
+
The system SHALL reject every write to `ctx://` with the structured `URL_READ_ONLY` error explaining the scheme is a curated read-only snapshot. There is no kernel-variable write channel and no variable mutation of any kind.
|
|
44
|
+
|
|
45
|
+
#### Scenario: Writing to a snapshot key
|
|
46
|
+
- **WHEN** the model writes to `ctx://<any key>`
|
|
47
|
+
- **THEN** the system returns the structured `URL_READ_ONLY` error and changes nothing
|
|
48
|
+
|
|
49
|
+
### Requirement: Session sub-path grammar
|
|
50
|
+
The system SHALL resolve `ctx://session/…` sub-paths: `transcript` (full transcript), `compactions` (manifest), `compactions[<label|ordinal>]` (the episode summary, 8 sections verbatim), `user_prompts[<n|seq>]`, `tool_calls[<n|seq>]`, `agent_responses[<n|seq>]`, `thinking[<n|seq>]` (reasoning blocks), and `system[<n|seq>]` (system messages). The former `compactions[<label|n>]/original` sub-path SHALL be removed — it was identical to `:raw` and is superseded by composing the `:raw` / `:N-M` selectors directly on the episode; a path using it SHALL be rejected with the structured `CTX_BAD_PATH` error echoing the URL. Bracket resolution SHALL match the label (the element's immutable seq coordinate) exactly first, and SHALL fall back to the 0-based ordinal on miss. The system SHALL support `:raw` and line windows (`:N`, `:N-M`, `:N+K`, `:N-`, comma-separated ranges) on every resolved resource, and the composite `:raw:<lines>` form SHALL be valid everywhere and SHALL equal `:<lines>` (the `:raw` prefix is redundant in a line-window context but MUST parse).
|
|
51
|
+
|
|
52
|
+
#### Scenario: Drilling into a compaction episode by label
|
|
53
|
+
- **WHEN** the model reads `ctx://session/compactions[221217]`
|
|
54
|
+
- **THEN** the system returns that episode's structured summary (all 8 sections verbatim)
|
|
55
|
+
|
|
56
|
+
#### Scenario: Ordinal fallback
|
|
57
|
+
- **WHEN** the model reads `ctx://session/compactions[0]` and no episode carries the label `0`
|
|
58
|
+
- **THEN** the system returns the first-recorded episode (0-based)
|
|
59
|
+
|
|
60
|
+
#### Scenario: Composite raw selector
|
|
61
|
+
- **WHEN** the model reads `ctx://session/compactions[221217]:raw:500-560`
|
|
62
|
+
- **THEN** the system returns the same lines as `ctx://session/compactions[221217]:500-560`
|
|
63
|
+
|
|
64
|
+
#### Scenario: Removed /original sub-path
|
|
65
|
+
- **WHEN** the model reads `ctx://session/compactions[221217]/original`
|
|
66
|
+
- **THEN** the system returns the structured `CTX_BAD_PATH` error echoing the URL and naming the `:raw` / `:N-M` selectors as the replacement
|
|
67
|
+
|
|
68
|
+
### Requirement: Canonical and prepared content faces
|
|
69
|
+
The system SHALL treat every resource as having one canonical content: `:raw` SHALL return the canonical full content, line windows SHALL always apply to the canonical content, and the bare URL SHALL return the prepared default face when one is prepared (session → statistics snapshot; compaction episodes → 8-section summary; `thinking` → per-block index list; `system` → per-message index list) or the canonical content when none is. `:raw:<lines>` SHALL equal `:<lines>` — the composite form is accepted on every resource.
|
|
70
|
+
|
|
71
|
+
#### Scenario: Line windows ignore the prepared face
|
|
72
|
+
- **WHEN** the model reads `ctx://session/compactions[221217]:500-560`
|
|
73
|
+
- **THEN** the system returns lines 500–560 of the episode's original shadowed span, not of the summary
|
|
74
|
+
|
|
75
|
+
### Requirement: Thinking, system, and injections collections
|
|
76
|
+
The system SHALL expose three index-faced collections under `ctx://session/`, all following the canonical/prepared face model (bare URL = prepared index; `:raw` / `:N-M` = canonical full text):
|
|
77
|
+
|
|
78
|
+
- `thinking` — the reasoning blocks of `assistant/message` events (`message.content` blocks of `type: "reasoning"`, in event order; a message may carry several). The bare URL SHALL return an index list, one line per block: 0-based ordinal, event seq, turn/step, and a ≤100-char single-line preview. `[<n|seq>]` SHALL return that block's full text (label = the block's event seq, exact match first, 0-based ordinal fallback). `:raw` SHALL return all blocks' full text joined in event order with a blank line between blocks, and line windows SHALL index that canonical text.
|
|
79
|
+
- `system` — the session's `system/message` events (text from `data.text` when present, else the message content blocks; source kind/plugin from `data.source` when present). The bare URL SHALL return an index list, one line per message: event seq, source kind/plugin, and a ≤100-char single-line preview. `[<n|seq>]` SHALL return that message's full text. `:raw` SHALL return all messages' full text joined with a blank line between messages, and line windows SHALL index that canonical text.
|
|
80
|
+
- `injections` — the session's injected `user/message` events, i.e. every `user/message` whose `source.kind` is not `user` (agent instructions, runtime-context snapshots, …; the exact complement of the `user_prompts` collection). The bare URL SHALL return an index list, one line per message: event seq, source kind, and a ≤100-char single-line preview. `[<n|seq>]` SHALL return that message's full text rendered as `[<zero-padded seq>] INJECTED <kind>` followed by the content. `:raw` SHALL return all messages' full text joined with a blank line between messages, and line windows SHALL index that canonical text.
|
|
81
|
+
|
|
82
|
+
#### Scenario: Index then drill into a reasoning block
|
|
83
|
+
- **WHEN** the model reads `ctx://session/thinking` and then `ctx://session/thinking[2]`
|
|
84
|
+
- **THEN** the index lists one line per reasoning block (ordinal, seq, turn/step, preview) and the drilled read returns the third block's full text
|
|
85
|
+
|
|
86
|
+
#### Scenario: Canonical window over the joined blocks
|
|
87
|
+
- **WHEN** the model reads `ctx://session/thinking:10-20`
|
|
88
|
+
- **THEN** the system returns lines 10–20 of the reasoning blocks' full text joined with blank lines, ignoring the index face
|
|
89
|
+
|
|
90
|
+
#### Scenario: System message by seq label
|
|
91
|
+
- **WHEN** the model reads `ctx://session/system[7]` where event seq 7 is a system message
|
|
92
|
+
- **THEN** the system returns that message's full text
|
|
93
|
+
|
|
94
|
+
#### Scenario: Injections complement user_prompts
|
|
95
|
+
- **WHEN** the model reads `ctx://session/injections` in a session whose `user/message` events carry both `source.kind: "user"` and non-`user` sources (agent instructions, runtime snapshots)
|
|
96
|
+
- **THEN** the index lists only the non-`user` messages (seq, source kind, preview), `ctx://session/injections[<n|seq>]` returns one message's full text, and `ctx://session/user_prompts` continues to list only the real prompts
|
|
97
|
+
|
|
98
|
+
#### Scenario: Injection message by ordinal or seq
|
|
99
|
+
- **WHEN** the model reads `ctx://session/injections[0]` or `ctx://session/injections[<seq>]`
|
|
100
|
+
- **THEN** the system returns that injected message's full text with its `INJECTED <kind>` header line
|
|
101
|
+
|
|
102
|
+
### Requirement: Unknown key echoes known keys
|
|
103
|
+
The `CTX_UNKNOWN_KEY` error SHALL list the currently known first-level keys and the sub-path pointer, so the model can self-correct without leaving the read tool.
|
|
104
|
+
|
|
105
|
+
#### Scenario: Unknown key with roster echo
|
|
106
|
+
- **WHEN** the model reads `ctx://bogus`
|
|
107
|
+
- **THEN** the system returns `CTX_UNKNOWN_KEY` naming `session` and the sub-path roster
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# dsh Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Let the model read the harness's own documentation and its effective configuration via `dsh://` URLs — runtime self-description, shipped with the package so it resolves in source, built, and installed layouts alike.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
### Requirement: Documentation addressing
|
|
10
|
+
The system SHALL let `dsh://docs` return the sorted recursive listing of readable harness docs as JSON, and `dsh://docs/<doc>` return that document's content. A missing docs tree returns `URL_DOCS_UNAVAILABLE`; a missing document, a path escaping the docs directory, or a non-file target returns `URL_DOC_NOT_FOUND`. Any other root resource returns `URL_UNKNOWN_RESOURCE`.
|
|
11
|
+
|
|
12
|
+
#### Scenario: Browsing the doc listing
|
|
13
|
+
- **WHEN** the model reads `dsh://docs`
|
|
14
|
+
- **THEN** the system returns the JSON array of doc paths relative to the docs root
|
|
15
|
+
|
|
16
|
+
#### Scenario: Reading a specific document
|
|
17
|
+
- **WHEN** the model reads `dsh://docs/<doc>`
|
|
18
|
+
- **THEN** the system returns that document's content
|
|
19
|
+
|
|
20
|
+
#### Scenario: Path traversal is rejected
|
|
21
|
+
- **WHEN** the model reads `dsh://docs/../secrets`
|
|
22
|
+
- **THEN** the system returns the structured `URL_DOC_NOT_FOUND` error (path escapes the docs directory) and reads nothing
|
|
23
|
+
|
|
24
|
+
### Requirement: Docs tree resolves in every layout
|
|
25
|
+
The system SHALL locate the docs tree by a nearest-first walk-up from the module's own location (`docs-dir.ts`), and the package SHALL ship the docs (`prebuild` copies the repo `docs/` into the package; the `files` array includes it) so source-tree, bundled-lib, and installed-`node_modules` layouts all resolve the package's own docs first.
|
|
26
|
+
|
|
27
|
+
#### Scenario: Installed package resolves its own docs
|
|
28
|
+
- **WHEN** the plugin runs from `node_modules/<dashr>/lib/index.js`
|
|
29
|
+
- **THEN** `dsh://docs` serves the docs shipped inside that package, not an ancestor directory's
|
|
30
|
+
|
|
31
|
+
### Requirement: Effective config addressing
|
|
32
|
+
The system SHALL let `dsh://config` return the current resolved settings as JSON keyed by namespace, and `dsh://config/<ns>` return one namespace. A missing settings service returns `URL_SETTINGS_UNAVAILABLE`; an unknown namespace returns `URL_UNKNOWN_SETTINGS_NAMESPACE`.
|
|
33
|
+
|
|
34
|
+
#### Scenario: Reading the effective config
|
|
35
|
+
- **WHEN** the model reads `dsh://config`
|
|
36
|
+
- **THEN** the system returns the resolved (not documented-default) configuration, namespace by namespace
|
|
37
|
+
|
|
38
|
+
#### Scenario: Reading one namespace
|
|
39
|
+
- **WHEN** the model reads `dsh://config/<known namespace>`
|
|
40
|
+
- **THEN** the system returns that namespace's resolved value as JSON
|
|
41
|
+
|
|
42
|
+
### Requirement: Config never leaks secrets
|
|
43
|
+
The system SHALL strip secrets from every config response: schema-declared `role('secret')` redaction plus a defensive key-name denylist matched against normalized key names (credential/env/API-key material), applied recursively.
|
|
44
|
+
|
|
45
|
+
#### Scenario: Config hides keys
|
|
46
|
+
- **WHEN** the model reads `dsh://config` or `dsh://config/<ns>` and a resolved field is an API key or other secret-named field
|
|
47
|
+
- **THEN** the returned JSON does not contain the secret value
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# dvc Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Reserve DASHR's device I/O surface under `dvc://` (renamed from the earlier `xd://` placeholder — no `xd` name remains anywhere): a read = device list/document view, a write = device dispatch entry. No device provider is mounted this wave, so both views are placeholders that fix the URL shapes and the structured write error for whatever device layer lands later.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
### Requirement: Device roster placeholder
|
|
10
|
+
`dvc://` SHALL return the mounted-device roster listing every registered device name. With no device modules loaded the roster is the placeholder text `no devices mounted`; once devices are registered it lists their names.
|
|
11
|
+
|
|
12
|
+
#### Scenario: Listing mounted devices
|
|
13
|
+
- **WHEN** the model reads bare `dvc://`
|
|
14
|
+
- **THEN** the system returns the roster of registered device names (or `no devices mounted` when none)
|
|
15
|
+
|
|
16
|
+
### Requirement: Unknown device placeholder
|
|
17
|
+
The system SHALL let `dvc://<device>` return placeholder text `unknown device: <name>` — no device provider exists to answer with a real document.
|
|
18
|
+
|
|
19
|
+
#### Scenario: Reading an unmounted device
|
|
20
|
+
- **WHEN** the model reads `dvc://<any device name>`
|
|
21
|
+
- **THEN** the system returns `unknown device: <name>`
|
|
22
|
+
|
|
23
|
+
### Requirement: Write dispatch is a structured no-op
|
|
24
|
+
Every write to `dvc://<device>` SHALL dispatch to the registered device's execute with the JSON-args payload; with no devices mounted the structured `DVC_NO_DEVICE` error stands, and an unknown device name remains a structured error.
|
|
25
|
+
|
|
26
|
+
#### Scenario: Writing with no devices
|
|
27
|
+
- **WHEN** the model writes to `dvc://<device>` and no device module is registered
|
|
28
|
+
- **THEN** the system returns the structured `DVC_NO_DEVICE` error and dispatches nothing
|
|
29
|
+
|
|
30
|
+
### Requirement: Device dispatch contract
|
|
31
|
+
The system SHALL implement the device write contract: `write dvc://<device>` with a JSON-args content executes the device and returns its result; a non-JSON content or a device-reported failure returns a structured error carrying the device name.
|
|
32
|
+
|
|
33
|
+
#### Scenario: Executing a registered device
|
|
34
|
+
- **WHEN** the model writes `dvc://ast_edit` with valid JSON args
|
|
35
|
+
- **THEN** the device executes and its result returns to the caller
|
|
36
|
+
|
|
37
|
+
### Requirement: ast devices
|
|
38
|
+
The system SHALL provide `ast_edit` (staged structured codemod) and `ast_grep` (structured search) devices, vendored from the omp harness (MIT), backed by the published `@oh-my-pi/pi-natives` binding.
|
|
39
|
+
|
|
40
|
+
#### Scenario: ast_grep search over a workspace file
|
|
41
|
+
- **WHEN** the model writes `dvc://ast_grep` with a pattern and path
|
|
42
|
+
- **THEN** structured matches return from the AST search
|
|
43
|
+
|
|
44
|
+
### Requirement: browser device
|
|
45
|
+
The system SHALL provide a `browser` device (open/close/run over real browser tabs) vendored from the omp harness, using puppeteer-core against the system Chrome; when no browser can launch, the device returns a structured error.
|
|
46
|
+
|
|
47
|
+
#### Scenario: Opening a page headlessly
|
|
48
|
+
- **WHEN** the model writes `dvc://browser` with an open action and URL
|
|
49
|
+
- **THEN** a headless tab opens and the action result returns
|
|
50
|
+
|
|
51
|
+
### Requirement: lsp device
|
|
52
|
+
The system SHALL provide an `lsp` device (definition/references/diagnostics/actions) vendored from the omp harness; languages whose server binary is absent degrade gracefully per language.
|
|
53
|
+
|
|
54
|
+
#### Scenario: Diagnostics for an installed language server
|
|
55
|
+
- **WHEN** the model writes `dvc://lsp` requesting diagnostics for a file whose language server is installed
|
|
56
|
+
- **THEN** the device returns the diagnostics
|
|
57
|
+
|
|
58
|
+
#### Scenario: Missing language server degrades
|
|
59
|
+
- **WHEN** the requested language's server binary is not installed
|
|
60
|
+
- **THEN** the device reports the missing server without crashing the session
|
|
61
|
+
|
|
62
|
+
### Requirement: lsp wired into write
|
|
63
|
+
The system SHALL close the write-feedback loop: after a `write` lands a file whose language has an available language server, the tool result SHALL include a diagnostics summary for that file (error/warning counts plus the first message detail when non-zero), and the content SHALL be formatted before the single native write when the language server provides formatting capability. The diagnostics pipeline SHALL be honest about freshness: the feedback path syncs the exact written content, then signals the standard save notification (`textDocument/didSave`) so save-triggered checkers (e.g. rust-analyzer's flycheck) re-run, and waits for the refreshed diagnostics under a bounded timeout. When the wait times out, save-triggered compiler-source diagnostics (which are provably stale at that point) SHALL be dropped while immediately-computed diagnostics are kept — under-reporting beats mis-reporting. As a final guard, any diagnostic whose line lies beyond the just-written content's line count SHALL be dropped: it cannot refer to what was written. Languages with no server available (absent binary or unsupported extension) SHALL behave exactly as before — the hook adds nothing and fails silently, and the native write receives the caller's arguments object unchanged when formatting changes nothing.
|
|
64
|
+
|
|
65
|
+
#### Scenario: Write surfaces the damage it just caused
|
|
66
|
+
- **WHEN** a write lands content that introduces a type error in a file with a language server installed and its check-on-save pipeline completes within the timeout
|
|
67
|
+
- **THEN** the write result carries a diagnostics summary describing the EXACT content just written (never a stale earlier version), so the model learns of the breakage without a separate diagnostics call
|
|
68
|
+
|
|
69
|
+
#### Scenario: A fixed error stops being reported
|
|
70
|
+
- **WHEN** a write replaces content that previously had a type error with correct content
|
|
71
|
+
- **THEN** the write result no longer reports the old error — the save-triggered checker re-ran on the new content, and any compiler-source diagnostic still describing the old content is either refreshed or dropped
|
|
72
|
+
|
|
73
|
+
#### Scenario: Slow checks degrade honestly
|
|
74
|
+
- **WHEN** the save-triggered check does not complete within the bounded timeout
|
|
75
|
+
- **THEN** compiler-source diagnostics are dropped from the summary (they are provably stale), immediately-computed diagnostics remain, and the result never reports an error that refers to content other than what was just written
|
|
76
|
+
|
|
77
|
+
#### Scenario: Out-of-range spans are dropped
|
|
78
|
+
- **WHEN** a published diagnostic references a line beyond the just-written content's line count
|
|
79
|
+
- **THEN** that diagnostic is excluded from the summary and the counts reflect only the retained set
|
|
80
|
+
|
|
81
|
+
#### Scenario: Format-before-write
|
|
82
|
+
- **WHEN** a write targets a file whose server provides formatting
|
|
83
|
+
- **THEN** the native write receives and stores the formatted content (one write, one audit), and the before/after pair stays truthful
|
|
84
|
+
|
|
85
|
+
#### Scenario: Serverless language unchanged
|
|
86
|
+
- **WHEN** a write targets a file whose language has no server available
|
|
87
|
+
- **THEN** the result is byte-identical to the pre-change behavior (no diagnostics block, no formatting, no error)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# escalation-guidance Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
在 workspace-write 沙箱模式下,向模型的运行时上下文注入 per-call 升级能力的精简披露:受限操作可被拒/已拒后按调用以 `sandbox_permissions` + 一行 `justification` 升级(runtime 提示 user 审批,审批/拒绝均为 per-call,无会话级预算措辞)。该注入只披露能力、不劝导行为,且不依赖 upstream 源码修改。
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
### Requirement: Escalation guidance injected under workspace-write only
|
|
9
|
+
|
|
10
|
+
The system SHALL inject an escalation-guidance context entry into the model-facing system prompt when the session's effective sandbox mode is `workspace-write`, and SHALL NOT inject it when the effective mode is `read-only` or `danger-full-access`. The guidance SHALL state the per-call escalation semantics in the approved wording: a sandbox-deniable or sandbox-denied call MAY be escalated with `sandbox_permissions` and a one-line `justification`; the runtime SHALL prompt the user for approval; escalation and its approval/denial SHALL be per-call. The guidance text SHALL NOT contain quota wording (`retried once`, `once`, allowed-once) or any claim of a session-level escalation budget.
|
|
11
|
+
|
|
12
|
+
#### Scenario: Workspace-write session sees the guidance
|
|
13
|
+
|
|
14
|
+
- **WHEN** a DASHR agent session runs with effective sandbox mode `workspace-write`
|
|
15
|
+
- **THEN** the runtime-context snapshot contains the escalation-guidance entry stating the deniable/denied per-call escalation path (`sandbox_permissions` + one-line `justification`, user approval prompted by the runtime)
|
|
16
|
+
|
|
17
|
+
#### Scenario: Guidance contains no quota wording
|
|
18
|
+
|
|
19
|
+
- **WHEN** the escalation-guidance entry renders under `workspace-write`
|
|
20
|
+
- **THEN** its text contains none of `retried once` / allowed-once / per-session budget claims, and states that escalation and its approval/denial are per-call
|
|
21
|
+
|
|
22
|
+
#### Scenario: Read-only session skips the guidance
|
|
23
|
+
|
|
24
|
+
- **WHEN** a DASHR agent session runs with effective sandbox mode `read-only`
|
|
25
|
+
- **THEN** the runtime-context snapshot contains no escalation-guidance entry from DASHR (the upstream read-only policy sentence already teaches the escalation guidance)
|
|
26
|
+
|
|
27
|
+
#### Scenario: Danger-full-access session skips the guidance
|
|
28
|
+
|
|
29
|
+
- **WHEN** a DASHR agent session runs with effective sandbox mode `danger-full-access`
|
|
30
|
+
- **THEN** the runtime-context snapshot contains no escalation-guidance entry (there is no restricted operation to escalate)
|
|
31
|
+
|
|
32
|
+
### Requirement: Guidance is minimal disclosure, not behavioral coaching
|
|
33
|
+
The system SHALL keep the injected guidance text limited to disclosing the escalation capability — it SHALL NOT instruct the model to attempt restricted operations, SHALL NOT instruct it to refrain, and SHALL NOT restate or claim the sandbox is immutable. Whether to attempt an out-of-box operation SHALL remain the model's own decision.
|
|
34
|
+
|
|
35
|
+
#### Scenario: Text states the lever only
|
|
36
|
+
- **WHEN** the escalation-guidance entry renders under `workspace-write`
|
|
37
|
+
- **THEN** its text discloses the single-call escalation path and contains no imperative coaching sentence (no "do not refuse", no "go try", no "you are sandboxed and cannot change it")
|
|
38
|
+
|
|
39
|
+
### Requirement: Guidance rides the runtime-context snapshot
|
|
40
|
+
The system SHALL render the escalation guidance inside the same runtime-context snapshot region as the sandbox and approval policy entries (positioned after the approval-policy entry), so it is adjacent to the policy statements the model already reads. The injection SHALL register through the plugin system-prompt context API (`ctx.systemPrompt.context`) without modifying upstream DSH source.
|
|
41
|
+
|
|
42
|
+
#### Scenario: Guidance sits beside the policy entries
|
|
43
|
+
- **WHEN** a `workspace-write` session renders the system prompt
|
|
44
|
+
- **THEN** the escalation-guidance entry appears in the runtime-context snapshot, ordered after the `approval:policy` entry and before any later context entries
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# fs-scheme-resolution Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
定义文件系统服务层的 URL scheme 解析契约:通过 `urlSchemes` 配置门控,在 `ctx.fs` 实例上原位包裹,使 `dsh://`、`dvc://`、`http(s)://` 等静态 scheme 经统一解析器读出虚拟目标。门控关闭时透明退化为 stock 行为(bit-for-bit 等价),真实路径语义不受影响。
|
|
5
|
+
|
|
6
|
+
### Requirement: FS-gate scheme resolution
|
|
7
|
+
The system SHALL resolve file-type scheme URLs (`dsh://`, `dvc://`, `http(s)://`) at the filesystem service seam by wrapping the LIVE `ctx.fs` instance in place (instance-level method wrap of its five public methods; symbol-idempotent, re-applied per boot, every added behavior gated behind `urlSchemes`; a wrap failure degrades to the stock service, never a failed boot). Every `ctx.fs` consumer — including the platform's native read/write/edit tools with no tool-layer wrapping — SHALL thus resolve these URLs through the URL resolver: `resolve` returns a virtual target keyed by the URL, `stat` answers a synthesized file entry, and `readText` dereferences the resolved text.
|
|
8
|
+
#### Scenario: Native read of a static scheme without tool-layer participation
|
|
9
|
+
- **WHEN** the hashline tool gate is disabled (the wrapped read delegates to the captured native read) and the model reads `dsh://docs/<doc>`
|
|
10
|
+
- **THEN** the native read resolves the document through the filesystem backend and returns its text — no tool-layer scheme code participated
|
|
11
|
+
|
|
12
|
+
#### Scenario: Real-path passthrough
|
|
13
|
+
- **WHEN** any consumer resolves, reads, or mutates a real filesystem path
|
|
14
|
+
- **THEN** every operation delegates to the inherited sandboxed backend unchanged (containment, observation events, atomic writes, read-match-write critical section)
|
|
15
|
+
|
|
16
|
+
### Requirement: Virtual targets are read-only
|
|
17
|
+
The backend SHALL refuse mutations that target a virtual scheme path with the structured `FS_VIRTUAL_READONLY` error before any policy or filesystem work, while `urlSchemes` is enabled. Real-path mutations keep the stock fence.
|
|
18
|
+
|
|
19
|
+
#### Scenario: Native write against a virtual target
|
|
20
|
+
- **WHEN** the model writes to a scheme path that has no write channel at the FS layer
|
|
21
|
+
- **THEN** the call fails with `FS_VIRTUAL_READONLY` and no file is created
|
|
22
|
+
|
|
23
|
+
### Requirement: Session-layer schemes stay at the tool layer
|
|
24
|
+
`ctx://`, `agent://`, and `skill://` require live-agent semantics the filesystem layer does not have: the first two read session state, and `skill://` must consult the host skill registry's layered catalog — whose discovery (which roots load: project/user/preset/custom/bundled, scan depth, rank and scope merge) is business logic owned by the host `skill-filesystem` provider and resolves only against a calling agent. The backend SHALL answer all three with a structured session-layer boundary error naming the sanctioned channel (the native `skill` tool for skill loading), and SHALL NOT re-implement or approximate skill discovery (no own root parsing, no cwd heuristics, no scope guessing). The wrapped read tool's scheme branch SHALL continue to serve `ctx://`/`agent://` with the calling agent's context, and the skill handler at the tool layer SHALL mirror the native tool's lookup exactly (`cwd` from the agent's session header, the agent as viewing scope).
|
|
25
|
+
#### Scenario: Native read of ctx:// names the boundary
|
|
26
|
+
- **WHEN** the model reads a `ctx://` URL through a consumer that has no live-agent resolver environment
|
|
27
|
+
- **THEN** the backend returns a structured error explaining that `ctx://` is served by the session-layer read, instead of a raw filesystem failure
|
|
28
|
+
|
|
29
|
+
#### Scenario: Native read of skill:// names the session-layer boundary
|
|
30
|
+
- **WHEN** the model reads any `skill://` URL through a filesystem-layer consumer (no calling agent)
|
|
31
|
+
- **THEN** the backend returns the structured session-layer boundary error pointing at the native `skill` tool — never a registry verdict (such as "unknown skill") guessed from a deployment-declared cwd
|
|
32
|
+
### Requirement: Gate disables resolution transparently
|
|
33
|
+
When `urlSchemes` is `false`, the backend SHALL short-circuit every override to the inherited stock behavior — scheme paths fail as ordinary native paths, real-path semantics are untouched, and the deployment behaves bit-for-bit like the stock `fs-sandbox` row.
|
|
34
|
+
|
|
35
|
+
#### Scenario: Stock degradation
|
|
36
|
+
- **WHEN** the deployment sets `urlSchemes: false` on the mounted row and a consumer reads a scheme URL
|
|
37
|
+
- **THEN** the call fails as it would under the stock backend (no scheme interception anywhere)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# hash-edit Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
DASHR 的哈希锚点读写/edit 契约:`read` 以 `HASH│content` 行锚点呈现文件;`edit`/`undo_last_edit` 以锚点定位做单文件原子编辑;served 账本(schema v7,path 主键,集中存储于 `$DSH_HOME/storages/dsh-better-edit/`)保证锚点跨会话可验证。hash-edit 是自包含模块(`src/hashline/`),对 url-schemes 零出向引用;与 url-schemes 的组合只发生在 `url-schemes/index.ts` 组合根(read 链:scheme wrapper → hashline read → captured native)。
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
### Requirement: Anchored read presentation
|
|
9
|
+
The hashline read doer SHALL present every served text file as `HASH│content` rows (3-char hash anchors for later edit calls), with paging via `offset`/`limit` on file reads.
|
|
10
|
+
|
|
11
|
+
#### Scenario: Anchored read
|
|
12
|
+
- **WHEN** the agent calls `read` on a filesystem path with hashline enabled
|
|
13
|
+
- **THEN** each line returns as `HASH│content` and the served rows persist to the centralized store keyed by absolute path
|
|
14
|
+
|
|
15
|
+
### Requirement: Content-anchored edit with single-file atomicity
|
|
16
|
+
The `edit` tool SHALL apply the payload `{ path: string|null, edits: [[remove_from, remove_to, replacement_text], ...] }` as a single-file atomic batch; `null` path infers via anchors; `undo_last_edit` reverts the last edit on a file. Edit verification is content-anchored: a range whose bounds are unseen by the served ledger MAY pass via the content fast-path; `E_RANGE_STALE`/`E_RANGE_UNSERVED` semantics are preserved.
|
|
17
|
+
|
|
18
|
+
#### Scenario: Atomic batch
|
|
19
|
+
- **WHEN** an edit payload contains multiple edits and one anchor fails to resolve
|
|
20
|
+
- **THEN** no edit from the batch is written and the failing range is echoed back with fresh anchors
|
|
21
|
+
|
|
22
|
+
### Requirement: Host guard independence
|
|
23
|
+
The host `dsh-fs-observation-policy`'s `E_NOT_OBSERVED` (read-before-edit) SHALL remain an independent design-intent guard for cross-session edits; hash-edit verification complements, never replaces, it.
|
|
24
|
+
|
|
25
|
+
#### Scenario: Cross-session edit
|
|
26
|
+
- **WHEN** a session edits a file it never read and no served rows exist for its bounds
|
|
27
|
+
- **THEN** the host observation policy still denies or the content fast-path rules, per its own contract — hash-edit does not silently relax it
|
|
28
|
+
|
|
29
|
+
### Requirement: Module orthogonality
|
|
30
|
+
The hashline module SHALL NOT import anything from `url-schemes` (or any scheme surface). Its standalone entries — `initHashlineRuntime()`, `createHashlineReadTool()`, `installHashline()` — SHALL work with url-schemes absent; per-agent features it does not own (e.g. lsp edit feedback) arrive only as injected callbacks.
|
|
31
|
+
|
|
32
|
+
#### Scenario: Standalone mount
|
|
33
|
+
- **WHEN** a deployment mounts hashline without url-schemes
|
|
34
|
+
- **THEN** anchored read + edit/undo + guidance register and function; no scheme branch exists anywhere in the module
|
|
35
|
+
|
|
36
|
+
### Requirement: Shared sandbox controller
|
|
37
|
+
When co-mounted with a write wrapper, the `FsSandboxController` instance SHALL be created by the composition root and injected into both the hashline edit family and the write wrapper, so escalation advertisement and per-call policy stamping share one controller.
|
|
38
|
+
|
|
39
|
+
#### Scenario: Shared escalation surface
|
|
40
|
+
- **WHEN** a confining sandbox backend is mounted and both hashline and the write wrapper are active
|
|
41
|
+
- **THEN** `edit` and `write` escalate through the same controller with the session workspace root stamped
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# http-read Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Let the model read plain-text web resources via `http://` / `https://` URLs — a curl-equivalent direct HTTP GET with a hard budget, never a browser. One stateless handler serves both schemes.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
### Requirement: GET-only plain-text fetch
|
|
10
|
+
The system SHALL resolve `http://` and `https://` URLs by one GET request (redirects followed) to the exact URL — parsed strictly with `new URL(raw)` from the env's `rawUrl`, so ports and queries survive at the handler level — and return the disclaimer line, a blank line, then the decoded body text.
|
|
11
|
+
|
|
12
|
+
#### Scenario: Fetching a text resource
|
|
13
|
+
- **WHEN** the model reads `https://example.com/a.txt` and the server responds 200 with a text content-type
|
|
14
|
+
- **THEN** the system returns the disclaimer line, a blank line, and the body text
|
|
15
|
+
|
|
16
|
+
#### Scenario: The disclaimer is always first
|
|
17
|
+
- **WHEN** any http(s) URL resolves successfully
|
|
18
|
+
- **THEN** the first line of the result is `[url-fetch] plain-text result of a direct HTTP GET (curl-equivalent). No JS execution or interaction — use browser tools, if any, for that.` — the consumer sees the fetch semantics before any body content
|
|
19
|
+
|
|
20
|
+
#### Scenario: Non-http(s) protocol is rejected
|
|
21
|
+
- **WHEN** the handler is asked to resolve a URL whose strict-parsed protocol is neither `http:` nor `https:`
|
|
22
|
+
- **THEN** the system returns the structured `URL_INVALID` error
|
|
23
|
+
|
|
24
|
+
### Requirement: Hard time budget
|
|
25
|
+
The system SHALL abort the GET after 20 seconds and return the structured `URL_HTTP_TIMEOUT` error.
|
|
26
|
+
|
|
27
|
+
#### Scenario: Server never responds
|
|
28
|
+
- **WHEN** the server accepts the connection but sends no response within the deadline
|
|
29
|
+
- **THEN** the system aborts the fetch and returns `URL_HTTP_TIMEOUT`
|
|
30
|
+
|
|
31
|
+
### Requirement: Hard size cap
|
|
32
|
+
The system SHALL reject bodies over 2 MiB: first via a `Content-Length` precheck when present, then via streaming byte accounting while decoding (and a buffered re-check on bodyless runtimes), returning the structured `URL_HTTP_TOO_LARGE` error with the actual byte count.
|
|
33
|
+
|
|
34
|
+
#### Scenario: Oversized declared body
|
|
35
|
+
- **WHEN** the response declares a Content-Length over 2 MiB
|
|
36
|
+
- **THEN** the system returns `URL_HTTP_TOO_LARGE` without downloading the body
|
|
37
|
+
|
|
38
|
+
#### Scenario: Undeclared oversized body
|
|
39
|
+
- **WHEN** no Content-Length is declared but the streamed bytes pass 2 MiB
|
|
40
|
+
- **THEN** the system aborts decoding and returns `URL_HTTP_TOO_LARGE` with the received byte count
|
|
41
|
+
|
|
42
|
+
### Requirement: Text-only media whitelist
|
|
43
|
+
The system SHALL accept only textual responses: any `text/*` content-type, or `application/{json, xml, yaml, toml, xhtml+xml, javascript, plain}` (charset parameters ignored). A missing content-type fails the check. Anything else returns the structured `URL_HTTP_UNSUPPORTED_MEDIA` error — binary decoding is deliberately not guessed.
|
|
44
|
+
|
|
45
|
+
#### Scenario: JSON response resolves
|
|
46
|
+
- **WHEN** the server responds with `application/json`
|
|
47
|
+
- **THEN** the body text resolves normally
|
|
48
|
+
|
|
49
|
+
#### Scenario: Binary response is rejected
|
|
50
|
+
- **WHEN** the server responds with `image/png`
|
|
51
|
+
- **THEN** the system returns `URL_HTTP_UNSUPPORTED_MEDIA` and decodes nothing
|
|
52
|
+
|
|
53
|
+
### Requirement: Structured failure codes
|
|
54
|
+
The system SHALL report every failure with a structured code: non-2xx status → `URL_HTTP_STATUS` (status + statusText); network/DNS failure → `URL_HTTP_FETCH_FAILED` (with the underlying cause message); unparseable or non-http(s) URL → `URL_INVALID`. Precedence: status → size precheck → media whitelist → streamed body.
|
|
55
|
+
|
|
56
|
+
#### Scenario: HTTP error status
|
|
57
|
+
- **WHEN** the server responds 404
|
|
58
|
+
- **THEN** the system returns `URL_HTTP_STATUS` with the status in the message
|
|
59
|
+
|
|
60
|
+
#### Scenario: DNS failure
|
|
61
|
+
- **WHEN** the host does not resolve
|
|
62
|
+
- **THEN** the system returns `URL_HTTP_FETCH_FAILED` with the underlying cause
|
|
63
|
+
|
|
64
|
+
### Requirement: No scheme-specific selector
|
|
65
|
+
The system SHALL define no selector of its own for http(s): the handler always returns the disclaimer plus the full body. Selector handling is inherited solely from the shared resolver layer, whose parse runs first on the tool path — a URL query (`?…`) is consumed as a query selector by the shared parser (the fetch itself still uses the complete raw URL), and a `:port` currently fails the shared `URL_BAD_SELECTOR` check end-to-end. This is a documented known limitation, not a hidden behavior.
|
|
66
|
+
|
|
67
|
+
#### Scenario: Query string is preserved for the fetch
|
|
68
|
+
- **WHEN** the model reads `https://example.com/x?q=1`
|
|
69
|
+
- **THEN** the fetch uses the complete URL `https://example.com/x?q=1` (from the env's rawUrl), and the shared parser's query selector applies only to the result text
|
|
70
|
+
|
|
71
|
+
#### Scenario: Port-carrying URL on the tool path
|
|
72
|
+
- **WHEN** the model reads `https://example.com:8443/x` through the read tool
|
|
73
|
+
- **THEN** the shared selector parse fails with `URL_BAD_SELECTOR` — the handler's whole-URL parse is only reachable directly or via URLs without a port
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# kernel-provisioning Specification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
better-dsh 的 REPL kernel(IPython)供给契约:独占 managed venv(插件包目录内,`kernelEnvDir` 可显式覆盖)、版本锁定(ipykernel 7.3.0 / dill 0.4.1,uv 与 pip 双路径)、三级触发供给(postinstall 加速器 / daemon spin-up 主路径 / 首用 lazy 兜底)全 fail-open 且幂等、供给状态可观测;npm 包不内嵌预建 venv(供给能力随包,供给结果不随包)。
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
### Requirement: Exclusive managed kernel venv
|
|
9
|
+
|
|
10
|
+
The plugin SHALL provision its REPL kernel interpreter exclusively inside a managed venv rooted in the plugin's own package directory (web-profile scope in production deployments, `kernelEnvDir` as the explicit override), and SHALL NOT install into, mutate, or depend on the user's global Python environment; kernel probes MUST NOT import user-site modules, and the distributed npm package MUST NOT embed a prebuilt venv (provisioning capability ships, not provisioning results).
|
|
11
|
+
|
|
12
|
+
#### Scenario: Venv lives inside the plugin territory
|
|
13
|
+
|
|
14
|
+
- **WHEN** the plugin is installed into a web profile and the kernel is provisioned
|
|
15
|
+
- **THEN** the venv root is inside the plugin's package directory (or the explicitly configured `kernelEnvDir`), and no file outside that territory is required for kernel operation
|
|
16
|
+
|
|
17
|
+
#### Scenario: User global environment untouched
|
|
18
|
+
|
|
19
|
+
- **WHEN** provisioning runs on a host with an existing global Python installation
|
|
20
|
+
- **THEN** no package is installed into, and no configuration of, the user's global environment is modified
|
|
21
|
+
|
|
22
|
+
### Requirement: Robust provisioning with pinned versions
|
|
23
|
+
|
|
24
|
+
Provisioning SHALL redirect its tool caches (uv) to a plugin-territory location so read-only home directories cannot block it, SHALL fall back to `python3 -m venv` + ensurepip when `uv` is unavailable, and SHALL install pinned, tested versions of `ipykernel` and `dill` alongside the pinned CPython version; provisioning MUST be idempotent (a complete venv is reused; a partial one is repaired).
|
|
25
|
+
|
|
26
|
+
#### Scenario: Read-only home cache does not block
|
|
27
|
+
|
|
28
|
+
- **WHEN** the kernel is provisioned on a host whose `~/.cache` is read-only
|
|
29
|
+
- **THEN** provisioning succeeds using the redirected cache location
|
|
30
|
+
|
|
31
|
+
#### Scenario: Pinned versions installed
|
|
32
|
+
|
|
33
|
+
- **WHEN** provisioning creates or repairs the venv
|
|
34
|
+
- **THEN** the installed `ipykernel` and `dill` match the pinned tested versions, verifiable by the kernel probe
|
|
35
|
+
|
|
36
|
+
### Requirement: Provisioning ladder — install-time, daemon spin-up, first-use
|
|
37
|
+
|
|
38
|
+
The plugin SHALL provision the kernel through a three-trigger ladder converging on the same managed venv, every trigger fail-open (a failure or suppression at any level degrades to a logged status message and NEVER blocks package installation, daemon startup, or plugin mounting, and never asks the user for approval): (1) an install-time postinstall best-effort step that runs only when the package manager executes build scripts; (2) a daemon spin-up check as the PRIMARY path — when the plugin is brought up on the host plane by the host daemon, it asynchronously verifies the kernel environment and provisions it immediately when absent (uv → `python3 -m venv` → explicit configuration), so an agent session never discovers a missing kernel at first use; (3) first-use lazy provisioning as the final fallback. Provisioning status (provisioning/ready/degraded/failed) SHALL be logged, and failure messages MUST name the available remedies (`npm run kernel:venv`, `kernelAutoInstall`, explicit `python`).
|
|
39
|
+
|
|
40
|
+
#### Scenario: Daemon spin-up provisions before any agent session
|
|
41
|
+
|
|
42
|
+
- **WHEN** the host daemon starts and brings the plugin up on the host plane, and the managed venv is absent
|
|
43
|
+
- **THEN** the plugin asynchronously provisions the kernel within the spin-up window without blocking daemon startup or plugin mounting, and a new agent session's first REPL cell finds the kernel already in place
|
|
44
|
+
|
|
45
|
+
#### Scenario: Suppressed postinstall still reaches a working kernel
|
|
46
|
+
|
|
47
|
+
- **WHEN** the package manager skips the plugin's postinstall script and the daemon later starts
|
|
48
|
+
- **THEN** the spin-up check provisions the kernel and REPL cells execute, with the install itself never having failed and no approval ever having been requested
|
|
49
|
+
|
|
50
|
+
#### Scenario: Failure is non-blocking and visible
|
|
51
|
+
|
|
52
|
+
- **WHEN** provisioning fails on a constrained host at any trigger
|
|
53
|
+
- **THEN** the installation, daemon startup, and plugin mounting all succeed; the surfaced error names the concrete remedy commands/configuration paths
|