@softspark/ai-toolkit 4.29.2 → 4.30.3

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +40 -15
  3. package/app/.claude-plugin/plugin.json +1 -1
  4. package/app/ARCHITECTURE.md +2 -2
  5. package/app/mcp-templates/README.md +7 -2
  6. package/app/mcp-templates/rag-mcp-legal.json +11 -0
  7. package/app/mcp-templates/rag-mcp.json +11 -0
  8. package/app/surface.json +1 -0
  9. package/benchmarks/ecosystem-doctor-snapshot.json +29 -17
  10. package/bin/ai-toolkit.js +8 -0
  11. package/kb/history/completed/dsh-integration-plan-superseded.md +322 -0
  12. package/kb/history/completed/dsh-native-install-target-plan.md +331 -0
  13. package/kb/procedures/ecosystem-sync-sop.md +7 -5
  14. package/kb/procedures/maintenance-sop.md +1 -1
  15. package/kb/procedures/release-preparation-sop.md +81 -20
  16. package/kb/procedures/release-verification-sop.md +35 -5
  17. package/kb/reference/architecture-overview.md +24 -5
  18. package/kb/reference/cli-reference.md +1 -1
  19. package/kb/reference/dsh-compatibility.md +183 -0
  20. package/kb/reference/manifest-install.md +112 -5
  21. package/kb/reference/mcp-templates.md +11 -4
  22. package/kb/reference/plugin-pack-conventions.md +35 -18
  23. package/kb/reference/supported-tools-registry.md +30 -6
  24. package/llms-full.txt +1190 -69
  25. package/llms.txt +3 -0
  26. package/manifest.json +2 -2
  27. package/package.json +2 -2
  28. package/scripts/codex_skill_adapter.py +673 -34
  29. package/scripts/config_resolver.py +80 -14
  30. package/scripts/doctor.py +98 -20
  31. package/scripts/ecosystem_tools.json +51 -1
  32. package/scripts/generate_codex_skills.py +22 -20
  33. package/scripts/install.py +30 -13
  34. package/scripts/install_steps/ai_tools.py +97 -33
  35. package/scripts/install_steps/dsh.py +5063 -0
  36. package/scripts/install_steps/install_state.py +1645 -57
  37. package/scripts/mcp_editors.py +5 -2
  38. package/scripts/plugin.py +2495 -163
  39. package/scripts/plugin_mcp.py +279 -0
  40. package/scripts/plugin_rules.py +389 -0
  41. package/scripts/plugin_schema.py +139 -23
  42. package/scripts/uninstall.py +47 -4
  43. package/scripts/validate.py +421 -0
package/llms-full.txt CHANGED
@@ -15,6 +15,8 @@
15
15
  - [No Hardcoded Counts in Secondary Docs](kb/best-practices/no-hardcoded-counts.md)
16
16
  - [Plan: Deep Coverage v3.0 — 100% Native Surface Utilization](kb/history/completed/deep-coverage-v3-20260423.md)
17
17
  - [Plan: Drop Cascade hooks after 2026-07-01 sunset](kb/history/completed/drop-cascade-hooks-after-sunset-20260710.md)
18
+ - [Plan: DeepSeek Harness (dsh) Integration (Superseded)](kb/history/completed/dsh-integration-plan-superseded.md)
19
+ - [Plan: Native DSH Install Target](kb/history/completed/dsh-native-install-target-plan.md)
18
20
  - [Plan: Ecosystem Deep Sweep — All 12 Supported Tools](kb/history/completed/ecosystem-deep-sweep-20260423.md)
19
21
  - [Plan: Enterprise Config Inheritance — Multi-Repo Governance with `extends`](kb/history/completed/enterprise-config-inheritance-plan-20260412.md)
20
22
  - [Spike: F2 MCP Context Trim — Hook Feasibility & Path Decision](kb/history/completed/f2-mcp-trim-spike-20260504.md)
@@ -48,6 +50,7 @@
48
50
  - [Plan: Competitive Features — ai-toolkit](kb/reference/competitive-features-implementation.md)
49
51
  - [AI Toolkit - GitHub Copilot Compatibility](kb/reference/copilot-compatibility.md)
50
52
  - [Distribution Model](kb/reference/distribution-model.md)
53
+ - [DSH Compatibility](kb/reference/dsh-compatibility.md)
51
54
  - [Enterprise Config Inheritance Guide](kb/reference/enterprise-config-guide.md)
52
55
  - [Extension API Reference](kb/reference/extension-api.md)
53
56
  - [Global Install Model](kb/reference/global-install-model.md)
@@ -589,6 +592,669 @@ removing it before the sunset breaks Cascade users who are still on the old agen
589
592
 
590
593
  ---
591
594
 
595
+ ## kb/history/completed/dsh-integration-plan-superseded.md
596
+
597
+ ---
598
+ title: "Plan: DeepSeek Harness (dsh) Integration"
599
+ category: planning
600
+ service: ai-toolkit
601
+ tags:
602
+ - dsh
603
+ - deepseek-harness
604
+ - cordis
605
+ - integration
606
+ - skills
607
+ - subagents
608
+ - multi-model
609
+ - acp
610
+ - emission-target
611
+ doc_type: plan
612
+ status: superseded
613
+ created: "2026-08-25"
614
+ last_updated: "2026-08-27"
615
+ closed: "2026-08-27"
616
+ completion: "Functional objective delivered through standalone 1.0.0 modules; native ai-toolkit install target moved to a replacement plan"
617
+ superseded_by: "kb/history/completed/dsh-native-install-target-plan.md"
618
+ description: "Superseded DSH integration plan retained as the historical record of the subscription-backed runtime validation and the architecture split into dsh-codex and dsh-orchestrator."
619
+ ---
620
+
621
+ # Plan: DeepSeek Harness (dsh) Integration (Superseded)
622
+
623
+ **Status:** Superseded on 2026-08-27
624
+ **Completion:** Functional objective delivered; native ai-toolkit install target moved to a replacement plan
625
+ **Created:** 2026-08-25
626
+ **Origin:** Requirement for a single window driving three already-owned subscriptions (Claude Max, ChatGPT Plus, Gemini) without buying API credits
627
+ **Upstream reviewed:** `deepseek-ai/deepseek-harness` @ `b150a55` (2026-08-21), package version `0.1.1-rc.2`, MIT, developer preview
628
+ **Replacement:** [`dsh-native-install-target-plan.md`](dsh-native-install-target-plan.md)
629
+
630
+ ## Closure Record
631
+
632
+ This plan mixed two outcomes that now have different ownership:
633
+
634
+ 1. The user-facing runtime objective is complete. `@softspark/dsh-codex@1.0.0` provides the ChatGPT-backed Codex parent, and `@softspark/dsh-orchestrator@1.0.0` delegates bounded tasks to Claude Code and GitHub Copilot Gemini. Both are public Apache-2.0 modules with CI, provenance, security gates, KB, release SOPs, and post-release verification.
635
+ 2. Direct Gemini delegation through a personal Google AI Pro/Ultra login is not supported. The delivered route uses GitHub Copilot CLI ACP, GitHub authentication, and GitHub plan credits. No Google credential proxy or Antigravity workaround is part of the system.
636
+ 3. The native ai-toolkit emission target was not implemented. `ai-toolkit install --local --editors dsh`, managed preset installation, DSH-specific uninstall, registry metadata, and focused bats coverage move to the replacement plan.
637
+
638
+ The historical phases below remain useful as the research and validation record. Their status table is updated to show what shipped, what was cut, and what moved.
639
+
640
+ ## 1. Objective
641
+
642
+ Add dsh as the twelfth emission target so a single harness can delegate to Claude Code, Codex,
643
+ and Gemini CLI while each child authenticates natively against its own vendor subscription.
644
+
645
+ **Non-goal:** rewriting ai-toolkit on top of dsh. The toolkit stays the control plane and source
646
+ of truth. dsh is a runtime it emits to, exactly like Codex CLI and opencode.
647
+
648
+ **Hard constraint that shaped this plan:** Anthropic prohibits third-party tools from routing
649
+ Free/Pro/Max OAuth credentials, and enforces it server-side without notice. Any harness that
650
+ speaks the Anthropic API itself therefore requires a separate API key. dsh avoids this by
651
+ spawning the real Claude Code binary instead of routing credentials.
652
+
653
+ ## 2. Why dsh satisfies the subscription constraint
654
+
655
+ `packages/subagent/subagent-claude-code/README.md` states the provider deliberately omits the SDK
656
+ `settingSources` option, so the official Agent SDK reads the host's normal user, project, and local
657
+ Claude settings relative to the parent session cwd, including native account state. It neither
658
+ copies nor filters those files and does not create or modify login state. Authentication and
659
+ account state remain native; the bundle supplies the CLI but does not create an account, log in,
660
+ or probe an account. Credential-shaped ambient variables are scrubbed before the explicit `env`
661
+ overlay, so `ANTHROPIC_API_KEY` reaches the child only when supplied deliberately. The runtime is
662
+ pinned to `@anthropic-ai/claude-agent-sdk@0.3.220` (Claude Code 2.1.220) and the executable comes
663
+ from the SDK platform package, not from `PATH`.
664
+
665
+ Consequence: the subscription is exercised by Claude Code authenticating itself, not by dsh
666
+ presenting the user's credentials to Anthropic.
667
+
668
+ ### Subagent providers present in the tree
669
+
670
+ | Package | Spawns | Subscription exercised |
671
+ |---|---|---|
672
+ | `subagent-claude-code` | Agent SDK to native `claude` | Claude Max |
673
+ | `subagent-codex` | Codex | ChatGPT Plus |
674
+ | `subagent-acp` | any Agent Client Protocol agent (Gemini CLI ships native ACP) | Gemini |
675
+ | `subagent-dsh-sdk` | dsh SDK loop | model provider config |
676
+ | `subagent-fork-in-process` | forked in-process session | inherited |
677
+ | `subagent-spawn-in-process` | fresh in-process session | inherited |
678
+ | `subagent-in-process-driver` | shared driver for the in-process providers | inherited |
679
+
680
+ ## 3. Verified compatibility surface
681
+
682
+ ### 3.1 Skill discovery is already satisfied
683
+
684
+ `packages/skill/skill-filesystem` resolves roots in rank order:
685
+
686
+ | Rank | Source | Path |
687
+ |---|---|---|
688
+ | 100 | `project-dsh` | `<projectRoot>/.dsh/skills` |
689
+ | 200 | `project-agents` | `<projectRoot>/.agents/skills` |
690
+ | 300 | `custom` | `Config.customSkillDirs` |
691
+ | 400 | `user-dsh` | `<dshHome>/skills` (`$DSH_HOME`, default `~/.dsh`) |
692
+ | 500 | `user-agents` | `<agentsHome>/skills` (`$DSH_AGENTS_HOME`, default `~/.agents`) |
693
+
694
+ Skill format: single-level directory bundles `<name>/SKILL.md` or flat `<name>.md`. Frontmatter is
695
+ an open YAML object; the provider interprets required `name` and `description` plus optional
696
+ `whenToUse`, `metadata`, `disable-model-invocation`, and `user-invocable`. Names must be kebab-case.
697
+
698
+ This is the ai-toolkit skill convention field for field. `scripts/generate_codex_skills.py` already
699
+ mirrors every skill in `app/skills/` into `<target>/.agents/skills/<name>/`, native skills as
700
+ symlinks to canonical `app/skills` and delegation-heavy skills as adapted wrappers through
701
+ `codex_skill_adapter.sync_codex_skill`.
702
+
703
+ **No new skill generator is required.** Rank 200 is the same directory Codex CLI consumes.
704
+
705
+ A bare checkout shows only `ai-toolkit-skill-catalogue` under `.agents/skills/` because
706
+ `enable_codex_skills` defaults to `False` for the standalone generator; the installer sets it when
707
+ Codex is selected.
708
+
709
+ ### 3.2 Presets are compositions, not personas
710
+
711
+ `packages/preset/agent-presets` treats a preset as a plugin composition: the composition file is a
712
+ top-level list of plugin rows, with an optional sibling `preset.yml` carrying display `name` and
713
+ `description` only. The `id` is the directory name and must match `[a-z0-9][a-z0-9-]*`; `trust`
714
+ derives from the discovery root. Authoring is copy-only: `copy()` rejects a non-conforming id, an
715
+ id already supplied by any root, and an unknown source, then re-tightens the copied tree to
716
+ owner-only permissions and dereferences symlinks. A copied `preset.yml` keeps the description but
717
+ drops `name` and roster `order`.
718
+
719
+ Package-name rows resolve against the host composition rather than the preset directory, because a
720
+ user-home preset cannot reach the harness through Node's upward `node_modules` walk. Relative
721
+ paths resolve from the preset's own directory, so a preset's own plugin files and skill directories
722
+ travel with it.
723
+
724
+ **Implication:** mapping 44 agents onto 44 presets is architecturally wrong. Presets are session
725
+ compositions (expect 2-3 of them). The 44 agents belong on the subagent surface.
726
+
727
+ ## 4. Gotchas that must become gates
728
+
729
+ 1. **Invocation frontmatter fails closed.** A camel-case spelling (`userInvocable`,
730
+ `disableModelInvocation`) or a non-boolean invocation value **drops the entire skill from
731
+ discovery** with a warning rather than falling back to a permissive default. Accepted boolean
732
+ spellings are YAML booleans plus case-insensitive `true`/`false`, `yes`/`no`, `on`/`off`,
733
+ `1`/`0`. Current emitters are clean; this must be enforced by `validate.py`, not left to chance.
734
+ 2. **Discovery is one level deep.** Only `<root>/<name>/SKILL.md` and `<root>/<name>.md` are
735
+ recognized. Nested skill trees and package manifests are ignored. Resources under `references`,
736
+ `scripts`, and `assets` inside a bundle are fine and do not invalidate the catalog.
737
+ 3. **Project root is the nearest `.git` ancestor.** Without that marker the provider falls back to
738
+ the supplied cwd. No alternate project-root marker, no monorepo subproject selection.
739
+ 4. **Symlinked skills.** `generate_codex_skills.py` emits symlinks into `app/skills`.
740
+ `watchFollowSymlinks` defaults to `true`, so this should hold, but it needs empirical
741
+ confirmation before being relied on.
742
+ 5. **Malformed entries disappear silently.** The model catalog receives no per-skill diagnostic and
743
+ cannot distinguish an absent skill from an invalid one.
744
+
745
+ ## 5. Open questions
746
+
747
+ | # | Question | How to close |
748
+ |---|---|---|
749
+ | Q1 | Subagent definition format: how a delegatable agent such as `security-auditor` is declared | Moved to the replacement plan; the released orchestrator deliberately exposes two bounded static tools instead of mapping 44 toolkit agents |
750
+ | Q2 | Whether `packages/hooks` ("Claude Code/Codex hook bridges + wire-protocol library") accepts the toolkit's `app/hooks/*.sh` directly | Moved to the replacement plan as an optional compatibility slice, not a prerequisite for the install target |
751
+ | Q3 | Whether `subagent-acp` can drive Gemini CLI end to end on a Google login | Closed negative: individual Gemini CLI access ended; Antigravity has no ACP and prohibits third-party login use |
752
+ | Q4 | Plugin row schema for a composition file | Closed by the released `softspark-orchestrator` preset and `cordis.patch.yml` |
753
+ | Q5 | Whether Claude Max actually authenticates through the spawned CLI in practice | Closed positive by isolated Codex-to-Claude Max verification without an Anthropic API key |
754
+
755
+ ## 6. Progress Tracking
756
+
757
+ | Phase | Deliverable | Depends on | Status |
758
+ |---|---|---|---|
759
+ | 0 | Empirical validation: dsh sees all 109 skills; subscription-backed providers run | none | completed through standalone modules; direct Google route replaced by Copilot Gemini |
760
+ | 1 | `validate.py` gates for kebab-case invocation fields and one-level `.agents/skills` depth | 0 | moved to replacement Phase 1 |
761
+ | 2 | `scripts/generate_dsh_preset.py` emitting 1-2 compositions | 0, Q4 | replaced by the released `softspark-orchestrator` preset; managed installation moved to the replacement plan |
762
+ | 3 | 44 agents mapped onto the subagent surface | Q1 | cut; the released boundary exposes only Claude Code and Copilot Gemini delegation tools |
763
+ | 4 | MCP servers and hook bridge | Q2 | cut from the runtime deliverable; optional compatibility work moved to the replacement plan |
764
+ | 5 | `ecosystem_tools.json` entry, docs across the nine mandated files, bats coverage | 1-4 | native ai-toolkit registry, docs, tests, and uninstall moved to the replacement plan |
765
+
766
+ ### Phase 0 checkpoint: Codex primary provider verified (2026-08-26)
767
+
768
+ - The checkpoint began at `@softspark/dsh-codex@0.1.0`; the public `1.0.0` release now bridges DSH to the official local `codex app-server`
769
+ over JSONL stdio. Codex retains sole ownership of ChatGPT authentication and tokens.
770
+ - The isolated DSH profile loaded provider `codex`, exposed seven models, booted the Web UI
771
+ on `127.0.0.1:3080`, and completed end-to-end session prompts on Codex models.
772
+ - The live app-server reported authentication kind `chatgpt`; no OpenAI API key was configured.
773
+ - The final local tarball passed 92 tests, typecheck, lint, build, coverage, dependency,
774
+ signature, SARIF, package, and composition gates. Its SHA-256 is
775
+ `87db7be9f959de507d708bfa74feb4b5890b9b8a7a33d3520e31d91fcbe673c0`.
776
+ - A persistent DSH session resumed the identical Codex thread after a host restart, and a live
777
+ cancellation ended with reason `aborted`.
778
+ - The public `1.0.0` release keeps stable mode unchanged and exposes a bounded, opt-in
779
+ `experimentalDynamicTools` bridge. Dynamic-tool threads remain non-replayable after restart.
780
+
781
+ Evidence and release gates live in the standalone repository:
782
+ the public [softspark/dsh-codex](https://github.com/softspark/dsh-codex) repository.
783
+
784
+ ### Phase 0 checkpoint: SoftSpark orchestrator composition (2026-08-26)
785
+
786
+ - `@softspark/dsh-codex@1.0.0` exposes an explicit bounded dynamic-tool bridge while stable mode remains unchanged.
787
+ - `@softspark/dsh-orchestrator@1.0.0` is a separate Apache-2.0 public module with exact DSH dependencies, multi-OS CI, provenance, security gates, tests, KB, and release SOPs.
788
+ - The isolated DSH profile loads `softspark-orchestrator` as its default preset and registers one-shot `subagent_claude_code` plus `subagent_gemini_copilot` tools.
789
+ - A real Codex-to-DSH `todo_write` tool roundtrip completed on the final composition with no provider API keys.
790
+ - Claude Max native login is verified. Google AI Pro/Ultra cannot be delegated through DSH: Gemini CLI ended individual access, Antigravity has no ACP, and its terms prohibit third-party use of account login. No proxy or token workaround will be implemented.
791
+ - The final isolated profile completed both a neutral Codex-to-DSH tool call and a Codex-to-Claude Max delegation with exact markers and no provider API keys.
792
+
793
+ ## 7. Detailed Implementation
794
+
795
+ ### Phase 0 - Empirical validation (no code)
796
+
797
+ ```bash
798
+ ai-toolkit install --local --editors codex # populates .agents/skills/ with all 109
799
+ npx @deepseek-ai/dsh web # UI on 127.0.0.1:3080
800
+ ```
801
+
802
+ Verify, in order:
803
+
804
+ 1. The skill catalog lists 109 entries, not the single `ai-toolkit-skill-catalogue` pointer.
805
+ 2. Symlinked skill bodies load (gotcha 4).
806
+ 3. A `subagent-claude-code` delegation runs without an `ANTHROPIC_API_KEY` present (Q5).
807
+ 4. A `subagent-codex` delegation runs on the ChatGPT login.
808
+ 5. A `subagent-acp` delegation reaches Gemini CLI on the Google login (Q3).
809
+
810
+ If step 3 fails, the entire premise collapses and the plan reverts to the ACP-in-JetBrains
811
+ alternative recorded in section 10.
812
+
813
+ ### Phase 1 - Gates
814
+
815
+ Extend `scripts/validate.py`:
816
+
817
+ - Reject any emitted `SKILL.md` whose frontmatter carries `userInvocable` or
818
+ `disableModelInvocation`, or a non-boolean value for the kebab-case forms.
819
+ - Reject any `SKILL.md` deeper than `<root>/<name>/SKILL.md` under `.agents/skills/`.
820
+ - Reject skill directory names failing `[a-z0-9]+(-[a-z0-9]+)*`.
821
+
822
+ These protect Codex CLI and opencode as well; the fail-closed behavior is what makes them
823
+ non-optional rather than cosmetic.
824
+
825
+ ### Phase 2 - Presets
826
+
827
+ `scripts/generate_dsh_preset.py` emits composition directories plus `preset.yml` display metadata.
828
+ Start with `ai-toolkit-standard`; add `ai-toolkit-strict` only if the profile split earns it. Ids
829
+ must satisfy `[a-z0-9][a-z0-9-]*`. Do not attempt to author presets by writing into a shipped
830
+ preset directory. Upstream authoring is copy-only and `remove()` refuses shipped presets.
831
+
832
+ ### Phase 3 - Agents
833
+
834
+ Blocked on Q1. Expected shape: one subagent declaration per `app/agents/*.md`, carrying
835
+ `description`, tool allowances, and delegation targets, with the model left unset so host settings
836
+ stay authoritative. The `model` alias problem is the same one documented for opencode in
837
+ `kb/reference/opencode-compatibility.md`: the toolkit stores `opus`/`sonnet`/`haiku`, which cannot
838
+ be mapped without assuming a provider.
839
+
840
+ ### Phase 4 - MCP and hooks
841
+
842
+ `packages/mcp` for server config, `packages/hooks` for the bridge. If the hook bridge speaks the
843
+ Claude Code hook wire protocol, `app/hooks/*.sh` may attach with a thin adapter rather than a
844
+ rewrite. Preserve `exit 2` blocking semantics for `guard-destructive.sh`. This matters most under
845
+ unattended delegation, where nobody is watching the permission prompt.
846
+
847
+ ### Phase 5 - Registry, docs, tests
848
+
849
+ Follow the opencode precedent exactly:
850
+
851
+ - `scripts/ecosystem_tools.json` entry with docs and release-notes URLs for drift detection.
852
+ - `kb/reference/dsh-compatibility.md` mirroring the section layout of
853
+ `kb/reference/opencode-compatibility.md` (Summary, Local/Global Install Outputs, Editor Surface
854
+ Comparison, translation models, Behavioral Limits, Verification, CLI Commands).
855
+ - Entry in `kb/reference/supported-tools-registry.md`.
856
+ - The nine files mandated by `CLAUDE.md`: README.md, CLAUDE.md, ARCHITECTURE.md, package.json,
857
+ plugin.json, skills-catalog.md, architecture-overview.md, llms.txt, AGENTS.md.
858
+ - bats generator contract tests, auto-detection tests, idempotency tests.
859
+ - `python3 scripts/validate.py --strict`, `python3 scripts/audit_skills.py --ci`, and
860
+ `shellcheck --severity=warning app/hooks/*.sh` if any hook is touched.
861
+
862
+ ## 8. Original Success Criteria and Outcome
863
+
864
+ | Criterion | Outcome |
865
+ |---|---|
866
+ | `ai-toolkit install --local --editors dsh` creates the workspace without manual editing | Not delivered; moved to the replacement plan |
867
+ | One session runs Claude Max, ChatGPT-backed Codex, and Gemini without provider API keys | Delivered with Gemini hosted through GitHub Copilot rather than a Google login |
868
+ | `validate.py --strict` and `audit_skills.py --ci` pass | Delivered for the standalone repositories; native target coverage remains in the replacement plan |
869
+ | Uninstall preserves user-authored files | Not applicable until ai-toolkit owns DSH artifacts; moved to the replacement plan |
870
+ | DSH remains opt-in | Delivered by separate packages and retained as a requirement of the replacement plan |
871
+
872
+ ## 9. Risks and Mitigation
873
+
874
+ | Risk | Impact | Mitigation |
875
+ |---|---|---|
876
+ | Upstream breaking changes (declared developer preview) | Generators break for users mid-release | Keep dsh strictly opt-in; never in `--editors all` defaults until it leaves preview |
877
+ | Anthropic changes its stance on spawned-CLI orchestration | Phase 0 premise invalidated | Fall back to ACP in JetBrains/Zed, where each agent owns its own auth by design |
878
+ | Preset schema churn | Phase 2 rework | Emit the minimum viable composition; keep display metadata in `preset.yml` where the contract is narrow and stable |
879
+ | Documentation drift across the nine mandated files | Broken user trust, per CLAUDE.md | Phase 5 is one atomic change with `validate.py --strict` as the gate |
880
+ | Silent skill loss from fail-closed frontmatter | Skills vanish with only a warning | Phase 1 gates land before phase 2 |
881
+
882
+ ## 10. Pre-Mortem
883
+
884
+ *It is six months out and this failed. What happened?*
885
+
886
+ 1. **We shipped dsh in the default editor set.** An upstream breaking change broke `install` for
887
+ every toolkit user, not just dsh users. Prevented by success criterion 5.
888
+ 2. **Phase 0 was skipped.** Phases 1-5 were built on the assumption that Max authenticates through
889
+ the spawned CLI, and it turned out to require an API key in practice. Prevented by making Q5 a
890
+ hard gate.
891
+ 3. **We mapped 44 agents onto 44 presets.** The preset surface is a session composition, not a
892
+ persona, so the emission produced 44 near-identical compositions nobody could maintain.
893
+ Prevented by section 3.2.
894
+ 4. **We became Cordis contributors.** Time went into upstream plugin work instead of the toolkit.
895
+ Prevented by treating dsh as an emission target with a fixed contract surface, never a fork.
896
+ 5. **A frontmatter regression silently dropped skills.** Nobody noticed because discovery only
897
+ warns. Prevented by phase 1.
898
+
899
+ ## 11. Archived Next Actions
900
+
901
+ No work should continue from this archived document. The scoped native install target is complete in [`dsh-native-install-target-plan.md`](dsh-native-install-target-plan.md). Reopen this record only if evidence about the 2026-08-26 validation needs correction.
902
+
903
+ ## Sources
904
+
905
+ - `deepseek-ai/deepseek-harness` @ `b150a55`, `0.1.1-rc.2`, MIT: `packages/skill/skill-filesystem`,
906
+ `packages/preset/agent-presets`, `packages/subagent/*`, `docs/`
907
+ - https://github.com/deepseek-ai/deepseek-harness
908
+ - https://deepseek.com/harness/en/
909
+ - `kb/reference/opencode-compatibility.md`: precedent for the emission-target contract
910
+ - `kb/reference/codex-cli-compatibility.md`: `.agents/skills` precedent
911
+ - `kb/reference/supported-tools-registry.md`
912
+
913
+ ## Related
914
+
915
+ - `kb/reference/opencode-compatibility.md`
916
+ - `kb/reference/codex-cli-compatibility.md`
917
+ - `kb/reference/architecture-overview.md`
918
+ - `kb/reference/supported-tools-registry.md`
919
+
920
+ ---
921
+
922
+ ## kb/history/completed/dsh-native-install-target-plan.md
923
+
924
+ ---
925
+ title: "Plan: Native DSH Install Target"
926
+ category: planning
927
+ service: ai-toolkit
928
+ tags:
929
+ - dsh
930
+ - deepseek-harness
931
+ - installer
932
+ - editor-target
933
+ - subscriptions
934
+ - lifecycle
935
+ - security
936
+ doc_type: plan
937
+ status: completed
938
+ created: "2026-08-27"
939
+ last_updated: "2026-09-01"
940
+ approved: "2026-08-28"
941
+ started: "2026-08-28"
942
+ completion: "Phase 3 of 3 complete"
943
+ completed: "2026-09-01"
944
+ predecessor: "kb/history/completed/dsh-integration-plan-superseded.md"
945
+ description: "Implementation plan for an explicit ai-toolkit DSH target that emits project skills and safely manages the published dsh-codex and dsh-orchestrator packages without handling vendor credentials."
946
+ ---
947
+
948
+ # Plan: Native DSH Install Target
949
+
950
+ ## Status
951
+
952
+ Approved on 2026-08-28 and completed on 2026-09-01.
953
+
954
+ Estimated size: **L (3 to 5 days)**. The runtime integrations already exist. The remaining work is installer ownership, lifecycle safety, validation, tests, and documentation.
955
+
956
+ Predecessor: [`dsh-integration-plan-superseded.md`](dsh-integration-plan-superseded.md).
957
+
958
+ ## Context
959
+
960
+ The subscription-backed runtime is already delivered in two standalone Apache-2.0 packages:
961
+
962
+ - `@softspark/dsh-codex@1.0.0` registers the DSH `codex` provider and delegates authentication, tools, thread state, and model execution to the locally installed Codex app server. See <https://github.com/softspark/dsh-codex>.
963
+ - `@softspark/dsh-orchestrator@1.0.1` registers bounded Claude Code and GitHub Copilot Gemini delegation through native vendor logins. It accepts no provider API keys. See <https://github.com/softspark/dsh-orchestrator>.
964
+
965
+ ai-toolkit does not expose `dsh` in its editor list, does not track DSH profile artifacts, and has no DSH-specific install, doctor, update, or uninstall contract. [PATH: bin/ai-toolkit.js:309]
966
+
967
+ The published packages currently require two explicit operations: install exact plugins into a named DSH profile, then copy `softspark-orchestrator` from the installed package into `$DSH_HOME/.agent-presets`. See the orchestrator setup guide at <https://github.com/softspark/dsh-orchestrator>.
968
+
969
+ ## Decision
970
+
971
+ The native target has two separate ownership surfaces:
972
+
973
+ 1. `ai-toolkit install --local --editors dsh` emits project-owned `.agents/skills` and validates DSH compatibility. It must not mutate `$DSH_HOME`, install npm packages, or inspect vendor credentials.
974
+ 2. `ai-toolkit dsh install --profile web` is the explicit profile mutation command. It installs exact reviewed package versions, copies the released preset, and records ownership in the existing ai-toolkit state model.
975
+
976
+ This split preserves the meaning of `--local`. It also makes global DSH changes impossible without a command that names DSH and the target profile.
977
+
978
+ `dsh` stays out of `--editors all`, auto-detection, default profiles, and global editor defaults while DSH remains a developer preview. Selecting `dsh` must be explicit.
979
+
980
+ ## Scope
981
+
982
+ ### Included
983
+
984
+ - Explicit project target under `--editors dsh`.
985
+ - Reuse of the existing `.agents/skills/<name>/SKILL.md` emission path.
986
+ - DSH-specific validation for fail-closed skill metadata and one-level discovery depth.
987
+ - Explicit `ai-toolkit dsh install`, `update`, `doctor`, and `uninstall` lifecycle commands.
988
+ - Exact installation of `@softspark/dsh-codex@1.0.0` and `@softspark/dsh-orchestrator@1.0.1` into a named DSH profile.
989
+ - Ownership-safe copy and update of `$DSH_HOME/.agent-presets/softspark-orchestrator`.
990
+ - State tracking through `~/.softspark/ai-toolkit/state.json`.
991
+ - Dry-run output, collision refusal, rollback, tests, registry metadata, and public documentation.
992
+
993
+ ### Excluded
994
+
995
+ - Direct Google AI Pro/Ultra, Gemini CLI OAuth, Antigravity, or Gemini API integration.
996
+ - Provider API keys, custom OAuth, token copying, credential-file reads, or login automation.
997
+ - Mapping all 44 ai-toolkit agents into DSH subagents.
998
+ - A new DSH skill generator. DSH already consumes `.agents/skills`.
999
+ - Automatic DSH installation from `--editors all`, auto-detection, or default install profiles.
1000
+ - Rewriting the released dsh-codex or dsh-orchestrator packages inside ai-toolkit.
1001
+ - MCP and hook bridging in the first native-target release.
1002
+ - Support for arbitrary DSH prereleases or unpinned community package versions.
1003
+
1004
+ ## Global Success Criteria
1005
+
1006
+ - [x] `ai-toolkit install --local --editors dsh` emits the complete managed skill catalog and makes no write under `$DSH_HOME`.
1007
+ - [x] `ai-toolkit dsh install --profile web` installs exact `@softspark/dsh-codex@1.0.0` and `@softspark/dsh-orchestrator@1.0.1` packages plus the released preset without manual file editing.
1008
+ - [x] Install, update, doctor, and uninstall preserve user-authored presets and unrelated DSH plugins.
1009
+ - [x] No command accepts, reads, copies, logs, or forwards provider credentials.
1010
+ - [x] `dsh` remains excluded from `--editors all`, auto-detection, default profiles, and default global editors.
1011
+ - [x] Offline, missing-runtime, collision, partial-install, and interrupted-update paths fail without leaving untracked artifacts.
1012
+ - [x] The full repository test, validation, skill-audit, and documentation gates pass.
1013
+
1014
+ ## Phase 1: Project Target and Fail-Closed Gates
1015
+
1016
+ Dependency: none.
1017
+
1018
+ Size: **M (1 to 2 days)**.
1019
+
1020
+ ### Phase 1 Success Criteria
1021
+
1022
+ - [x] CLI help and validation accept `dsh` only when named explicitly.
1023
+ - [x] `--editors all` resolves to the existing stable editor set and excludes `dsh`.
1024
+ - [x] Dry-run lists `.agents/skills` changes but writes nothing.
1025
+ - [x] Project installation emits every managed skill at one discovery level.
1026
+ - [x] Validation rejects camel-case invocation fields, non-boolean invocation values, invalid skill directory names, and nested `SKILL.md` locations.
1027
+ - [x] A read-only doctor check reports DSH, Codex, Claude Code, and Copilot executable availability without opening credential stores.
1028
+
1029
+ ### Phase 1 Completion Evidence
1030
+
1031
+ Completed on 2026-08-28 after sequential TDD, three spec review passes, and four quality-review repair cycles.
1032
+
1033
+ - Full repository suite: 1726/1726 tests.
1034
+ - Final spec review: 10/10 requirements approved.
1035
+ - Final quality review: 0 Critical, 0 Important.
1036
+ - Strict validator: 0 errors, 0 warnings.
1037
+ - Skill audit: 0 HIGH, 0 WARN.
1038
+ - DSH remains explicit-only, project-local, credential-blind, transactionally owned, and outside Phase 2 profile lifecycle behavior.
1039
+
1040
+ ### Phase 1 Tasks
1041
+
1042
+ | ID | Outcome | Affected files | Owner | Depends on |
1043
+ |---|---|---|---|---|
1044
+ | P1.1 | Add an explicit-only DSH editor capability separate from the stable `ALL_EDITORS` expansion | `bin/ai-toolkit.js`, `scripts/install.py`, `scripts/install_steps/ai_tools.py` | `backend-specialist` | none |
1045
+ | P1.2 | Reuse the managed Codex skill emitter for the DSH project surface without emitting unrelated Codex configuration | `scripts/generate_codex_skills.py`, `scripts/install_steps/ai_tools.py` | `backend-specialist` | P1.1 |
1046
+ | P1.3 | Enforce the DSH fail-closed metadata, name, and depth contract | `scripts/validate.py`, `tests/test_metadata_contracts.bats`, `tests/test_skills_native.bats` | `backend-specialist` | none |
1047
+ | P1.4 | Add read-only runtime and version diagnostics with no login automation | `scripts/doctor.py`, `tests/test_doctor_fix.bats`, `tests/test_dsh.bats` | `infrastructure-validator` | P1.1 |
1048
+ | P1.5 | Cover explicit selection, `all` exclusion, dry-run, idempotency, and project-only writes | `tests/test_dsh.bats`, `tests/test_install.bats`, `tests/test_install_profiles.bats` | `test-engineer` | P1.1, P1.2, P1.3, P1.4 |
1049
+
1050
+ ### Phase 1 Rollback and Scope Cut
1051
+
1052
+ Remove the explicit `dsh` selector and its focused tests. Existing Codex skill emission and both standalone DSH packages remain unchanged. If the fail-closed metadata gates reveal unrelated invalid skills, fix those skills before shipping rather than weakening the gate.
1053
+
1054
+ ## Phase 2: Explicit DSH Profile Lifecycle
1055
+
1056
+ Dependency: Phase 1 → Phase 2.
1057
+
1058
+ Size: **M (1 to 2 days)**.
1059
+
1060
+ ### Phase 2 Success Criteria
1061
+
1062
+ - [x] `ai-toolkit dsh install --profile web` performs preflight before the first mutation.
1063
+ - [x] The command installs exact reviewed package versions through the DSH plugin manager.
1064
+ - [x] The preset is copied from the installed orchestrator package, not reconstructed by ai-toolkit.
1065
+ - [x] Existing user-owned preset or plugin collisions stop the command with an actionable error.
1066
+ - [x] State records the DSH home, profile, package versions, preset path, and managed content hash without recording credentials.
1067
+ - [x] Update replaces only artifacts whose ownership and previous hash match state.
1068
+ - [x] Uninstall removes only ai-toolkit-managed DSH artifacts and leaves unrelated profile content unchanged.
1069
+ - [x] Interrupted or failed installation restores the pre-operation state or reports a deterministic recovery command.
1070
+
1071
+ ### Phase 2 Completion Evidence
1072
+
1073
+ Completed on 2026-08-31 after adversarial transaction, concurrency, rollback, path-swap, state-CAS, and credential-boundary testing.
1074
+
1075
+ - Full repository suite on the final isolated DSH scope: 1846/1846 tests.
1076
+ - Phase 2 spec review: approved with zero must-fix gaps.
1077
+ - Defensive security review: approved with zero findings.
1078
+ - Code quality review: 0 Critical, 0 Important, 0 Suggestions.
1079
+ - Strict validator: 0 errors, 0 warnings on the verified DSH tree.
1080
+ - Skill audit: 0 HIGH, 0 WARN.
1081
+ - Exact reviewed pins are DSH `0.1.1-rc.2`, dsh-codex `1.0.0`, and dsh-orchestrator `1.0.1`.
1082
+ - Lifecycle state stores canonical package and preset ownership metadata without credentials or package contents.
1083
+
1084
+ ### Phase 2 Tasks
1085
+
1086
+ | ID | Outcome | Affected files | Owner | Depends on |
1087
+ |---|---|---|---|---|
1088
+ | P2.1 | Freeze the pinned DSH plugin add, update, and removal contract against DSH `0.1.1-rc.2` in bounded fixtures | `scripts/install_steps/dsh.py`, `tests/fixtures/dsh/`, `tests/test_dsh.bats` | `backend-specialist` | Phase 1 |
1089
+ | P2.2 | Implement explicit profile install, update, doctor, and uninstall dispatch with `web` as the documented default profile | `bin/ai-toolkit.js`, `scripts/install.py`, `scripts/install_steps/dsh.py`, `scripts/uninstall.py` | `command-expert` | P2.1 |
1090
+ | P2.3 | Extend state tracking with DSH profile and managed-preset ownership | `scripts/install_steps/install_state.py`, `kb/reference/manifest-install.md`, `tests/test_install_state.bats` | `backend-specialist` | P2.1 |
1091
+ | P2.4 | Add atomic preset copy, collision refusal, hash verification, and recovery behavior | `scripts/install_steps/dsh.py`, `tests/test_dsh.bats`, `tests/test_uninstall_recovery.bats` | `backend-specialist` | P2.2, P2.3 |
1092
+ | P2.5 | Audit command construction, environment filtering, logs, and state for credential exposure | `scripts/install_steps/dsh.py`, `scripts/uninstall.py`, `tests/test_dsh.bats` | `security-auditor` | P2.2, P2.4 |
1093
+ | P2.6 | Exercise clean install, repeat install, update, collision, offline, interruption, and uninstall with fake DSH binaries and isolated roots | `tests/test_dsh.bats`, `tests/test_uninstall_ai_tools.bats`, `tests/fixtures/dsh/` | `test-engineer` | P2.2, P2.3, P2.4, P2.5 |
1094
+
1095
+ ### Phase 2 Rollback and Scope Cut
1096
+
1097
+ Disable the lifecycle subcommand while retaining the Phase 1 project target and read-only doctor output. Users can continue following the standalone package installation guides. Never recover from a lifecycle bug by deleting an unowned preset or profile.
1098
+
1099
+ ## Phase 3: Registry, Documentation, and Release Qualification
1100
+
1101
+ Dependency: Phase 2 → Phase 3.
1102
+
1103
+ Size: **S to M (1 day)**.
1104
+
1105
+ ### Phase 3 Success Criteria
1106
+
1107
+ - [x] DSH has one opt-in registry entry with pinned docs and release-note sources.
1108
+ - [x] Compatibility documentation distinguishes project emission, explicit profile mutation, vendor authentication, and unsupported Google routes.
1109
+ - [x] README, CLI help, architecture, supported-tools registry, manifest install reference, and `llms.txt` describe the same commands and boundaries.
1110
+ - [x] An isolated real-profile qualification installs the two published packages, selects the released preset, and completes Codex-to-Claude plus Codex-to-Copilot-Gemini delegation.
1111
+ - [x] No release is tagged while focused tests, full tests, validation, skill audit, ShellCheck, or generated-document checks are red.
1112
+
1113
+ ### Phase 3 Completion Evidence
1114
+
1115
+ Completed on 2026-09-01 after exact-package pre-tag and post-release qualification.
1116
+
1117
+ - Full repository suite: 1920/1920 tests.
1118
+ - Strict validator: 0 errors and 0 warnings; skill audit: 0 HIGH and 0 WARN.
1119
+ - ShellCheck, Apache-2.0 licensing, SARIF, public-surface, ecosystem, npm audit, and package dry-run gates passed.
1120
+ - `@softspark/dsh-orchestrator@1.0.1` published with SLSA provenance after both native-login marker tools completed through a Codex parent.
1121
+ - The exact npm registry package repeated both Claude Code and Copilot Gemini child/parent marker roundtrips, with no provider API key handling.
1122
+ - The isolated DSH process stopped cleanly and the unrelated profile fixture remained intact.
1123
+
1124
+ ### Phase 3 Tasks
1125
+
1126
+ | ID | Outcome | Affected files | Owner | Depends on |
1127
+ |---|---|---|---|---|
1128
+ | P3.1 | Add the opt-in DSH registry and drift-monitoring contract | `scripts/ecosystem_tools.json`, `tests/test_ecosystem_doctor.bats` | `technical-researcher` | Phase 2 |
1129
+ | P3.2 | Publish one compatibility contract and synchronize all user-facing command surfaces | `kb/reference/dsh-compatibility.md`, `kb/reference/supported-tools-registry.md`, `kb/reference/architecture-overview.md`, `kb/reference/manifest-install.md`, `README.md`, `CLAUDE.md`, `llms.txt`, `bin/ai-toolkit.js` | `documenter` | P3.1 |
1130
+ | P3.3 | Run isolated end-to-end qualification with real DSH and published packages, then record evidence | `kb/reference/dsh-compatibility.md`, `kb/procedures/release-verification-sop.md` | `infrastructure-validator` | P3.2 |
1131
+ | P3.4 | Run focused and full repository gates and assess regression blast radius | `tests/test_dsh.bats`, `tests/test_cli.bats`, `tests/test_install.bats`, `tests/test_uninstall_ai_tools.bats`, `scripts/validate.py`, `scripts/audit_skills.py` | `qa-automation-engineer` | P3.2, P3.3 |
1132
+ | P3.5 | Review final security boundaries and veto release on credential or ownership regressions | `scripts/install_steps/dsh.py`, `scripts/install_steps/install_state.py`, `scripts/uninstall.py`, `kb/reference/dsh-compatibility.md`, `tests/test_dsh.bats` | `security-architect` | P3.3, P3.4 |
1133
+
1134
+ ### Phase 3 Rollback and Scope Cut
1135
+
1136
+ Do not tag or publish the ai-toolkit release. Keep the published standalone `@softspark/dsh-codex@1.0.0` and `@softspark/dsh-orchestrator@1.0.1` packages as the supported installation route. If upstream DSH drifts during qualification, retain the registry entry as unsupported-preview metadata and remove the user-facing install command until compatibility is restored.
1137
+
1138
+ ## Dependencies
1139
+
1140
+ ```text
1141
+ Phase 1 → Phase 2 → Phase 3
1142
+ ```
1143
+
1144
+ Within phases:
1145
+
1146
+ ```text
1147
+ P1.1 → P1.2 → P1.5
1148
+ P1.3 ─────────→ P1.5
1149
+ P1.4 ─────────→ P1.5
1150
+
1151
+ P2.1 → P2.2 → P2.4 → P2.5 → P2.6
1152
+ ↘ P2.3 ↗
1153
+
1154
+ P3.1 → P3.2 → P3.3 → P3.4 → P3.5
1155
+ ```
1156
+
1157
+ No phase begins until the previous phase meets its success criteria. Phase 1 can ship as project-only compatibility without Phase 2. Phase 2 can remain unreleased if real-profile qualification fails.
1158
+
1159
+ ## Requirement Traceability
1160
+
1161
+ | Requirement | Tasks |
1162
+ |---|---|
1163
+ | Explicit DSH project target | P1.1, P1.2, P1.5 |
1164
+ | DSH excluded from defaults and `all` | P1.1, P1.5 |
1165
+ | Fail-closed skill discovery | P1.3, P1.5 |
1166
+ | No credential handling | P1.4, P2.5, P3.5 |
1167
+ | Exact package installation | P2.1, P2.2, P2.6 |
1168
+ | Managed preset lifecycle | P2.3, P2.4, P2.6 |
1169
+ | Ownership-safe uninstall | P2.3, P2.4, P2.6 |
1170
+ | Registry and documentation parity | P3.1, P3.2 |
1171
+ | Real subscription-backed smoke test | P3.3, P3.4 |
1172
+ | Release blocked on red gates | P3.4, P3.5 |
1173
+
1174
+ ## Verification
1175
+
1176
+ ### Focused gates
1177
+
1178
+ ```bash
1179
+ bats tests/test_dsh.bats
1180
+ bats tests/test_install.bats
1181
+ bats tests/test_install_profiles.bats
1182
+ bats tests/test_install_state.bats
1183
+ bats tests/test_uninstall_ai_tools.bats
1184
+ bats tests/test_uninstall_recovery.bats
1185
+ ```
1186
+
1187
+ ### Repository gates
1188
+
1189
+ ```bash
1190
+ python3 scripts/validate.py --strict
1191
+ python3 scripts/audit_skills.py --ci
1192
+ python3 scripts/ecosystem_doctor.py
1193
+ npm test
1194
+ ```
1195
+
1196
+ Run ShellCheck when a shell fixture, hook, or command wrapper changes. Run the existing generated-document drift checks before commit.
1197
+
1198
+ ### Isolated runtime qualification
1199
+
1200
+ Use a new task-specific `DSH_HOME` and DSH profile. Do not replace `HOME` and do not reuse the maintainer's regular DSH profile.
1201
+
1202
+ Verify these observations:
1203
+
1204
+ 1. Project installation emits the full managed skill catalog and no nested skill entry.
1205
+ 2. Profile installation records exact package versions and one managed preset.
1206
+ 3. Codex reports ChatGPT-owned authentication through its own status command.
1207
+ 4. Claude Code and Copilot own their login state; ai-toolkit state and logs contain no credential values.
1208
+ 5. A Codex parent delegates one bounded marker task to Claude Code and one to Copilot Gemini.
1209
+ 6. Uninstall returns the isolated profile to its pre-install inventory while preserving an injected user-owned preset fixture.
1210
+
1211
+ ## Pre-Mortem
1212
+
1213
+ | Failure mode | Probability | Impact | Mitigation |
1214
+ |---|---|---|---|
1215
+ | Generic `install --local` mutates a global DSH profile | Medium | High | Separate project emission from the explicit `ai-toolkit dsh install` command and test zero `$DSH_HOME` writes in Phase 1 |
1216
+ | `--editors all` silently gains a developer-preview runtime | Medium | High | Keep explicit-only editors in a separate registry and assert expansion output in tests |
1217
+ | Preset update overwrites user edits or a same-name user preset | Medium | High | Require ownership state plus matching previous hash; refuse every ambiguous collision |
1218
+ | Partial DSH plugin installation leaves one provider without the matching preset | Medium | High | Preflight all inputs, snapshot managed state, order mutations, and implement deterministic recovery |
1219
+ | Installer logs or state capture vendor credentials | Low | Critical | Never invoke login flows, never read credential files, redact command output, and audit fixtures for secret-shaped data |
1220
+ | DSH prerelease changes plugin or preset discovery semantics | High | High | Pin the reviewed DSH version, run ecosystem drift checks, and block release on real-profile qualification failure |
1221
+ | Reusing Codex-adapted skills produces incorrect DSH delegation instructions | Medium | Medium | Validate representative delegation-heavy skills in the Codex parent and add a DSH-specific adapter only if evidence requires it |
1222
+ | Copilot changes Gemini model availability or credit policy | Medium | Medium | Treat model and credit policy as doctor-visible compatibility data, not a promise hardcoded into ai-toolkit behavior |
1223
+
1224
+ ## Agent Assignments
1225
+
1226
+ | Workstream | Primary agent | Review agent | Reason |
1227
+ |---|---|---|---|
1228
+ | CLI and installer plumbing | `backend-specialist` | `tech-lead` | Python and Node entry-point integration with existing installer layers |
1229
+ | Command UX | `command-expert` | `product-manager` | Explicit mutation semantics, dry-run output, and actionable errors |
1230
+ | Runtime preflight and qualification | `infrastructure-validator` | `technical-researcher` | DSH profile behavior, pinned compatibility, and observable smoke evidence |
1231
+ | Security and ownership | `security-auditor` | `security-architect` | Credential boundary, collision refusal, state minimization, and release veto |
1232
+ | Test automation | `test-engineer` | `qa-automation-engineer` | Fake-runtime fixtures, lifecycle integration tests, and full regression gates |
1233
+ | Documentation | `documenter` | `fact-checker` | Cross-file parity and evidence-backed compatibility claims |
1234
+
1235
+ ## Approval Checkpoint
1236
+
1237
+ Implementation starts only after the user approves:
1238
+
1239
+ 1. The two-command split between project emission and explicit DSH profile mutation.
1240
+ 2. Excluding DSH from `--editors all` and auto-detection while upstream remains a developer preview.
1241
+ 3. Pinning the native target to DSH `0.1.1-rc.2`, dsh-codex `1.0.0`, and dsh-orchestrator `1.0.1`.
1242
+ 4. Deferring 44-agent mapping, MCP bridging, and hook bridging outside this plan.
1243
+
1244
+ ## Sources
1245
+
1246
+ - `kb/history/completed/dsh-integration-plan-superseded.md`
1247
+ - `bin/ai-toolkit.js`
1248
+ - `scripts/install.py`
1249
+ - `scripts/install_steps/ai_tools.py`
1250
+ - `scripts/install_steps/install_state.py`
1251
+ - `scripts/ecosystem_tools.json`
1252
+ - <https://github.com/softspark/dsh-codex>
1253
+ - <https://github.com/softspark/dsh-orchestrator>
1254
+ - <https://github.com/deepseek-ai/deepseek-harness>
1255
+
1256
+ ---
1257
+
592
1258
  ## kb/history/completed/ecosystem-deep-sweep-20260423.md
593
1259
 
594
1260
  ---
@@ -6270,10 +6936,10 @@ title: "SOP: Ecosystem Sync"
6270
6936
  category: procedures
6271
6937
  service: ai-toolkit
6272
6938
  tags: [sop, ecosystem, editors, generators, drift-detection, sync]
6273
- version: "1.1.0"
6939
+ version: "1.2.0"
6274
6940
  created: "2026-04-23"
6275
- last_updated: "2026-07-10"
6276
- description: "Quarterly (or event-triggered) sync procedure that detects documentation and capability drift in supported tools (Claude Code, Claude app, and 11 editors), analyses our generators and skills for missing features, and walks through the migration + generator-update workflow."
6941
+ last_updated: "2026-08-31"
6942
+ description: "Quarterly or event-triggered sync procedure for the 14 registry tools: Claude Code, Claude app, explicit-preview DSH, and 11 default editor integrations."
6277
6943
  ---
6278
6944
 
6279
6945
  # SOP: Ecosystem Sync
@@ -6293,7 +6959,7 @@ Keeps ai-toolkit aligned with the tools it integrates with. When an editor adds
6293
6959
  ## Quick Reference
6294
6960
 
6295
6961
  ```bash
6296
- # Full check (all 13 tools, online)
6962
+ # Full check (all 14 registry tools, online)
6297
6963
  python3 scripts/ecosystem_doctor.py --format text
6298
6964
 
6299
6965
  # Single tool
@@ -6315,11 +6981,13 @@ python3 scripts/ecosystem_doctor.py --offline --format text
6315
6981
 
6316
6982
  | File | Purpose |
6317
6983
  |------|---------|
6318
- | `scripts/ecosystem_tools.json` | Authoritative registry: 13 tools with doc URLs, config paths, our generators, capability markers |
6984
+ | `scripts/ecosystem_tools.json` | Authoritative registry: 14 tools with doc URLs, config paths, our generators, capability markers |
6319
6985
  | `benchmarks/ecosystem-doctor-snapshot.json` | Last-seen state (headings, content hash, markers, version) — updated via `--update` |
6320
6986
  | `scripts/ecosystem_doctor.py` | Drift detector |
6321
6987
  | `kb/reference/supported-tools-registry.md` | Human-readable view of the registry |
6322
6988
 
6989
+ DSH is counted because the ecosystem doctor tracks its upstream documentation and reviewed version. It remains an explicit developer-preview target, not a default editor integration, and stays outside `--editors all` and auto-detection.
6990
+
6323
6991
  ---
6324
6992
 
6325
6993
  ## Phase 1: Run the Doctor
@@ -6840,7 +7508,7 @@ python3 scripts/validate.py --strict
6840
7508
  ai-toolkit plugin list # show available packs
6841
7509
  ai-toolkit plugin install --editor claude <name> # install for Claude Code global target
6842
7510
  ai-toolkit plugin install --editor codex <name> # install for Codex global target
6843
- ai-toolkit plugin install --editor all --all # install all 12 packs for both runtimes
7511
+ ai-toolkit plugin install --editor all --all # install all available packs for all supported editors
6844
7512
  ai-toolkit plugin update --editor all --all # re-apply all installed packs after toolkit updates
6845
7513
  ai-toolkit plugin clean <name> # prune data older than 90 days
6846
7514
  ai-toolkit plugin clean <name> --days 30 # custom retention
@@ -7364,10 +8032,10 @@ title: "SOP: Release Preparation"
7364
8032
  category: procedures
7365
8033
  service: ai-toolkit
7366
8034
  tags: [sop, release, version, publish, changelog, semver, provenance, sarif, ecosystem, shellcheck]
7367
- version: "1.14.0"
8035
+ version: "1.15.0"
7368
8036
  created: "2026-04-10"
7369
- last_updated: "2026-08-06"
7370
- description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, and checksum-pin checks added in v2.8.0, the single-run npm test discipline added in v1.8.0, the ecosystem-sync gate added in v1.9.0, the registry-vs-generators drift gate added in v1.10.0, the mandatory pre-tag ShellCheck gate added in v1.11.0 (publish.yml does not run ShellCheck, so a hook lint failure can publish while reddening main CI see the v4.5.1 postmortem in Phase 5), the pre-push tag assertions added in v1.12.0 after v4.19.0 was tagged on the wrong commit (Phase 7), and the licensing gate added in v1.13.0 with the move to Apache-2.0 (Phase 5c)."
8037
+ last_updated: "2026-09-02"
8038
+ description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, branch CI, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, checksum-pin, ShellCheck, licensing, exact-tag assertions, and a green Ubuntu/macOS branch-CI gate before any release tag is created."
7371
8039
  ---
7372
8040
 
7373
8041
  # SOP: Release Preparation
@@ -7429,16 +8097,38 @@ python3 scripts/ecosystem_doctor.py --offline --check || { echo "STALE ecosystem
7429
8097
  # 5c. Licensing gate — SPDX headers, LICENSE, NOTICE, manifest consistency
7430
8098
  npx bats tests/test_licensing.bats || { echo "LICENSING GATE FAILED"; exit 1; }
7431
8099
 
7432
- # 6. Commit + tag + push
8100
+ # 6. Commit, push branch, and wait for the exact commit's full CI
7433
8101
  git add -A && git commit -m "chore: release vX.Y.Z"
7434
- git tag vX.Y.Z
8102
+ RELEASE_SHA=$(git rev-parse HEAD)
8103
+ git push origin main || { echo "FAIL: release commit push failed"; exit 1; }
8104
+ RUN_ID=""
8105
+ for ATTEMPT in 1 2 3 4 5; do
8106
+ RUN_ID=$(gh run list --workflow ci.yml --event push --commit "$RELEASE_SHA" \
8107
+ --limit 1 --json databaseId --jq '.[0].databaseId')
8108
+ [ -n "$RUN_ID" ] && break
8109
+ echo "Waiting for CI run registration ($ATTEMPT/5)" >&2
8110
+ [ "$ATTEMPT" -eq 5 ] || sleep 60
8111
+ done
8112
+ test -n "$RUN_ID" || { echo "FAIL: CI run not found for release commit"; exit 1; }
8113
+ gh run watch "$RUN_ID" --exit-status \
8114
+ || { echo "FAIL: release commit CI failed"; exit 1; }
8115
+ for OS in ubuntu-latest macos-latest; do
8116
+ gh run view "$RUN_ID" --json jobs \
8117
+ --jq ".jobs[] | select(.name == \"Bats test suite ($OS)\") | .conclusion" \
8118
+ | grep -qx success || { echo "FAIL: $OS test job not green"; exit 1; }
8119
+ done
8120
+ test "$(git rev-parse HEAD)" = "$RELEASE_SHA" || { echo "FAIL: local HEAD changed during CI"; exit 1; }
8121
+ git fetch origin main || { echo "FAIL: origin/main refresh failed"; exit 1; }
8122
+ test "$(git rev-parse origin/main)" = "$RELEASE_SHA" || { echo "FAIL: origin/main changed during CI"; exit 1; }
8123
+
8124
+ # 6a. Only green branch CI authorizes tag creation
8125
+ git tag vX.Y.Z "$RELEASE_SHA"
7435
8126
 
7436
- # 6a. Assert the tag before pushing it (v4.19.0 postmortem, Phase 7)
7437
- test "$(git rev-parse vX.Y.Z)" = "$(git rev-parse HEAD)" || { echo "FAIL: tag not on HEAD"; exit 1; }
8127
+ # 6b. Assert the tag before pushing it (v4.19.0 postmortem, Phase 7)
8128
+ test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA" || { echo "FAIL: tag not on tested release commit"; exit 1; }
7438
8129
  git show --no-patch --format=%s vX.Y.Z | grep -qx "chore: release vX.Y.Z" || { echo "FAIL: tag not on release commit"; exit 1; }
7439
8130
 
7440
- # 6b. Branch first, then the single tag by full ref. Never --tags.
7441
- git push origin main
8131
+ # 6c. Push the single tag by full ref. Never --tags.
7442
8132
  git push origin refs/tags/vX.Y.Z
7443
8133
  ```
7444
8134
 
@@ -7854,23 +8544,60 @@ git commit -m "chore: release vX.Y.Z"
7854
8544
 
7855
8545
  ---
7856
8546
 
7857
- ## Phase 7: Tag and Push
8547
+ ## Phase 7: Push Branch, Verify CI, Tag, and Push Tag
7858
8548
 
7859
8549
  ```bash
7860
- git tag vX.Y.Z
8550
+ RELEASE_SHA=$(git rev-parse HEAD)
8551
+ git push origin main || { echo "FAIL: release commit push failed"; exit 1; }
8552
+
8553
+ # Bind the gate to the exact release commit. GitHub run registration is
8554
+ # asynchronous, so retry at most five times and log every attempt.
8555
+ RUN_ID=""
8556
+ for ATTEMPT in 1 2 3 4 5; do
8557
+ RUN_ID=$(gh run list --workflow ci.yml --event push --commit "$RELEASE_SHA" \
8558
+ --limit 1 --json databaseId --jq '.[0].databaseId')
8559
+ [ -n "$RUN_ID" ] && break
8560
+ echo "Waiting for CI run registration ($ATTEMPT/5)" >&2
8561
+ [ "$ATTEMPT" -eq 5 ] || sleep 60
8562
+ done
8563
+ test -n "$RUN_ID" || { echo "FAIL: CI run not found for release commit"; exit 1; }
8564
+ gh run watch "$RUN_ID" --exit-status \
8565
+ || { echo "FAIL: release commit CI failed"; exit 1; }
8566
+
8567
+ # publish.yml is Ubuntu-only. Require both full CI matrix jobs before creating
8568
+ # the tag so a green publish job cannot bypass a red macOS test.
8569
+ for OS in ubuntu-latest macos-latest; do
8570
+ gh run view "$RUN_ID" --json jobs \
8571
+ --jq ".jobs[] | select(.name == \"Bats test suite ($OS)\") | .conclusion" \
8572
+ | grep -qx success || { echo "FAIL: $OS test job not green"; exit 1; }
8573
+ done
8574
+
8575
+ # Refuse to tag if either local or remote main moved while CI was running.
8576
+ test "$(git rev-parse HEAD)" = "$RELEASE_SHA" \
8577
+ || { echo "FAIL: local HEAD changed during CI"; exit 1; }
8578
+ git fetch origin main || { echo "FAIL: origin/main refresh failed"; exit 1; }
8579
+ test "$(git rev-parse origin/main)" = "$RELEASE_SHA" \
8580
+ || { echo "FAIL: origin/main changed during CI"; exit 1; }
8581
+
8582
+ git tag vX.Y.Z "$RELEASE_SHA"
7861
8583
 
7862
8584
  # Assert the tag before pushing it. Both checks are one line each and both
7863
8585
  # have caught a real broken release.
7864
- test "$(git rev-parse vX.Y.Z)" = "$(git rev-parse HEAD)" \
7865
- || { echo "FAIL: tag is not on HEAD"; exit 1; }
8586
+ test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA" \
8587
+ || { echo "FAIL: tag is not on the tested release commit"; exit 1; }
7866
8588
  git show --no-patch --format=%s vX.Y.Z | grep -qx "chore: release vX.Y.Z" \
7867
8589
  || { echo "FAIL: tag is not on the chore: release commit"; exit 1; }
7868
8590
 
7869
- # Push the branch, then the single release tag by its full ref.
7870
- git push origin main
8591
+ # Push the single release tag by its full ref.
7871
8592
  git push origin refs/tags/vX.Y.Z
7872
8593
  ```
7873
8594
 
8595
+ **Why branch CI comes before the tag (v4.30.2 postmortem).** The publish
8596
+ workflow runs only on Ubuntu and can publish while the separate macOS matrix job
8597
+ is red. `v4.30.2` exposed this with a macOS-only DSH timing failure. A release
8598
+ commit must therefore pass the complete Ubuntu/macOS branch workflow before its
8599
+ tag exists; a successful publish workflow is not a substitute for green CI.
8600
+
7874
8601
  **Why the assertions (v4.19.0 postmortem).** v4.19.0 was tagged on a commit
7875
8602
  that contained only a KB document and still carried `package.json` version
7876
8603
  `4.18.0`; the actual release sat in the commit above it under a recycled
@@ -7941,10 +8668,12 @@ git push origin --delete vX.Y.Z
7941
8668
  | 15a | Licensing gate | `npx bats tests/test_licensing.bats` | 7/7 — SPDX headers, LICENSE, NOTICE, npm `files`, manifest consistency |
7942
8669
  | 16 | Tests | `git add -A kb/` if the KB changed, then `npm test` | All pass |
7943
8670
  | 17 | Commit | `git commit` | Clean working tree |
7944
- | 18 | Tag | `git tag vX.Y.Z` | Tag exists |
7945
- | 18a | Tag is on HEAD | `test "$(git rev-parse vX.Y.Z)" = "$(git rev-parse HEAD)"` | Exit 0 |
7946
- | 18b | Tag is on the release commit | `git show --no-patch --format=%s vX.Y.Z` | Reads `chore: release vX.Y.Z` |
7947
- | 19 | Push branch, then the single tag | `git push origin main && git push origin refs/tags/vX.Y.Z` | CI triggered with `id-token: write`. Never `--tags`. |
8671
+ | 18 | Push branch | `git push origin main` | Exact release commit is on `origin/main` |
8672
+ | 18a | Full branch CI | `gh run watch "$RUN_ID" --exit-status` plus matrix job assertions | Ubuntu and macOS Bats jobs both conclude `success` |
8673
+ | 19 | Tag | `git tag vX.Y.Z` | Tag exists only after green branch CI |
8674
+ | 19a | Tag is on tested SHA | `test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA"` | Exit 0 |
8675
+ | 19b | Tag is on the release commit | `git show --no-patch --format=%s vX.Y.Z` | Reads `chore: release vX.Y.Z` |
8676
+ | 20 | Push the single tag | `git push origin refs/tags/vX.Y.Z` | Publish CI triggered with `id-token: write`. Never `--tags`. |
7948
8677
 
7949
8678
  ---
7950
8679
 
@@ -7954,11 +8683,11 @@ git push origin --delete vX.Y.Z
7954
8683
  title: "SOP: Release Verification"
7955
8684
  category: procedures
7956
8685
  service: ai-toolkit
7957
- tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif]
7958
- version: "1.7.0"
8686
+ tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif, dsh]
8687
+ version: "1.8.0"
7959
8688
  created: "2026-04-08"
7960
- last_updated: "2026-07-14"
7961
- description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit. Verifies CLI, native Codex and GitHub Copilot surfaces, Claude app export, doctor, validation, tests, eject, provenance, SARIF, and per-skill permissions."
8689
+ last_updated: "2026-09-01"
8690
+ description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit. Verifies CLI, native Codex and GitHub Copilot surfaces, explicit DSH lifecycle, Claude app export, doctor, validation, tests, eject, provenance, SARIF, and per-skill permissions."
7962
8691
  ---
7963
8692
 
7964
8693
  # SOP: Release Verification
@@ -7983,7 +8712,7 @@ Verifies all critical paths from the user's perspective.
7983
8712
 
7984
8713
  ## Quick Checklist (TL;DR)
7985
8714
 
7986
- 14 commands if all pass, the release is ready:
8715
+ The 14 core commands below must pass. Releases that change DSH must also complete Phase 10.
7987
8716
 
7988
8717
  ```bash
7989
8718
  # Pre-commit (Phase 0)
@@ -8396,6 +9125,36 @@ app-native rules skill, bundled agents/skills, and plugin-relative Cowork hooks.
8396
9125
 
8397
9126
  ---
8398
9127
 
9128
+ ## Phase 10: Explicit DSH Qualification (v4.30.0+)
9129
+
9130
+ Run this phase whenever the release changes the `dsh` target, package pins, preset lifecycle, or DSH compatibility documentation. Use a new task-specific `DSH_HOME`; never replace `HOME` or reuse a regular profile.
9131
+
9132
+ Prerequisites: DSH `0.1.1-rc.2`, pnpm `>=11.7.0,<12.0.0`, Codex logged in through ChatGPT, Claude Code logged in natively, and GitHub Copilot CLI logged in natively. Do not supply provider API keys.
9133
+
9134
+ ```bash
9135
+ DSH_SMOKE_ROOT="$(mktemp -d)"
9136
+ export DSH_HOME="$DSH_SMOKE_ROOT/dsh-home"
9137
+
9138
+ ai-toolkit dsh install --profile web
9139
+ ai-toolkit dsh doctor --profile web
9140
+ dsh --profile web --host 127.0.0.1 --port 0 --no-open
9141
+ ```
9142
+
9143
+ In a new `softspark-orchestrator` session, select the `codex` provider and run two standalone marker prompts:
9144
+
9145
+ 1. `subagent_claude_code` returns an exact child marker, then the Codex parent returns its exact completion marker.
9146
+ 2. `subagent_gemini_copilot` returns an exact child marker, then the Codex parent returns its exact completion marker.
9147
+
9148
+ Stop DSH, then remove only the managed profile artifacts:
9149
+
9150
+ ```bash
9151
+ ai-toolkit dsh uninstall --profile web --yes
9152
+ ```
9153
+
9154
+ **Verify:** both tool results have `isError=false`, both turns end as `completed`, `doctor` reports no recovery requirement before uninstall, and an unrelated preset fixture remains unchanged. Preserve only redacted event sequence evidence; never attach credentials, auth files, or full private prompts.
9155
+
9156
+ ---
9157
+
8399
9158
  ## Troubleshooting
8400
9159
 
8401
9160
  ### `ai-toolkit: command not found`
@@ -8817,17 +9576,17 @@ title: "AI Toolkit - Architecture Overview"
8817
9576
  category: reference
8818
9577
  service: ai-toolkit
8819
9578
  tags: [architecture, overview, design, structure]
8820
- version: "1.8.0"
9579
+ version: "1.10.0"
8821
9580
  created: "2026-03-23"
8822
- last_updated: "2026-08-19"
8823
- description: "Architecture of ai-toolkit: directory layout, Claude app export, global install model, editor-aware MCP install, Codex translation layer, skill tiers, and integration with projects."
9581
+ last_updated: "2026-09-01"
9582
+ description: "Architecture of ai-toolkit: install ownership, runtime adapters, the explicit DSH target, skill tiers, and project integration."
8824
9583
  ---
8825
9584
 
8826
9585
  # AI Toolkit Architecture
8827
9586
 
8828
9587
  ## Purpose
8829
9588
 
8830
- Shared, project-agnostic AI development toolkit for Claude Code, Claude Chat/Cowork, and compatible assistants such as Cursor, Devin, Copilot, Gemini, Cline, Roo/Zoo Code, Aider, Augment, and Google Antigravity. Provides agents, skills, lifecycle hooks, persona presets, and runtime-specific plugin packaging.
9589
+ Shared, project-agnostic AI development toolkit for Claude Code, Claude Chat/Cowork, compatible assistants, and the explicit developer-preview DSH target. Provides agents, skills, lifecycle hooks, persona presets, and runtime-specific plugin packaging.
8831
9590
 
8832
9591
  ## Design Principles
8833
9592
 
@@ -8931,6 +9690,7 @@ Machine (global) Project (local)
8931
9690
  **`ai-toolkit install --local`** — run per project. Always installs Claude Code configs (CLAUDE.md, settings.local.json, constitution.md, language rules). Editor configs are opt-in via `--editors`:
8932
9691
  - `--editors all` — install all 11 editors (Cursor, Windsurf, Cline, Roo, Aider, Augment, Copilot, Antigravity, Codex, Gemini, opencode)
8933
9692
  - `--editors cursor,aider` — install only selected editors
9693
+ - `--editors dsh` requires explicit selection. Its DSH-specific output is project `.agents/skills`; the normal `--local` Claude files, detected language rules, and generic project outputs still apply. DSH is excluded from `all`, auto-detection, and defaults.
8934
9694
  - (no flag) — auto-detect from existing project files; `update --local` picks up whatever editors already have configs
8935
9695
 
8936
9696
  Each editor gets its documented directory-based format. Copilot receives root
@@ -8953,6 +9713,10 @@ packs can layer their rules, skills, and hooks onto that Codex user target.
8953
9713
 
8954
9714
  Claude Chat/Desktop/Cowork is deliberately outside `--editors`: the app does not scan filesystem configuration under `~/.claude`. `ai-toolkit claude-app export` creates a self-contained plugin ZIP with skills, agents, Cowork hooks, app-native rules, and bundled hook dependencies. It also emits the compact text that users paste into Cowork global instructions. Updating requires re-export and re-upload because the app owns its plugin store.
8955
9715
 
9716
+ DSH profile mutation is also outside generic installation. `ai-toolkit dsh install|update|doctor|uninstall --profile web` names both the integration and profile. It manages only `@softspark/dsh-codex@1.0.0`, `@softspark/dsh-orchestrator@1.0.1`, the released preset, and their ownership record. Vendor CLIs own login and credentials. DSH `0.1.1-rc.2` is the only reviewed host version.
9717
+
9718
+ Both DSH preview paths are read-only. Project `--dry-run` resolves `extends` without persisting its lockfile and changes no project or `DSH_HOME` entry. Profile lifecycle `--dry-run` changes no package, preset, state, profile, or authentication surface.
9719
+
8956
9720
  If a project already has `.mcp.json`, local install mirrors its `mcpServers`
8957
9721
  entries into `.claude/settings.local.json` plus any selected editors with
8958
9722
  project-scoped native MCP files: `.cursor/mcp.json`, `.github/mcp.json`,
@@ -8964,6 +9728,10 @@ project-scoped native MCP files: `.cursor/mcp.json`, `.github/mcp.json`,
8964
9728
  |---------|--------|-------------|
8965
9729
  | `install` | `~/.claude/` | First-time: per-file symlinks + JSON merge + marker injection + rules |
8966
9730
  | `install --local` | `./` | Claude Code configs + editors via `--editors` (auto-detect or explicit) |
9731
+ | `install --local --editors dsh` | `./` | Generic local outputs plus the shared `.agents/skills` catalog; no DSH profile writes |
9732
+ | `dsh install|update --profile <name>` | `$DSH_HOME/profiles/<name>` | Exact SoftSpark package and preset lifecycle |
9733
+ | `dsh doctor --profile <name>` | DSH profile and ai-toolkit state | Read-only runtime, ownership, drift, and recovery diagnostics |
9734
+ | `dsh uninstall --profile <name>` | Managed DSH package, preset, and state entries | Ownership-checked removal that preserves unrelated profile content |
8967
9735
  | `claude-app export` | output ZIP + Markdown | Uploadable Claude Chat/Cowork plugin and global instructions |
8968
9736
  | `update` | `~/.claude/` | Re-apply after npm update or after add-rule/remove-rule |
8969
9737
  | `update --local` | `./` | Re-apply + refresh project-local configs |
@@ -9060,6 +9828,16 @@ translation and hook-compatibility model when targeting the global Codex layer.
9060
9828
 
9061
9829
  See `kb/reference/codex-cli-compatibility.md` for the detailed mapping.
9062
9830
 
9831
+ ### DSH Explicit Target
9832
+
9833
+ The DSH target reuses the Codex `.agents/skills` emitter. Canonical skill ownership stays under `app/skills`. DSH invocation metadata is validated before emission because invalid camel-case fields, non-boolean invocation values, and nested discovery entries fail closed upstream.
9834
+
9835
+ The profile lifecycle is a separate transaction boundary. It stores exact package-tree and preset identity under the shared ai-toolkit state path selected by `AI_TOOLKIT_HOME`, `SOFTSPARK_HOME`, or the default `~/.softspark/ai-toolkit`. A DSH lifecycle lock plus state compare-and-swap checks protect concurrent writers. Collision or rollback ambiguity preserves user data and reports doctor-visible recovery paths.
9836
+
9837
+ Codex remains the parent model through its local app server. The released preset adds one-shot Claude Code and GitHub Copilot Gemini delegation tools. ai-toolkit does not handle provider API keys or login state. GitHub Copilot policy and AI credits apply to the Gemini route. Direct Google, Antigravity, and Gemini API-key routes are unsupported.
9838
+
9839
+ See `kb/reference/dsh-compatibility.md` for the exact command, version, authentication, and recovery contract. Real-profile Phase 3 qualification is pending.
9840
+
9063
9841
  ## MCP Rendering Layer
9064
9842
 
9065
9843
  `.mcp.json` is the canonical project-level template format. ai-toolkit can render that configuration into editor-native MCP files through `scripts/mcp_editors.py`.
@@ -9183,7 +9961,7 @@ Severity levels: HIGH (blocks deployment), WARN (should fix), INFO (best practic
9183
9961
  ## Extension Points
9184
9962
 
9185
9963
  ### MCP Templates
9186
- `app/mcp-templates/` contains 26 ready-to-use MCP server config templates. Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
9964
+ `app/mcp-templates/` contains 28 ready-to-use MCP server config templates. Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
9187
9965
 
9188
9966
  ### Language Rules
9189
9967
  `app/rules/` provides language-specific rule files covering 13 languages (TypeScript, Python, Go, Rust, Java, Kotlin, Swift, Dart, C#, PHP, C++, Ruby, common). Auto-detected from project files via `--auto-detect` or selectable with `--modules rules-<lang>`. See README.md for current count.
@@ -9611,7 +10389,7 @@ Usage: ai-toolkit <command> [options]
9611
10389
 
9612
10390
  | Command | Description |
9613
10391
  |---------|-------------|
9614
- | `mcp list` | List available MCP server templates (26 templates) |
10392
+ | `mcp list` | List available MCP server templates (28 templates) |
9615
10393
  | `mcp editors` | List editors with native MCP config adapters and scopes |
9616
10394
  | `mcp add <name> [names...]` | Add MCP server template(s) to `.mcp.json` |
9617
10395
  | `mcp install --editor <name[,..]> [names...]` | Install templates into native editor MCP config |
@@ -11043,6 +11821,194 @@ This model gives:
11043
11821
 
11044
11822
  ---
11045
11823
 
11824
+ ## kb/reference/dsh-compatibility.md
11825
+
11826
+ ---
11827
+ title: "AI Toolkit - DSH Compatibility"
11828
+ category: reference
11829
+ service: ai-toolkit
11830
+ tags: [dsh, deepseek-harness, subscriptions, lifecycle, compatibility]
11831
+ version: "1.7.0"
11832
+ created: "2026-08-31"
11833
+ last_updated: "2026-09-01"
11834
+ description: "Compatibility contract for project skills and the explicit SoftSpark package lifecycle in DeepSeek Harness."
11835
+ ---
11836
+
11837
+ # DSH Compatibility
11838
+
11839
+ ## Summary
11840
+
11841
+ ai-toolkit supports DeepSeek Harness as an explicit developer-preview target. The integration is maintained by SoftSpark as a community compatibility layer. DeepSeek AI has not endorsed it.
11842
+
11843
+ The reviewed runtime is DSH `0.1.1-rc.2`. Newer upstream prereleases are not covered until they pass the same qualification. Isolated pre-tag and exact-registry post-release profiles completed the Claude Code and Copilot Gemini marker roundtrips through a Codex parent on 2026-09-01.
11844
+
11845
+ ## Project vs Profile Outputs
11846
+
11847
+ | Surface | Command | Managed output | Explicit non-output |
11848
+ |---|---|---|---|
11849
+ | Project install | `ai-toolkit install --local --editors dsh` | `CLAUDE.md`, `.claude/settings.local.json`, `.claude/constitution.md`, detected language rules, other generic local outputs, and the DSH-specific one-level `.agents/skills/<name>/SKILL.md` catalog with bundled resources | No `$DSH_HOME` writes, npm package changes, profile changes, preset changes, or credential reads |
11850
+ | DSH profile | `ai-toolkit dsh install --profile web` | Two exact npm dependencies in the named profile, the released `softspark-orchestrator` preset, and ai-toolkit ownership state | No project files, provider login, API keys, unrelated plugins, or user presets |
11851
+
11852
+ DSH is excluded from `--editors all`, auto-detection, default profiles, and default editor selection. Naming `dsh` without `--local` is not a supported project install route.
11853
+
11854
+ Project `--dry-run` resolves and validates `extends`, then plans the generic local outputs and `.agents/skills` catalog without creating, changing, or deleting a project entry. It does not create or update `.softspark-toolkit.lock.json`, and it does not mutate `DSH_HOME`, packages, profiles, state, or authentication.
11855
+
11856
+ ## Local and Global Commands
11857
+
11858
+ ```bash
11859
+ # Generic local outputs plus DSH-specific project skills
11860
+ ai-toolkit install --local --editors dsh
11861
+
11862
+ # Read-only project preview
11863
+ ai-toolkit install --local --editors dsh --dry-run
11864
+
11865
+ # Explicit machine profile lifecycle
11866
+ ai-toolkit dsh install --profile web
11867
+ ai-toolkit dsh update --profile web
11868
+ ai-toolkit dsh doctor --profile web
11869
+ ai-toolkit dsh uninstall --profile web --yes
11870
+ ```
11871
+
11872
+ The DSH profile defaults to `web` when `--profile` is omitted. `DSH_HOME` selects the DSH root and defaults to `~/.dsh`. Profile mutation is never an implicit side effect of local installation, global installation, update, or generic uninstall.
11873
+
11874
+ ## Exact Pins
11875
+
11876
+ | Component | Reviewed version | Role |
11877
+ |---|---:|---|
11878
+ | DeepSeek Harness | `0.1.1-rc.2` | Profile host and plugin manager |
11879
+ | pnpm | `>=11.7.0,<12.0.0` | Package manager used by the DSH plugin command |
11880
+ | `@softspark/dsh-codex` | `1.0.0` | Codex parent provider through local `codex app-server` |
11881
+ | `@softspark/dsh-orchestrator` | `1.0.1` | Claude Code and GitHub Copilot Gemini delegation bundle plus released preset |
11882
+
11883
+ Install and update use exact package arguments with `--save-exact`. Arbitrary DSH prereleases and unpinned SoftSpark packages are outside this contract.
11884
+
11885
+ The reviewed DSH tag declares `pnpm@11.7.0`. The isolated cold-install environment used Corepack pnpm `11.24.0`, so the lifecycle accepts stable pnpm releases from `11.7.0` through the end of major 11. Before it creates the lifecycle lock or changes a profile, it resolves exact DSH and pnpm command paths from the minimal child `PATH`, records their command and resolved-file identities, and runs their version probes with a five-second bound. Missing, nonzero, timed-out, malformed, or unsupported pnpm probes fail with no package, preset, state, or lifecycle artifact.
11886
+
11887
+ ## Subscription and Authentication Boundaries
11888
+
11889
+ ai-toolkit does not log in to a model provider, accept a provider API key, read a vendor credential store, copy tokens, or add credentials to state. Each vendor CLI owns authentication:
11890
+
11891
+ | Route | Login owner | Subscription or billing boundary |
11892
+ |---|---|---|
11893
+ | Codex parent | `codex login` and `codex login status` | ChatGPT subscription managed by Codex |
11894
+ | Claude delegate | `claude auth login` | Claude Max or Pro managed by Claude Code |
11895
+ | Gemini delegate | `copilot login` | Active GitHub Copilot plan and GitHub AI credits |
11896
+
11897
+ Lifecycle subprocesses receive only `HOME`, the validated `DSH_HOME`, `PATH`, and locale or temporary-directory settings when present. Provider and registry secret environment variables are not forwarded. Vendor CLI output is not copied into lifecycle error messages.
11898
+
11899
+ ## DSH, Codex, Claude, and Copilot Topology
11900
+
11901
+ ```text
11902
+ DSH session using SoftSpark Orchestrator
11903
+ |
11904
+ +-> @softspark/dsh-codex
11905
+ | -> local codex app-server
11906
+ | -> Codex-owned ChatGPT authentication and parent thread
11907
+ |
11908
+ +-> subagent_claude_code
11909
+ | -> DSH Claude Code provider
11910
+ | -> Claude Code native login
11911
+ |
11912
+ +-> subagent_gemini_copilot
11913
+ -> GitHub Copilot CLI ACP server
11914
+ -> Gemini 3.6 Flash under GitHub policy and AI credits
11915
+ ```
11916
+
11917
+ Codex is the parent provider. The preset keeps the optional Codex subagent row disabled. Claude Code and Copilot Gemini receive bounded standalone delegation tasks.
11918
+
11919
+ ## Invocation Metadata and Shared Skill Ownership
11920
+
11921
+ DSH and Codex share the project `.agents/skills` output. `app/skills/<name>/` remains canonical. `scripts/generate_codex_skills.py` emits native links or adapted wrappers, so ai-toolkit does not maintain a second DSH-specific skill catalog.
11922
+
11923
+ DSH discovers one-level `<name>/SKILL.md` bundles and flat `<name>.md` entries. Names must use lowercase kebab-case. The required fields are `name` and `description`. Optional invocation fields use `user-invocable` and `disable-model-invocation` with boolean values. Camel-case spellings or invalid boolean values fail closed and remove the skill from discovery. Nested `SKILL.md` entries are not supported, but resources inside a valid bundle remain available.
11924
+
11925
+ The preset owns the session composition and external delegation tools. It does not copy the 44 ai-toolkit agent definitions into 44 DSH presets or subagents.
11926
+
11927
+ ## Lifecycle State and Recovery
11928
+
11929
+ State resolves in this order:
11930
+
11931
+ 1. `$AI_TOOLKIT_HOME/state.json` when `AI_TOOLKIT_HOME` is set.
11932
+ 2. `$SOFTSPARK_HOME/ai-toolkit/state.json` when `SOFTSPARK_HOME` is set.
11933
+ 3. `~/.softspark/ai-toolkit/state.json` by default.
11934
+
11935
+ The DSH record stores the canonical DSH home, profile, exact package versions, package-tree identity, preset path, preset hash, ownership flags, and timestamps. It stores no package contents, prompts, credentials, authentication paths, or child-process environment.
11936
+
11937
+ The published npm packages own their installed code. The canonical preset source is `@softspark/dsh-orchestrator/agent-presets/softspark-orchestrator` inside the exact installed package. ai-toolkit copies and verifies that tree. It does not reconstruct the preset.
11938
+
11939
+ Mutations first take a nonblocking exclusive POSIX `flock` on the already pinned `DSH_HOME` directory descriptor, then claim the bounded canonical lifecycle lock and use the shared state lock with compare-and-swap publication. Directory locking is independent of the replaceable lock filename. It remains held across sentinel scans, package and preset mutation, normal canonical-lock release, or recovery-sentinel creation plus file and directory `fsync`. A competing lifecycle must acquire the same directory lock before it can scan recovery state or claim the canonical name. The immutable prerequisite record is revalidated after lock acquisition and before every package mutation or package rollback. A replaced or removed executable, or a new earlier `pnpm` PATH shadow, blocks the command. The verified pnpm command directory is placed first in the child PATH so DSH's literal `pnpm` lookup resolves to the probed command. Install, update, and uninstall verify the profile manifest, package trees, preset identity, and unrelated dependencies before and after each external package-manager command. Rollback restores the immutable pre-operation target. It does not reinterpret concurrent bytes as owned data.
11940
+
11941
+ Each DSH plugin add, update, remove, or rollback command has a 300-second process bound, separate from the short prerequisite probe. This bound accommodates cold package resolution without promising registry or network latency. Every mutation starts DSH in a dedicated POSIX session and process group. A timeout or interruption signals the complete group, escalates from `SIGTERM` to `SIGKILL` when needed, and waits for confirmed group exit before rollback. If exit cannot be confirmed, package rollback is blocked and deterministic inspection steps are reported. Child stdout and stderr remain suppressed from user-facing errors.
11942
+
11943
+ Process-group signals are allowed only while the unreaped DSH supervisor still binds its PID to that group. If the supervisor identity is lost before escalation, the lifecycle fails closed instead of signaling a group identifier that the operating system could reuse. Before `Popen`, the calling thread blocks `SIGINT` with `pthread_sigmask`. It restores the previous mask only inside a catchable region that covers `communicate`, final PGID inspection, and command postconditions, then restores the mask again in `finally`. Any `BaseException` after spawn runs full process-tree teardown before propagation. Repeated `SIGINT` cannot escape the bounded TERM, KILL, and wait sequence.
11944
+
11945
+ An unconfirmed process-tree exit first verifies that `$DSH_HOME/.ai-toolkit-lifecycle.lock` still names the held inode, then creates and syncs a transaction-unique process-tree recovery sentinel. It rewrites the canonical lock as a recovery gate only while that identity remains exact. A removed or renamed lock leaves the sentinel as the gate; a foreign replacement is neither overwritten nor deleted. Install, update, and uninstall scan these sentinels before and after claiming the canonical lock, so recovery blocks DSH invocation even when the original lock name was displaced. `doctor` reports every gate's process-group identifier, original profile path, and exact artifact path. ai-toolkit never clears these gates automatically: the operator must verify that the recorded process group has exited, inspect the profile, and only then remove every named recovery artifact.
11946
+
11947
+ An identity conflict preserves the conflicting path and creates a doctor-visible recovery marker instead of deleting or replacing it. User plugins, dependencies, presets, profile patches, and unrelated state keys remain outside ai-toolkit ownership. Secure mutation and process-tree termination require POSIX primitives available on Linux, WSL, and macOS. Native Windows mutation is unsupported and fails before the lifecycle lock.
11948
+
11949
+ Profile lifecycle `--dry-run` is read-only. It runs the bounded DSH and pnpm prerequisite probes, but it does not create state, acquire a lock, invoke the plugin manager, or create profile paths. It can therefore report a missing or unsupported prerequisite without leaving lifecycle output.
11950
+
11951
+ ## Unsupported Google, Antigravity, and API-Key Routes
11952
+
11953
+ This integration does not provide direct Google AI Pro or Ultra login, Gemini CLI OAuth, Antigravity login, Gemini API keys, DeepSeek API keys, Anthropic API keys, or OpenAI API keys. Gemini is available only through the GitHub Copilot CLI ACP route described above.
11954
+
11955
+ The first native target also excludes DSH hook bridging, MCP bridging, arbitrary preset import, automatic profile selection, and full ai-toolkit agent mapping. Generic `ai-toolkit uninstall` does not mutate DSH profiles.
11956
+
11957
+ ## Behavioral Limits
11958
+
11959
+ - Claude Code and Copilot delegation are one-shot child tasks. Each child receives the task and workspace directory, not the parent conversation history.
11960
+ - Copilot runs with no available tools, rejects permission requests, disables built-in MCP servers, remote control, custom instructions, and auto-update, and uses a 30-credit session cap.
11961
+ - Child effects completed before cancellation are not rolled back.
11962
+ - Workspace content selected by a vendor CLI may leave the machine under that vendor's product terms and account policy.
11963
+ - Codex owns its built-in tools, sandbox, approval policy, thread state, and model execution. ai-toolkit does not reproduce those controls inside DSH.
11964
+ - Existing DSH sessions keep the preset generation with which they started. Restart DSH and open a new session after install or update.
11965
+
11966
+ ## Uninstall, Update, and Doctor
11967
+
11968
+ `ai-toolkit dsh update` changes only a recorded profile whose managed package and preset identities match state. It installs the current reviewed pins, then publishes the new state after all postconditions pass.
11969
+
11970
+ `ai-toolkit dsh doctor` is read-only. It reports the DSH runtime version, pnpm availability and version, package pins, package-tree and preset ownership, state consistency, lifecycle lock recovery artifacts, staging paths, and recovery markers. A recovery marker keeps `Recovery needed: yes` visible until the operator resolves the named paths.
11971
+
11972
+ `ai-toolkit dsh uninstall --yes` removes only the recorded SoftSpark packages, preset, and profile state. Drift or ownership ambiguity stops removal. Unrelated profile dependencies, patch files, presets, and state keys remain unchanged.
11973
+
11974
+ ## Verification
11975
+
11976
+ Run the static and isolated checks without modifying a regular DSH profile:
11977
+
11978
+ ```bash
11979
+ bats tests/test_ecosystem_doctor.bats
11980
+ bats tests/test_dsh.bats
11981
+ python3 scripts/ecosystem_doctor.py --tool dsh --offline --format text
11982
+ python3 scripts/validate.py --strict
11983
+
11984
+ ai-toolkit install --local --editors dsh --dry-run
11985
+ ai-toolkit dsh install --profile web --dry-run
11986
+ ai-toolkit dsh update --profile web --dry-run
11987
+ ai-toolkit dsh doctor --profile web
11988
+ ai-toolkit dsh uninstall --profile web --dry-run --yes
11989
+ ```
11990
+
11991
+ Phase 3 real-profile qualification completed with a task-specific `DSH_HOME`, exact published package artifacts, and native vendor logins. The pre-tag candidate and exact npm registry package both produced successful child and parent markers through `subagent_claude_code` and `subagent_gemini_copilot`; no provider API key was supplied or handled. The isolated DSH processes stopped cleanly and the unrelated profile fixture remained intact.
11992
+
11993
+ ## Preview and Upstream Drift
11994
+
11995
+ DeepSeek Harness describes itself as a developer preview with compatibility-breaking changes. The upstream release feed published `0.1.2-alpha.2` after the reviewed `0.1.1-rc.2` line. ai-toolkit does not adopt that prerelease by inference.
11996
+
11997
+ Use the registry doctor to detect documentation, capability-marker, and local version changes. A new upstream version requires source review, focused fixture updates, isolated real-profile qualification, and explicit pin changes before support moves.
11998
+
11999
+ ## Sources
12000
+
12001
+ - [DeepSeek Harness documentation](https://deepseek-harness.github.io/deepseek-harness/)
12002
+ - [DeepSeek Harness releases](https://github.com/deepseek-ai/deepseek-harness/releases)
12003
+ - [Reviewed DSH 0.1.1-rc.2 release](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.1-rc.2)
12004
+ - [Reviewed DSH package-manager declaration](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/package.json)
12005
+ - [Reviewed DSH CLI profile and plugin contract](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/apps/cli/reference/README.md)
12006
+ - [Reviewed DSH skill discovery contract](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/docs/subsystems/skills.md)
12007
+ - [PATH: kb/reference/manifest-install.md]
12008
+ - [PATH: kb/history/completed/dsh-native-install-target-plan.md]
12009
+
12010
+ ---
12011
+
11046
12012
  ## kb/reference/enterprise-config-guide.md
11047
12013
 
11048
12014
  ---
@@ -13371,11 +14337,11 @@ source, cross-verify against a second independent copy, and only then write
13371
14337
  title: "Manifest-Driven Install System"
13372
14338
  category: reference
13373
14339
  service: ai-toolkit
13374
- tags: [install, manifest, modules, profiles, auto-detect, state-tracking]
13375
- version: "1.0.0"
14340
+ tags: [install, manifest, modules, profiles, auto-detect, state-tracking, dsh]
14341
+ version: "1.16.0"
13376
14342
  created: "2026-04-07"
13377
- last_updated: "2026-04-07"
13378
- description: "Reference for the manifest-driven install system: 17 modules, 4 profiles, auto-detection, and state tracking in ~/.softspark/ai-toolkit/state.json."
14343
+ last_updated: "2026-09-01"
14344
+ description: "Reference for manifest-driven project installation, explicit DSH profile lifecycle management, and ownership state in ~/.softspark/ai-toolkit/state.json."
13379
14345
  ---
13380
14346
 
13381
14347
  # Manifest-Driven Install System
@@ -13408,7 +14374,7 @@ Modules are defined in `manifest.json` at the repository root. There are 17 modu
13408
14374
  | `rules-php` | PHP-specific rules (5 files) | auto-detect |
13409
14375
  | `rules-cpp` | C++-specific rules (5 files) | auto-detect |
13410
14376
  | `rules-ruby` | Ruby-specific rules (5 files) | auto-detect |
13411
- | `mcp-templates` | 26 MCP server config templates | strict, full |
14377
+ | `mcp-templates` | 28 MCP server config templates | strict, full |
13412
14378
 
13413
14379
  ## Profiles
13414
14380
 
@@ -13488,6 +14454,64 @@ ai-toolkit status
13488
14454
 
13489
14455
  Re-applies installed modules, skipping files whose content hash has not changed since last install. Implemented in `scripts/install_steps/install_state.py`.
13490
14456
 
14457
+ ## Explicit DSH Profile Lifecycle
14458
+
14459
+ The DSH project target and the DSH profile lifecycle are separate operations:
14460
+
14461
+ ```bash
14462
+ # Generic local outputs plus DSH-specific project skills. No DSH profile change.
14463
+ ai-toolkit install --local --editors dsh
14464
+
14465
+ # Read-only project plan, including extends resolution.
14466
+ ai-toolkit install --local --editors dsh --dry-run
14467
+
14468
+ # Explicit global DSH profile mutation. The default profile is web.
14469
+ ai-toolkit dsh install --profile web
14470
+ ai-toolkit dsh update --profile web
14471
+ ai-toolkit dsh doctor --profile web
14472
+ ai-toolkit dsh uninstall --profile web --yes
14473
+ ```
14474
+
14475
+ The project command is explicit-only. DSH is excluded from `--editors all`, auto-detection, default profiles, and default editor selection. Its DSH-specific output is `.agents/skills`; the generic `--local` Claude files, detected language rules, and other project outputs still apply. It never writes below `DSH_HOME`.
14476
+
14477
+ Project `--dry-run` resolves and validates `extends` without persisting `.softspark-toolkit.lock.json`, then plans every generic and DSH-specific project output without changing the project tree. Existing lock bytes and metadata remain unchanged. It also makes no DSH package, profile, state, or authentication change.
14478
+
14479
+ `DSH_HOME` selects the DSH root. The default is `~/.dsh`. It must resolve to an absolute, non-symlink managed root. Profile identifiers accept 1 to 64 lowercase letters, digits, periods, underscores, or hyphens.
14480
+
14481
+ The lifecycle supports DSH `0.1.1-rc.2`, stable pnpm `>=11.7.0,<12.0.0`, `@softspark/dsh-codex@1.0.0`, and `@softspark/dsh-orchestrator@1.0.1`. The DSH tag declares `pnpm@11.7.0`, while isolated cold-install qualification used Corepack pnpm `11.24.0`. It invokes the plugin manager with bounded argv-array subprocesses:
14482
+
14483
+ ```text
14484
+ dsh plugin --profile web add @softspark/dsh-codex@1.0.0 --save-exact
14485
+ dsh plugin --profile web add @softspark/dsh-orchestrator@1.0.1 --save-exact
14486
+ ```
14487
+
14488
+ The orchestrator preset is copied from the installed package:
14489
+
14490
+ ```text
14491
+ $DSH_HOME/profiles/web/node_modules/@softspark/dsh-orchestrator/agent-presets/softspark-orchestrator
14492
+ -> $DSH_HOME/.agent-presets/softspark-orchestrator
14493
+ ```
14494
+
14495
+ The lifecycle refuses unowned same-name plugins and presets. An unchanged owned install is idempotent. Update and uninstall require every recorded package-tree entry and the preset tree to match current bytes, types, paths, links, and POSIX modes. Generic `ai-toolkit uninstall` does not mutate DSH profiles or remove their ownership state. Use `ai-toolkit dsh uninstall` explicitly.
14496
+
14497
+ The persisted `packages` map is the ownership baseline, not the desired version target. Its key set must contain exactly the two managed package names, each value must be an exact version, and its keys must match the stored package-tree inventories. After a reviewed pin bump, `update` verifies the on-disk manifest and trees against those recorded versions, installs the current reviewed pins, and replaces the state record only after all postconditions pass. `uninstall` verifies and removes the recorded owned package names even when the current reviewed pins are newer. Rollback always restores the exact versions captured before the operation.
14498
+
14499
+ A zero exit status from DSH is not sufficient to commit a lifecycle operation. Immediately before and after every plugin add or remove, ai-toolkit rereads the profile manifest and the complete managed package trees under the lifecycle lock. A changed, malformed, unexpected, or newly introduced managed entry stops the next external mutation and preserves the concurrent bytes. The managed packages must have the exact recorded pins or be fully absent for uninstall. Dependency entries outside the two managed package names must remain unchanged. A false-success postcondition leaves ownership state uncommitted.
14500
+
14501
+ Each stored package inventory uses a domain-separated SHA-256 over stable, length-prefixed records. A record contains the entry type, relative path, POSIX mode, and type-specific metadata. Regular-file metadata contains the byte length and per-file SHA-256. Symlink metadata contains the target text. Traversal is bounded to 100,000 entries and 128 levels, never follows symlinks, and rejects special files. The state stores hashes and metadata only. It stores no package contents, credentials, authentication paths, or child-process environment.
14502
+
14503
+ Rollback gives every package-manager recovery command an explicit target derived from the immutable pre-operation snapshot. The target contains the managed package inventory, the exact target package tree, the unchanged non-target package trees, and the pre-operation unrelated dependencies. A successful child exit is accepted only when all four match. A post-command observation is evidence, never a new target. Target drift or unreadable state blocks every later package-manager recovery call, preserves the current bytes, creates a transaction-unique doctor-visible recovery marker, and prints `ai-toolkit dsh doctor --profile <name>` plus deterministic manual inspection paths. This rule applies to install, update, and uninstall rollback.
14504
+
14505
+ Before the first mutation, the lifecycle resolves exact DSH and pnpm command paths from the minimal child `PATH`. It records each command path, resolved path, device, inode, type, mode, size, timestamps, and symlink target when applicable. It runs both version probes with a five-second bound and requires pnpm to parse inside the supported range. Missing, nonzero, timed-out, malformed, or unsupported pnpm probes fail before the lifecycle lock and leave no package, preset, state, or lock artifact.
14506
+
14507
+ Profile lifecycle `--dry-run` performs read-only runtime, package-manager, and ownership preflight. It prints the exact planned argv and paths. It does not acquire a lifecycle or state lock, create a directory, write state, or start a package-manager mutation. Mutating install, update, and uninstall operations first acquire a nonblocking exclusive POSIX `flock` on the pinned `DSH_HOME` directory descriptor, then hold `$DSH_HOME/.ai-toolkit-lifecycle.lock` from preflight through mutation, rollback, cleanup, and recovery. The directory lock is independent of that replaceable filename. It remains held while a recovery sentinel is created with `O_EXCL` and while both its file and parent directory are synced; release occurs only after normal canonical-lock release or durable sentinel publication. Every competing lifecycle must acquire the same directory lock before sentinel scans and canonical claim. Lock acquisition pins the exact lexical `DSH_HOME` parent and root directory descriptors and passes that one resolved home through the full operation. The prerequisite record is revalidated after the lock and before every package mutation or rollback. Replacement, removal, in-place identity drift, and a new earlier PATH shadow fail closed. The verified pnpm command directory leads the child PATH. Every internal mutation and each external DSH command verifies that the lexical path still names the pinned device, inode, and directory kind. Preset parents, staging trees, recovery containers, copied children, and recovery markers are opened by walking from that root descriptor with no-follow operations. Creation, copy, cleanup, and recovery use descriptor-relative system calls and retain the parent and child device and inode identities through postcondition checks. A mismatch blocks state success and later package commands, preserves both roots, and reports recovery. The child process receives only the verified canonical path. The canonical lock is claimed as a regular non-symlink with exclusive descriptor-relative creation and waits for at most one second. A write, `fsync`, close, or interruption during lock initialization removes only the captured lock inode. If that cleanup cannot complete, the command reports a doctor-visible lock recovery artifact and the next lifecycle command remains fail-closed. Release uses the pinned root descriptor, atomically relocates the lock without replacement, and deletes it only after its device and inode still match the transaction. A displaced root never redirects lock cleanup into its replacement. `doctor` is read-only and does not acquire the lifecycle lock.
14508
+
14509
+ If process-tree termination cannot be confirmed, the lifecycle does not enter package rollback or normal lock release. Before writing recovery metadata it verifies that the canonical lock still names the held device and inode, then creates and syncs a transaction-unique `unconfirmed-process-tree` sentinel in the pinned DSH root. It rewrites the held inode only after a second canonical identity check. A removed or renamed canonical lock therefore leaves the recognized sentinel, while a foreign replacement remains byte-identical. Lock acquisition checks process-tree sentinels before and after claiming the canonical name, and every later install, update, or uninstall fails before DSH invocation. `doctor` prints the recorded process group, original profile path, and every exact gate file. Recovery is deliberately manual: verify that the process group has exited, inspect the preserved profile, and only then remove every named gate. Group signaling is permitted only while the unreaped DSH supervisor still binds the group identifier; after that identity is lost, the command preserves the gate rather than risk signaling a reused PGID. Repeated `SIGINT` is deferred or retried through the bounded TERM, KILL, and wait sequence.
14510
+
14511
+ Doctor reports runtime compatibility, pnpm availability and version, installed package versions, complete package-tree ownership, preset ownership and hash drift, state consistency, legacy recovery collisions, transaction-unique recovery containers, preserved staging, and whether recovery is required.
14512
+
14513
+ The lifecycle never runs login commands, reads vendor credential stores, accepts provider API keys, or forwards provider and registry secret environment variables. Codex, Claude Code, and GitHub Copilot own login state. GitHub AI credits apply to Copilot Gemini delegation. Direct Google AI Pro or Ultra, Gemini CLI OAuth, Antigravity, and Gemini API-key routes are unsupported. Prerequisite probes have a five-second bound. DSH plugin mutations and package rollback commands have a separate 300-second bound suitable for cold resolution, without promising registry or network latency. Each mutation uses a dedicated POSIX session and process group on Linux, WSL, or macOS. The calling thread blocks `SIGINT` with `pthread_sigmask` before `Popen`, restores its previous mask inside one catchable region covering communication and final PGID checks, and restores the mask in `finally`. Every `BaseException` after spawn triggers complete process-tree teardown before propagation. Timeout and interruption require confirmed group exit before rollback; an unconfirmed exit blocks rollback. POSIX directory `flock`, process groups, and thread signal masks are mandatory mutation primitives. Native Windows mutation is unsupported and fails before lifecycle writes. Failed child-process stdout and stderr are never included in user-facing errors. Errors expose only the safe command outcome, such as exit status, timeout, or interruption. Recovery argv contains only the validated DSH executable, profile, fixed package names, and exact pinned versions.
14514
+
13491
14515
  ## State Tracking
13492
14516
 
13493
14517
  Installed module state is persisted to `~/.softspark/ai-toolkit/state.json`:
@@ -13500,14 +14524,61 @@ Installed module state is persisted to `~/.softspark/ai-toolkit/state.json`:
13500
14524
  "last_updated": "2026-04-07T10:00:00Z",
13501
14525
  "file_hashes": {
13502
14526
  "app/hooks/session-start.sh": "abc123..."
14527
+ },
14528
+ "dsh": {
14529
+ "profiles": {
14530
+ "web": {
14531
+ "dsh_home": "/Users/example/.dsh",
14532
+ "profile": "web",
14533
+ "packages": {
14534
+ "@softspark/dsh-codex": "1.0.0",
14535
+ "@softspark/dsh-orchestrator": "1.0.1"
14536
+ },
14537
+ "package_trees": {
14538
+ "@softspark/dsh-codex": {
14539
+ "digest": "<canonical-tree-sha256>",
14540
+ "entries": [
14541
+ {"type": "directory", "path": ".", "mode": 493},
14542
+ {"type": "file", "path": "package.json", "mode": 420, "size": 53, "sha256": "<file-sha256>"}
14543
+ ]
14544
+ },
14545
+ "@softspark/dsh-orchestrator": {
14546
+ "digest": "<canonical-tree-sha256>",
14547
+ "entries": [
14548
+ {"type": "directory", "path": ".", "mode": 493}
14549
+ ]
14550
+ }
14551
+ },
14552
+ "preset_path": "/Users/example/.dsh/.agent-presets/softspark-orchestrator",
14553
+ "preset_hash": "<sha256>",
14554
+ "owned": true,
14555
+ "installed_at": "2026-08-29T08:00:00Z",
14556
+ "last_updated": "2026-08-29T08:00:00Z"
14557
+ }
14558
+ }
13503
14559
  }
13504
14560
  }
13505
14561
  ```
13506
14562
 
13507
14563
  - `installed_modules` — used by `update` to know which modules to re-apply
13508
14564
  - `file_hashes` — used to skip unchanged files during `update`
14565
+ - `dsh.profiles` records the DSH home, profile, exact package versions, canonical package-tree inventories, preset path and hash, ownership, and timestamps
13509
14566
  - The file is written after every successful install or update
13510
14567
 
14568
+ Every shared state writer uses the canonical path from `AI_TOOLKIT_HOME`, `SOFTSPARK_HOME`, or the default `~/.softspark/ai-toolkit/state.json` and cooperates through the same bounded `.state.lock`. Where the host provides descriptor-relative atomic primitives, the lock context pins the state parent device and inode. Transaction reads, snapshots, compare-and-swap merges, private temporary creation, writes, `fsync`, publication, mode changes, cleanup, and lock release then address entries relative to that same open parent descriptor. A DSH lifecycle snapshot also records this parent identity and requires the final install, update, uninstall, and rollback state transaction to reopen that exact lexical path and match the same device and inode. The lexical parent binding is checked before publication and release. Replacing the state directory therefore fails without publishing into the replacement or losing either root. Generic install, MCP, and editor state writers retain the portable state contract on every supported Python platform. They use this pinned atomic publisher when available and otherwise publish a private temporary with the platform's atomic replacement primitive while holding the shared lock.
14569
+
14570
+ DSH ownership mutation has a stricter platform gate. It requires Linux, WSL, or macOS support for pinned-directory, no-follow, no-replace, and atomic-exchange operations. The lifecycle checks both its DSH filesystem primitives and the state publisher before it creates the state root, state lock, lifecycle lock, temporary, or profile artifact. Secure state lock creation addresses `.state.lock` relative to a pinned no-follow parent descriptor and keeps that descriptor open through release. DSH state publication uses an atomic exchange for an existing file or a no-replace rename for first creation. The writer validates the displaced device, inode, and content digest before cleanup. A mismatched inode is restored or preserved for manual recovery instead of being overwritten or deleted. A bounded retry merges unrelated concurrent state keys. A concurrent change to the same DSH profile is preserved and reported as a recovery conflict.
14571
+
14572
+ Records created before package-tree inventories were introduced are intentionally not migrated by assumption. `doctor` reports the invalid ownership state. Reinstall the explicit DSH integration after inspecting or removing the old record. Update and uninstall never claim unknown package bytes as owned.
14573
+
14574
+ DSH mutations snapshot the profile manifest, managed package trees, base-directory existence, prior state, and preset before the first external mutation. Interruption and cleanup failure run the same rollback as package failure. Cleanup uses an entry-level inventory of device, inode, kind, digest, and symlink target. Snapshot recreation walks every ancestor without following symlinks, pins the destination parent, and uses descriptor-relative no-clobber creation for files, directories, and symlinks. File and directory modes are restored with `fchmod` only after pinning the exact inode. Post-creation and post-mode checks bind type, inode, mode, digest, and link target to the pinned parent. Unsupported primitives fail before any write, and an inode or ancestor mismatch remains untouched and doctor-visible. Manifest removal, manifest restoration, and transaction-created profile-directory pruning first relocate the candidate without replacement through pinned parent descriptors, then validate the moved inode and content before cleanup. A mismatch remains at its concurrent path or in a reported recovery container. Cleanup never unlinks, replaces, or removes a concurrently substituted file, symlink, or directory. A transaction-created `.agent-presets` parent is removed only when its identity is unchanged and it remains empty.
14575
+
14576
+ Update and uninstall revalidate the owned preset identity and content immediately before relocation. The transaction atomically claims a private mode-0700 recovery container with a cryptographically random suffix, then moves the preset to its previously absent `managed-preset` child. It never replaces a caller-provided recovery path. The relocated payload remains bound to the captured device, inode, kind, digest, and symlink target; that same identity is checked immediately and again before every restore or removal. A byte-identical replacement is therefore preserved and reported instead of being treated as transaction-owned. Managed dependency entries must contain exact semantic versions; malformed or non-string values fail before DSH is invoked. A clean-profile rollback removes transaction-created manifest and base directories when they remain unchanged. Existing profile manifests are restored byte-for-byte, and missing pre-existing package entries are recreated without overwriting collisions.
14577
+
14578
+ If byte-identical rollback cannot finish, the command returns nonzero and prints every exact safely quoted residual path plus deterministic recovery steps. One failed package recovery command does not authorize the next package command: the loop immediately rechecks the rollback-blocked flag and complete package identity after success or failure, records doctor and inspection actions, and stops package mutation on drift. Independent preset cleanup and state restoration still run, so their failures are aggregated without replacing the original error. Every surviving staging or recovery path remains listed and doctor-visible, so no operation reports success while its owned recovery data survives. Update staging cleanup removes only transaction-owned entries and reports every surviving staging path, including concurrent additions. Package-filesystem and cleanup residuals create transaction-unique `.softspark-orchestrator.ai-toolkit-package.<token>` containers. `ai-toolkit dsh doctor --profile <name>` reports `Recovery needed: yes` until manual recovery is complete.
14579
+
14580
+ Real-profile qualification with the published packages and native subscription logins remains pending Phase 3. Static, fixture, and dry-run success is not evidence that this qualification has completed.
14581
+
13511
14582
  ## Implementation Files
13512
14583
 
13513
14584
  | File | Purpose |
@@ -13515,6 +14586,7 @@ Installed module state is persisted to `~/.softspark/ai-toolkit/state.json`:
13515
14586
  | `manifest.json` | Module and profile definitions |
13516
14587
  | `scripts/install_steps/detect_language.py` | Auto-detect project language from marker files |
13517
14588
  | `scripts/install_steps/install_state.py` | Read/write `~/.softspark/ai-toolkit/state.json` |
14589
+ | `scripts/install_steps/dsh.py` | Explicit DSH install, update, doctor, uninstall, and recovery lifecycle |
13518
14590
 
13519
14591
  ## Backward Compatibility
13520
14592
 
@@ -13532,6 +14604,7 @@ No existing install scripts or CI configurations need changes.
13532
14604
  - [PATH: kb/reference/language-rules.md] — language rules structure and auto-detection detail
13533
14605
  - [PATH: kb/reference/mcp-templates.md] — MCP server templates (the `mcp-templates` module)
13534
14606
  - [PATH: kb/reference/architecture-overview.md] — overall install model
14607
+ - [PATH: kb/reference/dsh-compatibility.md] - DSH commands, topology, authentication, and preview limits
13535
14608
 
13536
14609
  ---
13537
14610
 
@@ -13655,17 +14728,17 @@ title: "MCP Server Templates"
13655
14728
  category: reference
13656
14729
  service: ai-toolkit
13657
14730
  tags: [mcp, templates, servers, configuration, editors, inject-mcp, external-templates]
13658
- version: "1.5.0"
14731
+ version: "1.6.0"
13659
14732
  created: "2026-04-07"
13660
- last_updated: "2026-08-21"
13661
- description: "Reference for 26 built-in MCP server templates, external template injection via inject-mcp, and native editor MCP installation support."
14733
+ last_updated: "2026-08-31"
14734
+ description: "Reference for 28 built-in MCP server templates, external template injection via inject-mcp, and native editor MCP installation support."
13662
14735
  ---
13663
14736
 
13664
14737
  # MCP Server Templates
13665
14738
 
13666
14739
  ## Overview
13667
14740
 
13668
- ai-toolkit ships 26 ready-to-use MCP server configuration templates in `app/mcp-templates/`. Each template is a JSON file that defines the canonical `mcpServers` block for a specific service. Templates can be merged into the project's `.mcp.json` and rendered into editor-native MCP config files via the `ai-toolkit mcp` CLI subcommand.
14741
+ ai-toolkit ships 28 ready-to-use MCP server configuration templates in `app/mcp-templates/`. Each template is a JSON file that defines the canonical `mcpServers` block for a specific service. Templates can be merged into the project's `.mcp.json` and rendered into editor-native MCP config files via the `ai-toolkit mcp` CLI subcommand.
13669
14742
 
13670
14743
  **External templates:** Tools outside the toolkit (MCP servers, plugins, custom integrations) can register their own MCP templates via `ai-toolkit inject-mcp <file|url>` -- the toolkit caches the template, tags every server with a `_source` field, and propagates the config to every editor that exposes a `global_path`. URL-sourced templates are auto-refreshed on every `ai-toolkit update`. See [PATH: kb/reference/extension-api.md] for the inject-mcp / remove-mcp reference.
13671
14744
 
@@ -13731,6 +14804,7 @@ loads `.codex/config.toml` only for trusted project layers.
13731
14804
  | `filesystem` | Local filesystem access for reading, writing, and searching files | — |
13732
14805
  | `git` | Git repository inspection: diffs, logs, branches | — |
13733
14806
  | `github` | GitHub API: issues, PRs, repos, code search | `GITHUB_PERSONAL_ACCESS_TOKEN` |
14807
+ | `jira` | Jira multi-instance routing, ADF, caching, and comment templates | — |
13734
14808
  | `google-drive` | Google Drive file search, reading, and management | `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI` |
13735
14809
  | `google-maps` | Google Maps geocoding, directions, place search | `GOOGLE_MAPS_API_KEY` |
13736
14810
  | `grafana` | Grafana dashboard queries, alerting, and data source management | `GRAFANA_URL`, `GRAFANA_API_KEY` |
@@ -13739,6 +14813,8 @@ loads `.codex/config.toml` only for trusted project layers.
13739
14813
  | `notion` | Notion workspace: pages, databases, content management | `NOTION_API_KEY` |
13740
14814
  | `postgres` | PostgreSQL database access, schema inspection, analysis | — |
13741
14815
  | `puppeteer` | Browser automation: screenshots, navigation, web scraping | — |
14816
+ | `rag-mcp` | General knowledge-base RAG over HTTP MCP (localhost port 8081 by default) | — |
14817
+ | `rag-mcp-legal` | Polish legal RAG over HTTP MCP (localhost port 8082 by default) | — |
13742
14818
  | `redis` | Redis cache inspection, data management, and monitoring | `REDIS_URL` |
13743
14819
  | `sentry` | Sentry error tracking: issue search, event details, alerting | `SENTRY_AUTH_TOKEN`, `SENTRY_ORG` |
13744
14820
  | `sequential-thinking` | Step-by-step reasoning and problem decomposition | — |
@@ -13772,6 +14848,10 @@ Each template is a JSON file with the following structure:
13772
14848
  - `mcpServers` — the block merged verbatim into `.mcp.json`
13773
14849
  - `env` values use `${VAR_NAME}` placeholders that must be set in the shell environment or `.env` file before Claude Code starts
13774
14850
 
14851
+ `rag-mcp` and `rag-mcp-legal` expose unauthenticated HTTP MCP endpoints by
14852
+ design. Keep the default localhost binding, use a VPN, or protect remote access
14853
+ with a restricted reverse proxy.
14854
+
13775
14855
  ## Example: Adding GitHub and PostgreSQL
13776
14856
 
13777
14857
  ```bash
@@ -14631,17 +15711,17 @@ title: "Plugin Pack Conventions"
14631
15711
  category: reference
14632
15712
  service: ai-toolkit
14633
15713
  tags: [plugins, plugin-packs, conventions, manifests, hooks, policy-packs]
14634
- version: "1.2.0"
15714
+ version: "1.3.0"
14635
15715
  created: "2026-03-28"
14636
- last_updated: "2026-08-18"
14637
- description: "Conventions for experimental ai-toolkit plugin packs, policy packs, hook packs, and plugin-creator scaffolding across Claude Code and Codex runtimes."
15716
+ last_updated: "2026-08-31"
15717
+ description: "Conventions for experimental ai-toolkit plugin packs, policy packs, hook packs, and plugin-creator scaffolding across supported editors."
14638
15718
  ---
14639
15719
 
14640
15720
  # Plugin Pack Conventions
14641
15721
 
14642
15722
  ## Purpose
14643
15723
 
14644
- `ai-toolkit` includes experimental plugin packs under `app/plugins/` for Claude Code and optional global Codex layering, and discovers external packs under `~/.softspark/ai-toolkit/plugins/` (see *Where Packs Live*). These internal pack manifests are distinct from the official uploadable Claude app plugin built by `ai-toolkit claude-app export`.
15724
+ `ai-toolkit` includes experimental plugin packs under `app/plugins/` for Claude Code, Codex, Cursor, and Gemini global layering, and discovers external packs under `~/.softspark/ai-toolkit/plugins/` (see *Where Packs Live*). These internal pack manifests are distinct from the official uploadable Claude app plugin built by `ai-toolkit claude-app export`.
14645
15725
 
14646
15726
  ## Where Packs Live
14647
15727
 
@@ -14697,6 +15777,7 @@ app/plugins/<pack-name>/
14697
15777
  ├── plugin.json
14698
15778
  ├── README.md
14699
15779
  ├── hooks/ # optional, executable if present
15780
+ ├── mcp/ # optional, pack-local MCP templates
14700
15781
  ├── rules/ # optional
14701
15782
  ├── skills/ # optional
14702
15783
  ├── agents/ # optional
@@ -14720,6 +15801,14 @@ Required keys:
14720
15801
  - `skills`
14721
15802
  - `rules`
14722
15803
  - `hooks`
15804
+ - `mcp` (optional MCP template names)
15805
+
15806
+ An MCP reference such as `"rag-mcp-legal"` resolves first to the pack-owned
15807
+ `mcp/rag-mcp-legal.json`, then to the built-in
15808
+ `app/mcp-templates/rag-mcp-legal.json`. Each template must use the same `name`
15809
+ as the reference and provide a non-empty `mcpServers` object. A localhost HTTP
15810
+ template must also include a `postInstall` warning that the endpoint is
15811
+ `unauthenticated`.
14723
15812
 
14724
15813
  ## Naming Rules
14725
15814
 
@@ -14739,10 +15828,12 @@ Required keys:
14739
15828
  ## CLI Management
14740
15829
 
14741
15830
  ```bash
14742
- ai-toolkit plugin list # show all 12 packs with install status
15831
+ ai-toolkit plugin list # show all available packs with install status
14743
15832
  ai-toolkit plugin install --editor claude <name> # Claude Code global target
14744
15833
  ai-toolkit plugin install --editor codex <name> # Codex global target
14745
- ai-toolkit plugin install --editor all --all # install all 12 packs for both runtimes
15834
+ ai-toolkit plugin install --editor cursor <name> # Cursor global target
15835
+ ai-toolkit plugin install --editor gemini <name> # Gemini CLI global target
15836
+ ai-toolkit plugin install --editor all --all # install all available packs for all supported editors
14746
15837
  ai-toolkit plugin update --editor all --all # update all installed packs
14747
15838
  ai-toolkit plugin clean <name> # prune data older than 90 days (default)
14748
15839
  ai-toolkit plugin clean <name> --days 30 # prune data older than 30 days
@@ -14753,21 +15844,25 @@ ai-toolkit plugin status --editor all # show installed packs with r
14753
15844
 
14754
15845
  ### What `plugin install` Does
14755
15846
 
14756
- 1. **Parses** `--editor claude|codex|all` (default: `claude`)
15847
+ 1. **Parses** `--editor claude|codex|cursor|gemini|all` (default: `claude`)
14757
15848
  2. **Copies** plugin-specific hooks to runtime-owned storage: Claude uses `~/.softspark/ai-toolkit/hooks/plugin-<pack>-<hook>.sh`; Codex uses `$CODEX_HOME/ai-toolkit-hooks/plugin-<pack>-<hook>.sh`
14758
15849
  3. **Copies** shared plugin scripts to `~/.softspark/ai-toolkit/plugin-scripts/<pack>/`
14759
15850
  4. **Runs** init scripts if present (e.g. `init_db.py` for memory-pack — safe to re-run, preserves data)
14760
15851
  5. **Claude Code target**: links missing agents/skills into `~/.claude/`, injects plugin-local rules into `~/.claude/CLAUDE.md`, and merges plugin hook entries into `~/.claude/settings.json`
14761
15852
  6. **Codex target**: bootstraps `$CODEX_HOME/AGENTS.md`, `$HOME/.agents/skills`, `$CODEX_HOME/hooks.json`, and self-contained `$CODEX_HOME/ai-toolkit-hooks`, then layers plugin-specific rules and hooks on top; it does not write `~/AGENTS.md` or `.agents/rules/`
14762
- 7. **Records** installed state per runtime in `~/.softspark/ai-toolkit/plugins.json`
15853
+ 7. **Cursor target**: writes each pack-owned rule as `~/.cursor/rules/plugin-<pack>-<rule>.mdc` with `alwaysApply: true`; files are exact-hash owned and collisions are rejected
15854
+ 8. **Gemini target**: marker-injects each pack-owned rule into `~/.gemini/GEMINI.md` as `plugin-<pack>-<rule>`, preserving all unrelated content
15855
+ 9. **Records** installed state per runtime in `~/.softspark/ai-toolkit/plugins.json`
15856
+ 10. **MCP assets**: installs `includes.mcp` into the selected editor's global MCP config, rejects unowned same-name entries, and records the exact normalized server configuration under the plugin's ownership state
14763
15857
 
14764
15858
  ### What `plugin update` Does
14765
15859
 
14766
- 1. **Removes** existing plugin runtime entries for the selected editor(s) (same as `remove`)
14767
- 2. **Reinstalls** from the current source (same as `install`)
14768
- 3. **Preserves plugin data** (e.g. memory-pack SQLite database is never deleted)
14769
- 4. Shared plugin scripts/hooks are kept if another runtime still has the same pack installed
14770
- 5. `--all` updates only currently installed packs for the selected runtime(s)
15860
+ 1. **Preflights** MCP and native-rule collisions before changing any plugin state, skill, rule, hook, or script
15861
+ 2. **Removes** existing plugin runtime entries for the selected editor(s) (same as `remove`)
15862
+ 3. **Reinstalls** from the current source (same as `install`)
15863
+ 4. **Preserves plugin data** (e.g. memory-pack SQLite database is never deleted)
15864
+ 5. Shared plugin scripts/hooks are kept if another runtime still has the same pack installed
15865
+ 6. `--all` updates only currently installed packs for the selected runtime(s)
14771
15866
 
14772
15867
  ### What `plugin clean` Does
14773
15868
 
@@ -14779,10 +15874,12 @@ ai-toolkit plugin status --editor all # show installed packs with r
14779
15874
 
14780
15875
  1. **Claude Code target**: strips plugin hook entries from `~/.claude/settings.json` and removes plugin-local rule sections from `~/.claude/CLAUDE.md`
14781
15876
  2. **Codex target**: strips only command handlers carrying the exact `AI_TOOLKIT_HOOK_OWNER=ai-toolkit-plugin-<pack>` marker from `$CODEX_HOME/hooks.json`, removes owned `$CODEX_HOME/ai-toolkit-hooks/plugin-<pack>-*` assets, and removes the pack's marker-bounded sections from `$CODEX_HOME/AGENTS.md`
14782
- 3. **Claude/shared assets** (`~/.softspark/ai-toolkit/hooks/plugin-*`, `plugin-scripts/<pack>/`) are removed only when no remaining runtime still uses that pack
14783
- 4. **Updates** `plugins.json` state per runtime
14784
- 5. **Leaves** core agents/skills untouched (they belong to the base install)
14785
- 6. **Leaves** plugin data intact (e.g. `memory.db` use `clean` to prune)
15877
+ 3. **Cursor/Gemini rules**: removes only exact content recorded in `rule_ownership`; foreign or user-modified files/sections are preserved with a warning
15878
+ 4. **Claude/shared assets** (`~/.softspark/ai-toolkit/hooks/plugin-*`, `plugin-scripts/<pack>/`) are removed only when no remaining runtime still uses that pack
15879
+ 5. **Updates** `plugins.json` state per runtime
15880
+ 6. **Leaves** core agents/skills untouched (they belong to the base install)
15881
+ 7. **Leaves** plugin data intact (e.g. `memory.db` — use `clean` to prune)
15882
+ 8. **MCP cleanup**: removes only unchanged servers recorded as owned by that plugin; user-created, foreign, or manually changed entries are preserved with a warning
14786
15883
 
14787
15884
  ### Data Retention (memory-pack)
14788
15885
 
@@ -14806,7 +15903,7 @@ time.
14806
15903
  links every core skill and agent, so a manifest naming only core assets resolves
14807
15904
  to nothing: `plugin install` reports `(0 file items)` and no file appears on
14808
15905
  disk. This is not a subtle degradation — it is a complete no-op, identical on
14809
- every profile (`minimal`, `standard`, `strict`) and on both runtimes.
15906
+ every profile (`minimal`, `standard`, `strict`) and on every supported editor.
14810
15907
 
14811
15908
  Nine packs were removed in v4.20.0 for failing this: `csharp`, `java`, `kotlin`,
14812
15909
  `ruby`, `rust`, `swift`, `frontend`, `research`, `security`. Every one declared
@@ -15481,19 +16578,19 @@ title: "Supported Tools Registry"
15481
16578
  category: reference
15482
16579
  service: ai-toolkit
15483
16580
  tags: [editors, platforms, generators, integration, ecosystem]
15484
- version: "1.13.0"
16581
+ version: "1.15.0"
15485
16582
  created: "2026-04-23"
15486
- last_updated: "2026-08-19"
15487
- description: "Human-readable view of scripts/ecosystem_tools.json — the canonical list of tools ai-toolkit integrates with (Claude Code, Claude Chat/Cowork, and 11 editors), their documentation URLs, config paths, our generators, and tracked capability markers."
16583
+ last_updated: "2026-09-01"
16584
+ description: "Human-readable view of scripts/ecosystem_tools.json: Claude Code, Claude Chat/Cowork, 11 editors, and the explicit developer-preview DSH target."
15488
16585
  ---
15489
16586
 
15490
16587
  # Supported Tools Registry
15491
16588
 
15492
- The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed by `scripts/ecosystem_doctor.py`. This document is a derived view when the JSON changes, update this table too.
16589
+ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed by `scripts/ecosystem_doctor.py`. This document is a derived view. Update it whenever the JSON changes.
15493
16590
 
15494
- ## Tool Count: 13
16591
+ ## Tool Count: 14
15495
16592
 
15496
- 1 primary runtime (Claude Code) + 1 Claude app target + 11 editor integrations.
16593
+ 1 primary runtime, 1 Claude app target, 11 editor integrations, and 1 explicit developer-preview harness target.
15497
16594
 
15498
16595
  ---
15499
16596
 
@@ -15536,6 +16633,30 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
15536
16633
 
15537
16634
  ---
15538
16635
 
16636
+ ## Explicit Developer-Preview Harness
16637
+
16638
+ ### DeepSeek Harness
16639
+
16640
+ | Field | Value |
16641
+ |-------|-------|
16642
+ | ID | `dsh` |
16643
+ | Status | `developer-preview`, `explicit-only`. This is a SoftSpark-maintained community compatibility target. DeepSeek AI has not endorsed it. |
16644
+ | Reviewed version | DSH `0.1.1-rc.2`, `@softspark/dsh-codex@1.0.0`, and `@softspark/dsh-orchestrator@1.0.1`. |
16645
+ | Docs | https://deepseek-harness.github.io/deepseek-harness/ |
16646
+ | Release sources | https://github.com/deepseek-ai/deepseek-harness/releases and the reviewed [DSH 0.1.1-rc.2 release](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.1-rc.2) |
16647
+ | Reviewed contracts | Tagged [CLI profile and plugin reference](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/apps/cli/reference/README.md) and [skill discovery reference](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/docs/subsystems/skills.md) |
16648
+ | Config paths | Project `.agents/skills/*/SKILL.md`; profile `$DSH_HOME/profiles/<profile>/package.json`; installed packages under `$DSH_HOME/profiles/<profile>/node_modules/@softspark/`; preset `$DSH_HOME/.agent-presets/softspark-orchestrator` |
16649
+ | Project generator | `scripts/generate_codex_skills.py` emits the shared Codex and DSH `.agents/skills` catalog. `ai-toolkit install --local --editors dsh` makes no `$DSH_HOME` write. |
16650
+ | Profile lifecycle | `scripts/install_steps/dsh.py` implements explicit `install`, `update`, `doctor`, and `uninstall` for one named profile. |
16651
+ | Selection boundary | Excluded from `--editors all`, auto-detection, defaults, default profiles, and global editor selection. |
16652
+ | Authentication | ai-toolkit accepts no provider API key and performs no login. Codex, Claude Code, and GitHub Copilot own authentication. Copilot Gemini usage consumes GitHub AI credits. |
16653
+ | State and recovery | State uses `AI_TOOLKIT_HOME`, then `SOFTSPARK_HOME`, then `~/.softspark/ai-toolkit/state.json`. Locks and compare-and-swap publication protect ownership. Doctor reports preserved recovery markers and drift. |
16654
+ | Upstream drift | Upstream has newer prereleases, including `0.1.2-alpha.2`. They remain unqualified until source review and isolated real-profile verification complete. Phase 3 real-profile evidence is pending. |
16655
+
16656
+ See [DSH Compatibility](./dsh-compatibility.md) for commands, topology, subscription boundaries, lifecycle ownership, and limitations.
16657
+
16658
+ ---
16659
+
15539
16660
  ## Editor Integrations
15540
16661
 
15541
16662
  ### Cursor