@softspark/ai-toolkit 4.29.2 → 4.30.2

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 (42) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +44 -18
  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-verification-sop.md +35 -5
  16. package/kb/reference/architecture-overview.md +24 -5
  17. package/kb/reference/cli-reference.md +1 -1
  18. package/kb/reference/dsh-compatibility.md +183 -0
  19. package/kb/reference/manifest-install.md +112 -5
  20. package/kb/reference/mcp-templates.md +11 -4
  21. package/kb/reference/plugin-pack-conventions.md +35 -18
  22. package/kb/reference/supported-tools-registry.md +30 -6
  23. package/llms-full.txt +1110 -50
  24. package/llms.txt +3 -0
  25. package/manifest.json +2 -2
  26. package/package.json +2 -2
  27. package/scripts/codex_skill_adapter.py +673 -34
  28. package/scripts/config_resolver.py +80 -14
  29. package/scripts/doctor.py +98 -20
  30. package/scripts/ecosystem_tools.json +51 -1
  31. package/scripts/generate_codex_skills.py +22 -20
  32. package/scripts/install.py +30 -13
  33. package/scripts/install_steps/ai_tools.py +97 -33
  34. package/scripts/install_steps/dsh.py +5063 -0
  35. package/scripts/install_steps/install_state.py +1645 -57
  36. package/scripts/mcp_editors.py +5 -2
  37. package/scripts/plugin.py +2495 -163
  38. package/scripts/plugin_mcp.py +279 -0
  39. package/scripts/plugin_rules.py +389 -0
  40. package/scripts/plugin_schema.py +139 -23
  41. package/scripts/uninstall.py +47 -4
  42. 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
@@ -7954,11 +8622,11 @@ git push origin --delete vX.Y.Z
7954
8622
  title: "SOP: Release Verification"
7955
8623
  category: procedures
7956
8624
  service: ai-toolkit
7957
- tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif]
7958
- version: "1.7.0"
8625
+ tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif, dsh]
8626
+ version: "1.8.0"
7959
8627
  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."
8628
+ last_updated: "2026-09-01"
8629
+ 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
8630
  ---
7963
8631
 
7964
8632
  # SOP: Release Verification
@@ -7983,7 +8651,7 @@ Verifies all critical paths from the user's perspective.
7983
8651
 
7984
8652
  ## Quick Checklist (TL;DR)
7985
8653
 
7986
- 14 commands if all pass, the release is ready:
8654
+ The 14 core commands below must pass. Releases that change DSH must also complete Phase 10.
7987
8655
 
7988
8656
  ```bash
7989
8657
  # Pre-commit (Phase 0)
@@ -8396,6 +9064,36 @@ app-native rules skill, bundled agents/skills, and plugin-relative Cowork hooks.
8396
9064
 
8397
9065
  ---
8398
9066
 
9067
+ ## Phase 10: Explicit DSH Qualification (v4.30.0+)
9068
+
9069
+ 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.
9070
+
9071
+ 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.
9072
+
9073
+ ```bash
9074
+ DSH_SMOKE_ROOT="$(mktemp -d)"
9075
+ export DSH_HOME="$DSH_SMOKE_ROOT/dsh-home"
9076
+
9077
+ ai-toolkit dsh install --profile web
9078
+ ai-toolkit dsh doctor --profile web
9079
+ dsh --profile web --host 127.0.0.1 --port 0 --no-open
9080
+ ```
9081
+
9082
+ In a new `softspark-orchestrator` session, select the `codex` provider and run two standalone marker prompts:
9083
+
9084
+ 1. `subagent_claude_code` returns an exact child marker, then the Codex parent returns its exact completion marker.
9085
+ 2. `subagent_gemini_copilot` returns an exact child marker, then the Codex parent returns its exact completion marker.
9086
+
9087
+ Stop DSH, then remove only the managed profile artifacts:
9088
+
9089
+ ```bash
9090
+ ai-toolkit dsh uninstall --profile web --yes
9091
+ ```
9092
+
9093
+ **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.
9094
+
9095
+ ---
9096
+
8399
9097
  ## Troubleshooting
8400
9098
 
8401
9099
  ### `ai-toolkit: command not found`
@@ -8817,17 +9515,17 @@ title: "AI Toolkit - Architecture Overview"
8817
9515
  category: reference
8818
9516
  service: ai-toolkit
8819
9517
  tags: [architecture, overview, design, structure]
8820
- version: "1.8.0"
9518
+ version: "1.10.0"
8821
9519
  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."
9520
+ last_updated: "2026-09-01"
9521
+ description: "Architecture of ai-toolkit: install ownership, runtime adapters, the explicit DSH target, skill tiers, and project integration."
8824
9522
  ---
8825
9523
 
8826
9524
  # AI Toolkit Architecture
8827
9525
 
8828
9526
  ## Purpose
8829
9527
 
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.
9528
+ 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
9529
 
8832
9530
  ## Design Principles
8833
9531
 
@@ -8931,6 +9629,7 @@ Machine (global) Project (local)
8931
9629
  **`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
9630
  - `--editors all` — install all 11 editors (Cursor, Windsurf, Cline, Roo, Aider, Augment, Copilot, Antigravity, Codex, Gemini, opencode)
8933
9631
  - `--editors cursor,aider` — install only selected editors
9632
+ - `--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
9633
  - (no flag) — auto-detect from existing project files; `update --local` picks up whatever editors already have configs
8935
9634
 
8936
9635
  Each editor gets its documented directory-based format. Copilot receives root
@@ -8953,6 +9652,10 @@ packs can layer their rules, skills, and hooks onto that Codex user target.
8953
9652
 
8954
9653
  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
9654
 
9655
+ 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.
9656
+
9657
+ 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.
9658
+
8956
9659
  If a project already has `.mcp.json`, local install mirrors its `mcpServers`
8957
9660
  entries into `.claude/settings.local.json` plus any selected editors with
8958
9661
  project-scoped native MCP files: `.cursor/mcp.json`, `.github/mcp.json`,
@@ -8964,6 +9667,10 @@ project-scoped native MCP files: `.cursor/mcp.json`, `.github/mcp.json`,
8964
9667
  |---------|--------|-------------|
8965
9668
  | `install` | `~/.claude/` | First-time: per-file symlinks + JSON merge + marker injection + rules |
8966
9669
  | `install --local` | `./` | Claude Code configs + editors via `--editors` (auto-detect or explicit) |
9670
+ | `install --local --editors dsh` | `./` | Generic local outputs plus the shared `.agents/skills` catalog; no DSH profile writes |
9671
+ | `dsh install|update --profile <name>` | `$DSH_HOME/profiles/<name>` | Exact SoftSpark package and preset lifecycle |
9672
+ | `dsh doctor --profile <name>` | DSH profile and ai-toolkit state | Read-only runtime, ownership, drift, and recovery diagnostics |
9673
+ | `dsh uninstall --profile <name>` | Managed DSH package, preset, and state entries | Ownership-checked removal that preserves unrelated profile content |
8967
9674
  | `claude-app export` | output ZIP + Markdown | Uploadable Claude Chat/Cowork plugin and global instructions |
8968
9675
  | `update` | `~/.claude/` | Re-apply after npm update or after add-rule/remove-rule |
8969
9676
  | `update --local` | `./` | Re-apply + refresh project-local configs |
@@ -9060,6 +9767,16 @@ translation and hook-compatibility model when targeting the global Codex layer.
9060
9767
 
9061
9768
  See `kb/reference/codex-cli-compatibility.md` for the detailed mapping.
9062
9769
 
9770
+ ### DSH Explicit Target
9771
+
9772
+ 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.
9773
+
9774
+ 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.
9775
+
9776
+ 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.
9777
+
9778
+ See `kb/reference/dsh-compatibility.md` for the exact command, version, authentication, and recovery contract. Real-profile Phase 3 qualification is pending.
9779
+
9063
9780
  ## MCP Rendering Layer
9064
9781
 
9065
9782
  `.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 +9900,7 @@ Severity levels: HIGH (blocks deployment), WARN (should fix), INFO (best practic
9183
9900
  ## Extension Points
9184
9901
 
9185
9902
  ### 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`.
9903
+ `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
9904
 
9188
9905
  ### Language Rules
9189
9906
  `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 +10328,7 @@ Usage: ai-toolkit <command> [options]
9611
10328
 
9612
10329
  | Command | Description |
9613
10330
  |---------|-------------|
9614
- | `mcp list` | List available MCP server templates (26 templates) |
10331
+ | `mcp list` | List available MCP server templates (28 templates) |
9615
10332
  | `mcp editors` | List editors with native MCP config adapters and scopes |
9616
10333
  | `mcp add <name> [names...]` | Add MCP server template(s) to `.mcp.json` |
9617
10334
  | `mcp install --editor <name[,..]> [names...]` | Install templates into native editor MCP config |
@@ -11043,6 +11760,194 @@ This model gives:
11043
11760
 
11044
11761
  ---
11045
11762
 
11763
+ ## kb/reference/dsh-compatibility.md
11764
+
11765
+ ---
11766
+ title: "AI Toolkit - DSH Compatibility"
11767
+ category: reference
11768
+ service: ai-toolkit
11769
+ tags: [dsh, deepseek-harness, subscriptions, lifecycle, compatibility]
11770
+ version: "1.7.0"
11771
+ created: "2026-08-31"
11772
+ last_updated: "2026-09-01"
11773
+ description: "Compatibility contract for project skills and the explicit SoftSpark package lifecycle in DeepSeek Harness."
11774
+ ---
11775
+
11776
+ # DSH Compatibility
11777
+
11778
+ ## Summary
11779
+
11780
+ 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.
11781
+
11782
+ 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.
11783
+
11784
+ ## Project vs Profile Outputs
11785
+
11786
+ | Surface | Command | Managed output | Explicit non-output |
11787
+ |---|---|---|---|
11788
+ | 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 |
11789
+ | 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 |
11790
+
11791
+ 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.
11792
+
11793
+ 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.
11794
+
11795
+ ## Local and Global Commands
11796
+
11797
+ ```bash
11798
+ # Generic local outputs plus DSH-specific project skills
11799
+ ai-toolkit install --local --editors dsh
11800
+
11801
+ # Read-only project preview
11802
+ ai-toolkit install --local --editors dsh --dry-run
11803
+
11804
+ # Explicit machine profile lifecycle
11805
+ ai-toolkit dsh install --profile web
11806
+ ai-toolkit dsh update --profile web
11807
+ ai-toolkit dsh doctor --profile web
11808
+ ai-toolkit dsh uninstall --profile web --yes
11809
+ ```
11810
+
11811
+ 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.
11812
+
11813
+ ## Exact Pins
11814
+
11815
+ | Component | Reviewed version | Role |
11816
+ |---|---:|---|
11817
+ | DeepSeek Harness | `0.1.1-rc.2` | Profile host and plugin manager |
11818
+ | pnpm | `>=11.7.0,<12.0.0` | Package manager used by the DSH plugin command |
11819
+ | `@softspark/dsh-codex` | `1.0.0` | Codex parent provider through local `codex app-server` |
11820
+ | `@softspark/dsh-orchestrator` | `1.0.1` | Claude Code and GitHub Copilot Gemini delegation bundle plus released preset |
11821
+
11822
+ Install and update use exact package arguments with `--save-exact`. Arbitrary DSH prereleases and unpinned SoftSpark packages are outside this contract.
11823
+
11824
+ 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.
11825
+
11826
+ ## Subscription and Authentication Boundaries
11827
+
11828
+ 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:
11829
+
11830
+ | Route | Login owner | Subscription or billing boundary |
11831
+ |---|---|---|
11832
+ | Codex parent | `codex login` and `codex login status` | ChatGPT subscription managed by Codex |
11833
+ | Claude delegate | `claude auth login` | Claude Max or Pro managed by Claude Code |
11834
+ | Gemini delegate | `copilot login` | Active GitHub Copilot plan and GitHub AI credits |
11835
+
11836
+ 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.
11837
+
11838
+ ## DSH, Codex, Claude, and Copilot Topology
11839
+
11840
+ ```text
11841
+ DSH session using SoftSpark Orchestrator
11842
+ |
11843
+ +-> @softspark/dsh-codex
11844
+ | -> local codex app-server
11845
+ | -> Codex-owned ChatGPT authentication and parent thread
11846
+ |
11847
+ +-> subagent_claude_code
11848
+ | -> DSH Claude Code provider
11849
+ | -> Claude Code native login
11850
+ |
11851
+ +-> subagent_gemini_copilot
11852
+ -> GitHub Copilot CLI ACP server
11853
+ -> Gemini 3.6 Flash under GitHub policy and AI credits
11854
+ ```
11855
+
11856
+ Codex is the parent provider. The preset keeps the optional Codex subagent row disabled. Claude Code and Copilot Gemini receive bounded standalone delegation tasks.
11857
+
11858
+ ## Invocation Metadata and Shared Skill Ownership
11859
+
11860
+ 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.
11861
+
11862
+ 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.
11863
+
11864
+ 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.
11865
+
11866
+ ## Lifecycle State and Recovery
11867
+
11868
+ State resolves in this order:
11869
+
11870
+ 1. `$AI_TOOLKIT_HOME/state.json` when `AI_TOOLKIT_HOME` is set.
11871
+ 2. `$SOFTSPARK_HOME/ai-toolkit/state.json` when `SOFTSPARK_HOME` is set.
11872
+ 3. `~/.softspark/ai-toolkit/state.json` by default.
11873
+
11874
+ 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.
11875
+
11876
+ 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.
11877
+
11878
+ 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.
11879
+
11880
+ 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.
11881
+
11882
+ 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.
11883
+
11884
+ 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.
11885
+
11886
+ 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.
11887
+
11888
+ 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.
11889
+
11890
+ ## Unsupported Google, Antigravity, and API-Key Routes
11891
+
11892
+ 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.
11893
+
11894
+ 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.
11895
+
11896
+ ## Behavioral Limits
11897
+
11898
+ - Claude Code and Copilot delegation are one-shot child tasks. Each child receives the task and workspace directory, not the parent conversation history.
11899
+ - 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.
11900
+ - Child effects completed before cancellation are not rolled back.
11901
+ - Workspace content selected by a vendor CLI may leave the machine under that vendor's product terms and account policy.
11902
+ - Codex owns its built-in tools, sandbox, approval policy, thread state, and model execution. ai-toolkit does not reproduce those controls inside DSH.
11903
+ - Existing DSH sessions keep the preset generation with which they started. Restart DSH and open a new session after install or update.
11904
+
11905
+ ## Uninstall, Update, and Doctor
11906
+
11907
+ `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.
11908
+
11909
+ `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.
11910
+
11911
+ `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.
11912
+
11913
+ ## Verification
11914
+
11915
+ Run the static and isolated checks without modifying a regular DSH profile:
11916
+
11917
+ ```bash
11918
+ bats tests/test_ecosystem_doctor.bats
11919
+ bats tests/test_dsh.bats
11920
+ python3 scripts/ecosystem_doctor.py --tool dsh --offline --format text
11921
+ python3 scripts/validate.py --strict
11922
+
11923
+ ai-toolkit install --local --editors dsh --dry-run
11924
+ ai-toolkit dsh install --profile web --dry-run
11925
+ ai-toolkit dsh update --profile web --dry-run
11926
+ ai-toolkit dsh doctor --profile web
11927
+ ai-toolkit dsh uninstall --profile web --dry-run --yes
11928
+ ```
11929
+
11930
+ 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.
11931
+
11932
+ ## Preview and Upstream Drift
11933
+
11934
+ 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.
11935
+
11936
+ 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.
11937
+
11938
+ ## Sources
11939
+
11940
+ - [DeepSeek Harness documentation](https://deepseek-harness.github.io/deepseek-harness/)
11941
+ - [DeepSeek Harness releases](https://github.com/deepseek-ai/deepseek-harness/releases)
11942
+ - [Reviewed DSH 0.1.1-rc.2 release](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.1-rc.2)
11943
+ - [Reviewed DSH package-manager declaration](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/package.json)
11944
+ - [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)
11945
+ - [Reviewed DSH skill discovery contract](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.1-rc.2/docs/subsystems/skills.md)
11946
+ - [PATH: kb/reference/manifest-install.md]
11947
+ - [PATH: kb/history/completed/dsh-native-install-target-plan.md]
11948
+
11949
+ ---
11950
+
11046
11951
  ## kb/reference/enterprise-config-guide.md
11047
11952
 
11048
11953
  ---
@@ -13371,11 +14276,11 @@ source, cross-verify against a second independent copy, and only then write
13371
14276
  title: "Manifest-Driven Install System"
13372
14277
  category: reference
13373
14278
  service: ai-toolkit
13374
- tags: [install, manifest, modules, profiles, auto-detect, state-tracking]
13375
- version: "1.0.0"
14279
+ tags: [install, manifest, modules, profiles, auto-detect, state-tracking, dsh]
14280
+ version: "1.16.0"
13376
14281
  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."
14282
+ last_updated: "2026-09-01"
14283
+ description: "Reference for manifest-driven project installation, explicit DSH profile lifecycle management, and ownership state in ~/.softspark/ai-toolkit/state.json."
13379
14284
  ---
13380
14285
 
13381
14286
  # Manifest-Driven Install System
@@ -13408,7 +14313,7 @@ Modules are defined in `manifest.json` at the repository root. There are 17 modu
13408
14313
  | `rules-php` | PHP-specific rules (5 files) | auto-detect |
13409
14314
  | `rules-cpp` | C++-specific rules (5 files) | auto-detect |
13410
14315
  | `rules-ruby` | Ruby-specific rules (5 files) | auto-detect |
13411
- | `mcp-templates` | 26 MCP server config templates | strict, full |
14316
+ | `mcp-templates` | 28 MCP server config templates | strict, full |
13412
14317
 
13413
14318
  ## Profiles
13414
14319
 
@@ -13488,6 +14393,64 @@ ai-toolkit status
13488
14393
 
13489
14394
  Re-applies installed modules, skipping files whose content hash has not changed since last install. Implemented in `scripts/install_steps/install_state.py`.
13490
14395
 
14396
+ ## Explicit DSH Profile Lifecycle
14397
+
14398
+ The DSH project target and the DSH profile lifecycle are separate operations:
14399
+
14400
+ ```bash
14401
+ # Generic local outputs plus DSH-specific project skills. No DSH profile change.
14402
+ ai-toolkit install --local --editors dsh
14403
+
14404
+ # Read-only project plan, including extends resolution.
14405
+ ai-toolkit install --local --editors dsh --dry-run
14406
+
14407
+ # Explicit global DSH profile mutation. The default profile is web.
14408
+ ai-toolkit dsh install --profile web
14409
+ ai-toolkit dsh update --profile web
14410
+ ai-toolkit dsh doctor --profile web
14411
+ ai-toolkit dsh uninstall --profile web --yes
14412
+ ```
14413
+
14414
+ 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`.
14415
+
14416
+ 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.
14417
+
14418
+ `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.
14419
+
14420
+ 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:
14421
+
14422
+ ```text
14423
+ dsh plugin --profile web add @softspark/dsh-codex@1.0.0 --save-exact
14424
+ dsh plugin --profile web add @softspark/dsh-orchestrator@1.0.1 --save-exact
14425
+ ```
14426
+
14427
+ The orchestrator preset is copied from the installed package:
14428
+
14429
+ ```text
14430
+ $DSH_HOME/profiles/web/node_modules/@softspark/dsh-orchestrator/agent-presets/softspark-orchestrator
14431
+ -> $DSH_HOME/.agent-presets/softspark-orchestrator
14432
+ ```
14433
+
14434
+ 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.
14435
+
14436
+ 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.
14437
+
14438
+ 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.
14439
+
14440
+ 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.
14441
+
14442
+ 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.
14443
+
14444
+ 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.
14445
+
14446
+ 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.
14447
+
14448
+ 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.
14449
+
14450
+ 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.
14451
+
14452
+ 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.
14453
+
13491
14454
  ## State Tracking
13492
14455
 
13493
14456
  Installed module state is persisted to `~/.softspark/ai-toolkit/state.json`:
@@ -13500,14 +14463,61 @@ Installed module state is persisted to `~/.softspark/ai-toolkit/state.json`:
13500
14463
  "last_updated": "2026-04-07T10:00:00Z",
13501
14464
  "file_hashes": {
13502
14465
  "app/hooks/session-start.sh": "abc123..."
14466
+ },
14467
+ "dsh": {
14468
+ "profiles": {
14469
+ "web": {
14470
+ "dsh_home": "/Users/example/.dsh",
14471
+ "profile": "web",
14472
+ "packages": {
14473
+ "@softspark/dsh-codex": "1.0.0",
14474
+ "@softspark/dsh-orchestrator": "1.0.1"
14475
+ },
14476
+ "package_trees": {
14477
+ "@softspark/dsh-codex": {
14478
+ "digest": "<canonical-tree-sha256>",
14479
+ "entries": [
14480
+ {"type": "directory", "path": ".", "mode": 493},
14481
+ {"type": "file", "path": "package.json", "mode": 420, "size": 53, "sha256": "<file-sha256>"}
14482
+ ]
14483
+ },
14484
+ "@softspark/dsh-orchestrator": {
14485
+ "digest": "<canonical-tree-sha256>",
14486
+ "entries": [
14487
+ {"type": "directory", "path": ".", "mode": 493}
14488
+ ]
14489
+ }
14490
+ },
14491
+ "preset_path": "/Users/example/.dsh/.agent-presets/softspark-orchestrator",
14492
+ "preset_hash": "<sha256>",
14493
+ "owned": true,
14494
+ "installed_at": "2026-08-29T08:00:00Z",
14495
+ "last_updated": "2026-08-29T08:00:00Z"
14496
+ }
14497
+ }
13503
14498
  }
13504
14499
  }
13505
14500
  ```
13506
14501
 
13507
14502
  - `installed_modules` — used by `update` to know which modules to re-apply
13508
14503
  - `file_hashes` — used to skip unchanged files during `update`
14504
+ - `dsh.profiles` records the DSH home, profile, exact package versions, canonical package-tree inventories, preset path and hash, ownership, and timestamps
13509
14505
  - The file is written after every successful install or update
13510
14506
 
14507
+ 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.
14508
+
14509
+ 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.
14510
+
14511
+ 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.
14512
+
14513
+ 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.
14514
+
14515
+ 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.
14516
+
14517
+ 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.
14518
+
14519
+ 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.
14520
+
13511
14521
  ## Implementation Files
13512
14522
 
13513
14523
  | File | Purpose |
@@ -13515,6 +14525,7 @@ Installed module state is persisted to `~/.softspark/ai-toolkit/state.json`:
13515
14525
  | `manifest.json` | Module and profile definitions |
13516
14526
  | `scripts/install_steps/detect_language.py` | Auto-detect project language from marker files |
13517
14527
  | `scripts/install_steps/install_state.py` | Read/write `~/.softspark/ai-toolkit/state.json` |
14528
+ | `scripts/install_steps/dsh.py` | Explicit DSH install, update, doctor, uninstall, and recovery lifecycle |
13518
14529
 
13519
14530
  ## Backward Compatibility
13520
14531
 
@@ -13532,6 +14543,7 @@ No existing install scripts or CI configurations need changes.
13532
14543
  - [PATH: kb/reference/language-rules.md] — language rules structure and auto-detection detail
13533
14544
  - [PATH: kb/reference/mcp-templates.md] — MCP server templates (the `mcp-templates` module)
13534
14545
  - [PATH: kb/reference/architecture-overview.md] — overall install model
14546
+ - [PATH: kb/reference/dsh-compatibility.md] - DSH commands, topology, authentication, and preview limits
13535
14547
 
13536
14548
  ---
13537
14549
 
@@ -13655,17 +14667,17 @@ title: "MCP Server Templates"
13655
14667
  category: reference
13656
14668
  service: ai-toolkit
13657
14669
  tags: [mcp, templates, servers, configuration, editors, inject-mcp, external-templates]
13658
- version: "1.5.0"
14670
+ version: "1.6.0"
13659
14671
  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."
14672
+ last_updated: "2026-08-31"
14673
+ description: "Reference for 28 built-in MCP server templates, external template injection via inject-mcp, and native editor MCP installation support."
13662
14674
  ---
13663
14675
 
13664
14676
  # MCP Server Templates
13665
14677
 
13666
14678
  ## Overview
13667
14679
 
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.
14680
+ 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
14681
 
13670
14682
  **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
14683
 
@@ -13731,6 +14743,7 @@ loads `.codex/config.toml` only for trusted project layers.
13731
14743
  | `filesystem` | Local filesystem access for reading, writing, and searching files | — |
13732
14744
  | `git` | Git repository inspection: diffs, logs, branches | — |
13733
14745
  | `github` | GitHub API: issues, PRs, repos, code search | `GITHUB_PERSONAL_ACCESS_TOKEN` |
14746
+ | `jira` | Jira multi-instance routing, ADF, caching, and comment templates | — |
13734
14747
  | `google-drive` | Google Drive file search, reading, and management | `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI` |
13735
14748
  | `google-maps` | Google Maps geocoding, directions, place search | `GOOGLE_MAPS_API_KEY` |
13736
14749
  | `grafana` | Grafana dashboard queries, alerting, and data source management | `GRAFANA_URL`, `GRAFANA_API_KEY` |
@@ -13739,6 +14752,8 @@ loads `.codex/config.toml` only for trusted project layers.
13739
14752
  | `notion` | Notion workspace: pages, databases, content management | `NOTION_API_KEY` |
13740
14753
  | `postgres` | PostgreSQL database access, schema inspection, analysis | — |
13741
14754
  | `puppeteer` | Browser automation: screenshots, navigation, web scraping | — |
14755
+ | `rag-mcp` | General knowledge-base RAG over HTTP MCP (localhost port 8081 by default) | — |
14756
+ | `rag-mcp-legal` | Polish legal RAG over HTTP MCP (localhost port 8082 by default) | — |
13742
14757
  | `redis` | Redis cache inspection, data management, and monitoring | `REDIS_URL` |
13743
14758
  | `sentry` | Sentry error tracking: issue search, event details, alerting | `SENTRY_AUTH_TOKEN`, `SENTRY_ORG` |
13744
14759
  | `sequential-thinking` | Step-by-step reasoning and problem decomposition | — |
@@ -13772,6 +14787,10 @@ Each template is a JSON file with the following structure:
13772
14787
  - `mcpServers` — the block merged verbatim into `.mcp.json`
13773
14788
  - `env` values use `${VAR_NAME}` placeholders that must be set in the shell environment or `.env` file before Claude Code starts
13774
14789
 
14790
+ `rag-mcp` and `rag-mcp-legal` expose unauthenticated HTTP MCP endpoints by
14791
+ design. Keep the default localhost binding, use a VPN, or protect remote access
14792
+ with a restricted reverse proxy.
14793
+
13775
14794
  ## Example: Adding GitHub and PostgreSQL
13776
14795
 
13777
14796
  ```bash
@@ -14631,17 +15650,17 @@ title: "Plugin Pack Conventions"
14631
15650
  category: reference
14632
15651
  service: ai-toolkit
14633
15652
  tags: [plugins, plugin-packs, conventions, manifests, hooks, policy-packs]
14634
- version: "1.2.0"
15653
+ version: "1.3.0"
14635
15654
  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."
15655
+ last_updated: "2026-08-31"
15656
+ description: "Conventions for experimental ai-toolkit plugin packs, policy packs, hook packs, and plugin-creator scaffolding across supported editors."
14638
15657
  ---
14639
15658
 
14640
15659
  # Plugin Pack Conventions
14641
15660
 
14642
15661
  ## Purpose
14643
15662
 
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`.
15663
+ `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
15664
 
14646
15665
  ## Where Packs Live
14647
15666
 
@@ -14697,6 +15716,7 @@ app/plugins/<pack-name>/
14697
15716
  ├── plugin.json
14698
15717
  ├── README.md
14699
15718
  ├── hooks/ # optional, executable if present
15719
+ ├── mcp/ # optional, pack-local MCP templates
14700
15720
  ├── rules/ # optional
14701
15721
  ├── skills/ # optional
14702
15722
  ├── agents/ # optional
@@ -14720,6 +15740,14 @@ Required keys:
14720
15740
  - `skills`
14721
15741
  - `rules`
14722
15742
  - `hooks`
15743
+ - `mcp` (optional MCP template names)
15744
+
15745
+ An MCP reference such as `"rag-mcp-legal"` resolves first to the pack-owned
15746
+ `mcp/rag-mcp-legal.json`, then to the built-in
15747
+ `app/mcp-templates/rag-mcp-legal.json`. Each template must use the same `name`
15748
+ as the reference and provide a non-empty `mcpServers` object. A localhost HTTP
15749
+ template must also include a `postInstall` warning that the endpoint is
15750
+ `unauthenticated`.
14723
15751
 
14724
15752
  ## Naming Rules
14725
15753
 
@@ -14739,10 +15767,12 @@ Required keys:
14739
15767
  ## CLI Management
14740
15768
 
14741
15769
  ```bash
14742
- ai-toolkit plugin list # show all 12 packs with install status
15770
+ ai-toolkit plugin list # show all available packs with install status
14743
15771
  ai-toolkit plugin install --editor claude <name> # Claude Code global target
14744
15772
  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
15773
+ ai-toolkit plugin install --editor cursor <name> # Cursor global target
15774
+ ai-toolkit plugin install --editor gemini <name> # Gemini CLI global target
15775
+ ai-toolkit plugin install --editor all --all # install all available packs for all supported editors
14746
15776
  ai-toolkit plugin update --editor all --all # update all installed packs
14747
15777
  ai-toolkit plugin clean <name> # prune data older than 90 days (default)
14748
15778
  ai-toolkit plugin clean <name> --days 30 # prune data older than 30 days
@@ -14753,21 +15783,25 @@ ai-toolkit plugin status --editor all # show installed packs with r
14753
15783
 
14754
15784
  ### What `plugin install` Does
14755
15785
 
14756
- 1. **Parses** `--editor claude|codex|all` (default: `claude`)
15786
+ 1. **Parses** `--editor claude|codex|cursor|gemini|all` (default: `claude`)
14757
15787
  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
15788
  3. **Copies** shared plugin scripts to `~/.softspark/ai-toolkit/plugin-scripts/<pack>/`
14759
15789
  4. **Runs** init scripts if present (e.g. `init_db.py` for memory-pack — safe to re-run, preserves data)
14760
15790
  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
15791
  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`
15792
+ 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
15793
+ 8. **Gemini target**: marker-injects each pack-owned rule into `~/.gemini/GEMINI.md` as `plugin-<pack>-<rule>`, preserving all unrelated content
15794
+ 9. **Records** installed state per runtime in `~/.softspark/ai-toolkit/plugins.json`
15795
+ 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
15796
 
14764
15797
  ### What `plugin update` Does
14765
15798
 
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)
15799
+ 1. **Preflights** MCP and native-rule collisions before changing any plugin state, skill, rule, hook, or script
15800
+ 2. **Removes** existing plugin runtime entries for the selected editor(s) (same as `remove`)
15801
+ 3. **Reinstalls** from the current source (same as `install`)
15802
+ 4. **Preserves plugin data** (e.g. memory-pack SQLite database is never deleted)
15803
+ 5. Shared plugin scripts/hooks are kept if another runtime still has the same pack installed
15804
+ 6. `--all` updates only currently installed packs for the selected runtime(s)
14771
15805
 
14772
15806
  ### What `plugin clean` Does
14773
15807
 
@@ -14779,10 +15813,12 @@ ai-toolkit plugin status --editor all # show installed packs with r
14779
15813
 
14780
15814
  1. **Claude Code target**: strips plugin hook entries from `~/.claude/settings.json` and removes plugin-local rule sections from `~/.claude/CLAUDE.md`
14781
15815
  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)
15816
+ 3. **Cursor/Gemini rules**: removes only exact content recorded in `rule_ownership`; foreign or user-modified files/sections are preserved with a warning
15817
+ 4. **Claude/shared assets** (`~/.softspark/ai-toolkit/hooks/plugin-*`, `plugin-scripts/<pack>/`) are removed only when no remaining runtime still uses that pack
15818
+ 5. **Updates** `plugins.json` state per runtime
15819
+ 6. **Leaves** core agents/skills untouched (they belong to the base install)
15820
+ 7. **Leaves** plugin data intact (e.g. `memory.db` — use `clean` to prune)
15821
+ 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
15822
 
14787
15823
  ### Data Retention (memory-pack)
14788
15824
 
@@ -14806,7 +15842,7 @@ time.
14806
15842
  links every core skill and agent, so a manifest naming only core assets resolves
14807
15843
  to nothing: `plugin install` reports `(0 file items)` and no file appears on
14808
15844
  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.
15845
+ every profile (`minimal`, `standard`, `strict`) and on every supported editor.
14810
15846
 
14811
15847
  Nine packs were removed in v4.20.0 for failing this: `csharp`, `java`, `kotlin`,
14812
15848
  `ruby`, `rust`, `swift`, `frontend`, `research`, `security`. Every one declared
@@ -15481,19 +16517,19 @@ title: "Supported Tools Registry"
15481
16517
  category: reference
15482
16518
  service: ai-toolkit
15483
16519
  tags: [editors, platforms, generators, integration, ecosystem]
15484
- version: "1.13.0"
16520
+ version: "1.15.0"
15485
16521
  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."
16522
+ last_updated: "2026-09-01"
16523
+ description: "Human-readable view of scripts/ecosystem_tools.json: Claude Code, Claude Chat/Cowork, 11 editors, and the explicit developer-preview DSH target."
15488
16524
  ---
15489
16525
 
15490
16526
  # Supported Tools Registry
15491
16527
 
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.
16528
+ 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
16529
 
15494
- ## Tool Count: 13
16530
+ ## Tool Count: 14
15495
16531
 
15496
- 1 primary runtime (Claude Code) + 1 Claude app target + 11 editor integrations.
16532
+ 1 primary runtime, 1 Claude app target, 11 editor integrations, and 1 explicit developer-preview harness target.
15497
16533
 
15498
16534
  ---
15499
16535
 
@@ -15536,6 +16572,30 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
15536
16572
 
15537
16573
  ---
15538
16574
 
16575
+ ## Explicit Developer-Preview Harness
16576
+
16577
+ ### DeepSeek Harness
16578
+
16579
+ | Field | Value |
16580
+ |-------|-------|
16581
+ | ID | `dsh` |
16582
+ | Status | `developer-preview`, `explicit-only`. This is a SoftSpark-maintained community compatibility target. DeepSeek AI has not endorsed it. |
16583
+ | Reviewed version | DSH `0.1.1-rc.2`, `@softspark/dsh-codex@1.0.0`, and `@softspark/dsh-orchestrator@1.0.1`. |
16584
+ | Docs | https://deepseek-harness.github.io/deepseek-harness/ |
16585
+ | 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) |
16586
+ | 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) |
16587
+ | 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` |
16588
+ | 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. |
16589
+ | Profile lifecycle | `scripts/install_steps/dsh.py` implements explicit `install`, `update`, `doctor`, and `uninstall` for one named profile. |
16590
+ | Selection boundary | Excluded from `--editors all`, auto-detection, defaults, default profiles, and global editor selection. |
16591
+ | 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. |
16592
+ | 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. |
16593
+ | 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. |
16594
+
16595
+ See [DSH Compatibility](./dsh-compatibility.md) for commands, topology, subscription boundaries, lifecycle ownership, and limitations.
16596
+
16597
+ ---
16598
+
15539
16599
  ## Editor Integrations
15540
16600
 
15541
16601
  ### Cursor