@colin4k1024/tsp 2.4.0 → 2.4.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 (230) hide show
  1. package/README.md +87 -4
  2. package/bin/lib/post-install-bridge.js +2 -2
  3. package/bin/tsp-create.js +11 -11
  4. package/commands/team-help.md +2 -2
  5. package/commands/team-plan.md +1 -1
  6. package/commands/update-codemaps.md +3 -2
  7. package/docs/.vitepress/config.mts +199 -0
  8. package/docs/adr/ADR-001-doc-architecture-integration.md +33 -0
  9. package/docs/guides/README.md +5 -0
  10. package/docs/guides/installation.md +33 -0
  11. package/docs/guides/user-guide.md +36 -0
  12. package/docs/index.md +65 -0
  13. package/docs/memory/backlog.md +10 -0
  14. package/docs/memory/decisions.md +43 -0
  15. package/docs/memory/lessons-learned.md +87 -0
  16. package/docs/plans/2026-04-03-python-remnants-audit.md +265 -0
  17. package/docs/plans/2026-04-03-scripts-python-to-js-migration.md +372 -0
  18. package/docs/plans/2026-04-03-solo-delivery-execution-checklist.md +413 -0
  19. package/docs/plans/2026-04-03-solo-delivery-gap-plan.md +377 -0
  20. package/docs/plans/2026-04-03-team-skills-workflow-gates.md +548 -0
  21. package/docs/plans/2026-04-21-open-source-readiness-gap-plan.md +217 -0
  22. package/docs/plans/llm-surface-reduction-audit.md +147 -0
  23. package/docs/plans/llm-surface-reduction-execution-checklist.md +217 -0
  24. package/docs/plans/llm-surface-reduction-execution-history.md +124 -0
  25. package/docs/plans/team-skills-platform-migration.md +54 -0
  26. package/docs/presentation/README.md +42 -0
  27. package/docs/presentation/audience-presentation-route-map.md +84 -0
  28. package/docs/presentation/executive-briefing-talk-track.md +50 -0
  29. package/docs/presentation/generate_capability_matrix.py +396 -0
  30. package/docs/presentation/generate_ppt.py +354 -0
  31. package/docs/presentation/implementation-onboarding-brief.md +38 -0
  32. package/docs/presentation/presentation-talk-track.md +97 -0
  33. package/docs/presentation/vertical-scenario-route-map.md +99 -0
  34. package/docs/presentation/workshop-facilitator-guide.md +47 -0
  35. package/docs/runbooks/actionlint-workflow-gates.md +80 -0
  36. package/docs/runbooks/agent-governance.md +131 -0
  37. package/docs/runbooks/ai-eval-platform-demo-execution-log.md +147 -0
  38. package/docs/runbooks/ai-eval-platform-demo-script.md +136 -0
  39. package/docs/runbooks/ai-eval-platform-walkthrough.md +113 -0
  40. package/docs/runbooks/ai-pr-review-automation.md +56 -0
  41. package/docs/runbooks/api-breaking-change-gates.md +58 -0
  42. package/docs/runbooks/api-design-evolution-walkthrough.md +42 -0
  43. package/docs/runbooks/api-lint-gates.md +57 -0
  44. package/docs/runbooks/api-mocking-strategy-and-lifecycle-guide.md +47 -0
  45. package/docs/runbooks/architect-daily-operations.md +63 -0
  46. package/docs/runbooks/architect-design-conversation-example.md +83 -0
  47. package/docs/runbooks/artifact-attestation-gates.md +75 -0
  48. package/docs/runbooks/artifact-persistence.md +257 -0
  49. package/docs/runbooks/backend-engineer-daily-operations.md +63 -0
  50. package/docs/runbooks/batch-optimization-completion-checklist.md +104 -0
  51. package/docs/runbooks/biz-service-designer-end-to-end-conversation-example.md +5 -0
  52. package/docs/runbooks/biz-service-designer-toolkit.md +5 -0
  53. package/docs/runbooks/bug-fix-complete-walkthrough.md +60 -0
  54. package/docs/runbooks/build-failure-recovery-walkthrough.md +40 -0
  55. package/docs/runbooks/canary-decision-matrix.md +41 -0
  56. package/docs/runbooks/canary-staging-release-walkthrough.md +46 -0
  57. package/docs/runbooks/checkov-iac-gates.md +104 -0
  58. package/docs/runbooks/claude-code-review-workflow.md +72 -0
  59. package/docs/runbooks/claude-conversation-prompt-recipes.md +132 -0
  60. package/docs/runbooks/claude-end-to-end-conversation-example.md +198 -0
  61. package/docs/runbooks/claude-feature-development-guide.md +112 -0
  62. package/docs/runbooks/claude-quick-start.md +227 -0
  63. package/docs/runbooks/claude-usage-scenarios.md +176 -0
  64. package/docs/runbooks/code-review-collaboration-walkthrough.md +65 -0
  65. package/docs/runbooks/codeql-pr-security-gates.md +64 -0
  66. package/docs/runbooks/codex-end-to-end-conversation-example.md +166 -0
  67. package/docs/runbooks/codex-multi-agent-orchestration.md +65 -0
  68. package/docs/runbooks/codex-parallel-prompt-recipes.md +131 -0
  69. package/docs/runbooks/codex-quick-start.md +223 -0
  70. package/docs/runbooks/codex-usage-scenarios.md +168 -0
  71. package/docs/runbooks/codex-workflow-essentials.md +88 -0
  72. package/docs/runbooks/command-and-capability-matrix.md +162 -0
  73. package/docs/runbooks/conftest-policy-gates.md +84 -0
  74. package/docs/runbooks/consumer-driven-contract-testing-with-mock-alignment.md +45 -0
  75. package/docs/runbooks/contract-testing-playbook.md +78 -0
  76. package/docs/runbooks/cosign-signing-gates.md +71 -0
  77. package/docs/runbooks/cross-role-issue-triage-walkthrough.md +47 -0
  78. package/docs/runbooks/cursor-quick-start.md +123 -0
  79. package/docs/runbooks/custom-overlay.md +115 -0
  80. package/docs/runbooks/data-ml-pipeline-demo-execution-log.md +141 -0
  81. package/docs/runbooks/data-ml-pipeline-demo-script.md +102 -0
  82. package/docs/runbooks/data-ml-pipeline-walkthrough.md +119 -0
  83. package/docs/runbooks/data-observability-quality-demo-execution-log.md +36 -0
  84. package/docs/runbooks/data-observability-quality-demo-script.md +42 -0
  85. package/docs/runbooks/data-observability-quality-walkthrough.md +86 -0
  86. package/docs/runbooks/demo-deliverables-overview.md +278 -0
  87. package/docs/runbooks/demo-execution-log.md +530 -0
  88. package/docs/runbooks/demo-scenario.md +129 -0
  89. package/docs/runbooks/dependency-review-gates.md +63 -0
  90. package/docs/runbooks/dependency-update-automation.md +83 -0
  91. package/docs/runbooks/design-md-workflow.md +185 -0
  92. package/docs/runbooks/devops-engineer-daily-operations.md +60 -0
  93. package/docs/runbooks/devops-release-conversation-example.md +88 -0
  94. package/docs/runbooks/doc-architecture-integration.md +59 -0
  95. package/docs/runbooks/doc-architecture-quick-start.md +122 -0
  96. package/docs/runbooks/document-execution-audit.md +32 -0
  97. package/docs/runbooks/documentation-update-walkthrough.md +37 -0
  98. package/docs/runbooks/ecc-harness-usage.md +93 -0
  99. package/docs/runbooks/error-experience-usage.md +116 -0
  100. package/docs/runbooks/evolution-usage.md +162 -0
  101. package/docs/runbooks/executive-value-one-page.md +55 -0
  102. package/docs/runbooks/external-capability-approval-and-enablement-workflow.md +39 -0
  103. package/docs/runbooks/external-capability-intake.md +160 -0
  104. package/docs/runbooks/first-team-command-60-seconds.md +96 -0
  105. package/docs/runbooks/first-team-workflow-walkthrough.md +245 -0
  106. package/docs/runbooks/frontend-backend-integration-acceptance-checklist.md +46 -0
  107. package/docs/runbooks/frontend-backend-parallel-integration-walkthrough.md +48 -0
  108. package/docs/runbooks/frontend-bugfix-one-page.md +82 -0
  109. package/docs/runbooks/frontend-engineer-daily-operations.md +60 -0
  110. package/docs/runbooks/frontend-enterprise-style-profile.md +5 -0
  111. package/docs/runbooks/frontend-governance.md +47 -0
  112. package/docs/runbooks/frontend-refactor-walkthrough.md +42 -0
  113. package/docs/runbooks/git-pr-workflow.md +63 -0
  114. package/docs/runbooks/github-actions-supply-chain-demo-execution-log.md +158 -0
  115. package/docs/runbooks/github-actions-supply-chain-demo-script.md +150 -0
  116. package/docs/runbooks/github-actions-supply-chain-walkthrough.md +117 -0
  117. package/docs/runbooks/github-token-permissions-baseline.md +92 -0
  118. package/docs/runbooks/gitlab-manual-pipeline-release.md +5 -0
  119. package/docs/runbooks/gitlab-release-integration-playbook.md +5 -0
  120. package/docs/runbooks/gitnexus-code-intelligence-usage.md +133 -0
  121. package/docs/runbooks/graphify-knowledge-graph-usage.md +88 -0
  122. package/docs/runbooks/handoff-filling-guide-with-examples.md +70 -0
  123. package/docs/runbooks/handoff-governance.md +250 -0
  124. package/docs/runbooks/helm-unittest-playbook.md +101 -0
  125. package/docs/runbooks/hotfix-emergency-release-walkthrough.md +60 -0
  126. package/docs/runbooks/iac-kubernetes-platform-demo-execution-log.md +144 -0
  127. package/docs/runbooks/iac-kubernetes-platform-demo-script.md +130 -0
  128. package/docs/runbooks/iac-kubernetes-platform-walkthrough.md +120 -0
  129. package/docs/runbooks/implementation-onboarding-reading-path.md +67 -0
  130. package/docs/runbooks/in-toto-attestation-framework.md +94 -0
  131. package/docs/runbooks/incident-severity-triage-tree.md +43 -0
  132. package/docs/runbooks/incident-triage-one-page.md +65 -0
  133. package/docs/runbooks/internal-developer-platform-demo-execution-log.md +36 -0
  134. package/docs/runbooks/internal-developer-platform-demo-script.md +42 -0
  135. package/docs/runbooks/internal-developer-platform-walkthrough.md +91 -0
  136. package/docs/runbooks/karpathy-guidelines-usage.md +27 -0
  137. package/docs/runbooks/kubeconform-schema-gates.md +100 -0
  138. package/docs/runbooks/kubectl-server-dry-run-gates.md +103 -0
  139. package/docs/runbooks/kyverno-policy-gates.md +90 -0
  140. package/docs/runbooks/langfuse-and-observability-integration-guide.md +43 -0
  141. package/docs/runbooks/langfuse-coding-trace.md +44 -0
  142. package/docs/runbooks/mobile-miniapp-delivery-walkthrough.md +112 -0
  143. package/docs/runbooks/mobile-miniapp-demo-execution-log.md +139 -0
  144. package/docs/runbooks/mobile-miniapp-demo-script.md +129 -0
  145. package/docs/runbooks/multi-service-backend-integration-walkthrough.md +61 -0
  146. package/docs/runbooks/open-design-integration.md +163 -0
  147. package/docs/runbooks/open-source-release-checklist.md +90 -0
  148. package/docs/runbooks/opencode-quick-start.md +128 -0
  149. package/docs/runbooks/parallel-development-coordination-walkthrough.md +47 -0
  150. package/docs/runbooks/parallel-execution-usage.md +179 -0
  151. package/docs/runbooks/platform-capability-demo-execution-log.md +184 -0
  152. package/docs/runbooks/platform-capability-demo-script.md +192 -0
  153. package/docs/runbooks/plugin-extension-platform-demo-execution-log.md +136 -0
  154. package/docs/runbooks/plugin-extension-platform-demo-script.md +102 -0
  155. package/docs/runbooks/plugin-extension-platform-walkthrough.md +111 -0
  156. package/docs/runbooks/policy-controller-gates.md +75 -0
  157. package/docs/runbooks/post-rollback-verification-checklist.md +37 -0
  158. package/docs/runbooks/pre-release-checklist.md +50 -0
  159. package/docs/runbooks/product-manager-clarification-conversation-example.md +90 -0
  160. package/docs/runbooks/product-manager-daily-operations.md +60 -0
  161. package/docs/runbooks/production-incident-response-walkthrough.md +50 -0
  162. package/docs/runbooks/project-claude-design-rationale.md +188 -0
  163. package/docs/runbooks/project-manager-daily-operations.md +61 -0
  164. package/docs/runbooks/project-manager-planning-conversation-example.md +82 -0
  165. package/docs/runbooks/project-onboarding.md +452 -0
  166. package/docs/runbooks/qa-engineer-daily-operations.md +63 -0
  167. package/docs/runbooks/qa-review-conversation-example.md +87 -0
  168. package/docs/runbooks/release-closure-one-page.md +65 -0
  169. package/docs/runbooks/release-governance-reading-path.md +56 -0
  170. package/docs/runbooks/release-notes-automation.md +48 -0
  171. package/docs/runbooks/release-rollback-recovery-walkthrough.md +47 -0
  172. package/docs/runbooks/requirement-clarity-and-scope-walkthrough.md +46 -0
  173. package/docs/runbooks/reviewdog-pr-gates.md +49 -0
  174. package/docs/runbooks/role-prompt-recipes.md +130 -0
  175. package/docs/runbooks/rtk-integration-intake.md +45 -0
  176. package/docs/runbooks/rtk-token-optimization-usage.md +107 -0
  177. package/docs/runbooks/runner-egress-hardening.md +81 -0
  178. package/docs/runbooks/runtime-capabilities-overview.md +113 -0
  179. package/docs/runbooks/sbom-generation-gates.md +71 -0
  180. package/docs/runbooks/scorecard-supply-chain-gates.md +82 -0
  181. package/docs/runbooks/secret-scanning-gates.md +85 -0
  182. package/docs/runbooks/security-compliance-platform-demo-execution-log.md +36 -0
  183. package/docs/runbooks/security-compliance-platform-demo-script.md +49 -0
  184. package/docs/runbooks/security-compliance-platform-walkthrough.md +98 -0
  185. package/docs/runbooks/slsa-generator-patterns.md +73 -0
  186. package/docs/runbooks/slsa-verification-gates.md +75 -0
  187. package/docs/runbooks/solo-delivery-mode.md +142 -0
  188. package/docs/runbooks/solo-delivery-one-page.md +111 -0
  189. package/docs/runbooks/specialist-commands-playbook.md +85 -0
  190. package/docs/runbooks/sub-agent-invocation-map.md +144 -0
  191. package/docs/runbooks/system-architecture-design-walkthrough.md +49 -0
  192. package/docs/runbooks/team-closeout-example.md +73 -0
  193. package/docs/runbooks/team-command-output-contracts.md +358 -0
  194. package/docs/runbooks/team-commands-quick-prompts.md +125 -0
  195. package/docs/runbooks/team-execute-example.md +63 -0
  196. package/docs/runbooks/team-handoff-example.md +49 -0
  197. package/docs/runbooks/team-intake-example.md +70 -0
  198. package/docs/runbooks/team-plan-example.md +62 -0
  199. package/docs/runbooks/team-release-example.md +63 -0
  200. package/docs/runbooks/team-review-example.md +61 -0
  201. package/docs/runbooks/team-skills-test-run.md +184 -0
  202. package/docs/runbooks/team-skills-usage.md +336 -0
  203. package/docs/runbooks/team-training-reading-path.md +64 -0
  204. package/docs/runbooks/tech-lead-closure-conversation-example.md +78 -0
  205. package/docs/runbooks/tech-lead-daily-operations.md +67 -0
  206. package/docs/runbooks/trivy-security-gates.md +79 -0
  207. package/docs/runbooks/troubleshooting.md +234 -0
  208. package/docs/runbooks/vertical-scenario-capability-matrix.md +107 -0
  209. package/docs/runbooks/witness-policy-gates.md +78 -0
  210. package/docs/runbooks/zizmor-workflow-audits.md +81 -0
  211. package/manifests/install-components.json +9 -1
  212. package/manifests/install-modules.json +38 -2
  213. package/manifests/install-profiles.json +2 -0
  214. package/package.json +4 -1
  215. package/scripts/gitnexus-preflight.js +187 -0
  216. package/scripts/install-apply.js +9 -0
  217. package/scripts/install-open-design.js +206 -0
  218. package/scripts/install-plan.js +17 -0
  219. package/scripts/lib/install/apply.js +31 -0
  220. package/scripts/lib/install-executor.js +56 -0
  221. package/scripts/lib/team-skills-data.json +7 -6
  222. package/scripts/project-progress.js +852 -0
  223. package/scripts/release-health-summary.js +49 -7
  224. package/scripts/release.sh +1 -1
  225. package/scripts/validate-packed-tarball.js +25 -0
  226. package/scripts/workflow-help.js +3 -3
  227. package/skills/gitnexus/SKILL.md +60 -0
  228. package/skills/gitnexus/agents/openai.yaml +4 -0
  229. package/skills/open-design/SKILL.md +87 -0
  230. package/skills/open-design/agents/openai.yaml +4 -0
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+
4
+ const { spawnSync } = require('child_process')
5
+
6
+ const MIN_NODE_MAJOR = 20
7
+ const PACKAGE_NAME = 'gitnexus'
8
+ const NPM_METADATA_TIMEOUT_MS = 8000
9
+
10
+ function run(command, args, options = {}) {
11
+ return spawnSync(command, args, {
12
+ encoding: 'utf8',
13
+ ...options,
14
+ })
15
+ }
16
+
17
+ function summarizeCommandFailure(result) {
18
+ if (result.error) {
19
+ return result.error.message
20
+ }
21
+
22
+ return `${result.stdout || ''}${result.stderr || ''}`
23
+ .split(/\r?\n/)
24
+ .map((line) => line.trim())
25
+ .filter(Boolean)
26
+ .slice(0, 4)
27
+ .join(' | ')
28
+ }
29
+
30
+ function parseNodeVersion(text) {
31
+ const match = String(text || '').trim().match(/^v?(\d+)\.(\d+)\.(\d+)/)
32
+ if (!match) {
33
+ return null
34
+ }
35
+
36
+ return {
37
+ major: Number(match[1]),
38
+ minor: Number(match[2]),
39
+ patch: Number(match[3]),
40
+ raw: `${match[1]}.${match[2]}.${match[3]}`,
41
+ }
42
+ }
43
+
44
+ function isNodeSupported(version) {
45
+ return Boolean(version && version.major >= MIN_NODE_MAJOR)
46
+ }
47
+
48
+ function detectCommand(command) {
49
+ const result = run(command, ['--version'])
50
+ if (result.error || result.status !== 0) {
51
+ return {
52
+ ok: false,
53
+ command,
54
+ output: result.error ? result.error.message : `${result.stdout || ''}${result.stderr || ''}`.trim(),
55
+ }
56
+ }
57
+
58
+ return {
59
+ ok: true,
60
+ command,
61
+ output: `${result.stdout || ''}${result.stderr || ''}`.trim(),
62
+ }
63
+ }
64
+
65
+ function parsePackageMetadata(rawJson) {
66
+ if (!rawJson) {
67
+ return null
68
+ }
69
+
70
+ const parsed = JSON.parse(rawJson)
71
+ return {
72
+ version: parsed.version || '(unknown)',
73
+ license: parsed.license || '(unknown)',
74
+ engines: parsed.engines || {},
75
+ }
76
+ }
77
+
78
+ function loadPackageMetadata() {
79
+ if (process.env.GITNEXUS_PREFLIGHT_NPM_VIEW_JSON) {
80
+ return {
81
+ ok: true,
82
+ source: 'env',
83
+ metadata: parsePackageMetadata(process.env.GITNEXUS_PREFLIGHT_NPM_VIEW_JSON),
84
+ }
85
+ }
86
+
87
+ const result = run('npm', ['view', PACKAGE_NAME, 'version', 'license', 'engines', '--json'], {
88
+ timeout: NPM_METADATA_TIMEOUT_MS,
89
+ })
90
+ if (result.error || result.status !== 0) {
91
+ return {
92
+ ok: false,
93
+ source: 'npm',
94
+ warning: summarizeCommandFailure(result),
95
+ }
96
+ }
97
+
98
+ try {
99
+ return {
100
+ ok: true,
101
+ source: 'npm',
102
+ metadata: parsePackageMetadata(result.stdout),
103
+ }
104
+ } catch (error) {
105
+ return {
106
+ ok: false,
107
+ source: 'npm',
108
+ warning: `Failed to parse npm metadata: ${error.message || error}`,
109
+ }
110
+ }
111
+ }
112
+
113
+ function main() {
114
+ console.log('GitNexus preflight check')
115
+ console.log('========================')
116
+
117
+ const nodeVersion = parseNodeVersion(process.env.GITNEXUS_PREFLIGHT_NODE_VERSION || process.version)
118
+ const npm = detectCommand('npm')
119
+ const npx = detectCommand('npx')
120
+ const packageInfo = loadPackageMetadata()
121
+ const warnings = []
122
+
123
+ let hasFailure = false
124
+
125
+ if (!nodeVersion) {
126
+ hasFailure = true
127
+ console.log(`- Node: unable to detect version (requires Node >= ${MIN_NODE_MAJOR})`)
128
+ } else if (!isNodeSupported(nodeVersion)) {
129
+ hasFailure = true
130
+ console.log(`- Node: ${nodeVersion.raw} (requires Node >= ${MIN_NODE_MAJOR})`)
131
+ } else {
132
+ console.log(`- Node: ${nodeVersion.raw} (ok)`)
133
+ }
134
+
135
+ if (!npm.ok) {
136
+ hasFailure = true
137
+ console.log('- npm: missing or unavailable')
138
+ } else {
139
+ console.log(`- npm: ${npm.output || 'available'} (ok)`)
140
+ }
141
+
142
+ if (!npx.ok) {
143
+ hasFailure = true
144
+ console.log('- npx: missing or unavailable')
145
+ } else {
146
+ console.log(`- npx: ${npx.output || 'available'} (ok)`)
147
+ }
148
+
149
+ if (packageInfo.ok && packageInfo.metadata) {
150
+ const engine = packageInfo.metadata.engines.node || '(not declared)'
151
+ console.log(`- GitNexus package: ${packageInfo.metadata.version} (license ${packageInfo.metadata.license}, node ${engine})`)
152
+ } else {
153
+ warnings.push(`Could not read npm metadata for ${PACKAGE_NAME}; continue only after checking the upstream license and engine manually.`)
154
+ if (packageInfo.warning) {
155
+ warnings.push(packageInfo.warning)
156
+ }
157
+ console.log('- GitNexus package: metadata unavailable (warning)')
158
+ }
159
+
160
+ if (warnings.length) {
161
+ console.log('\nWarnings:')
162
+ for (const warning of warnings) {
163
+ console.log(`- ${warning}`)
164
+ }
165
+ }
166
+
167
+ console.log('\nControlled integration boundaries:')
168
+ console.log('- GitNexus is optional and is not installed by TSP.')
169
+ console.log('- Review the upstream license before use; current npm metadata may report PolyForm-Noncommercial-1.0.0.')
170
+ console.log('- Do not run `gitnexus setup` automatically; it writes global editor/MCP configuration.')
171
+ console.log('- Do not run `gitnexus analyze` without `--skip-agents-md` in TSP-managed repositories.')
172
+
173
+ if (hasFailure) {
174
+ console.log('\nFix the failed checks before enabling GitNexus for a project.')
175
+ process.exit(1)
176
+ }
177
+
178
+ console.log('\nRecommended next commands:')
179
+ console.log('- npx --yes gitnexus@latest analyze --skip-agents-md')
180
+ console.log('- npx --yes gitnexus@latest status')
181
+ console.log('- npx --yes gitnexus@latest list')
182
+
183
+ console.log('\nManual MCP command:')
184
+ console.log('- npx --yes gitnexus@latest mcp')
185
+ }
186
+
187
+ main()
@@ -192,6 +192,9 @@ function printHumanPlan(plan, dryRun, knownRisks = []) {
192
192
  }
193
193
  }
194
194
  console.log(`Operations: ${plan.operations.length}`);
195
+ if (Array.isArray(plan.externalInstalls) && plan.externalInstalls.length > 0) {
196
+ console.log(`External installs: ${plan.externalInstalls.length}`);
197
+ }
195
198
 
196
199
  if (plan.warnings.length > 0) {
197
200
  console.log('\nWarnings:');
@@ -210,6 +213,12 @@ function printHumanPlan(plan, dryRun, knownRisks = []) {
210
213
  for (const operation of plan.operations) {
211
214
  console.log(`- ${operation.sourceRelativePath} -> ${operation.destinationPath}`);
212
215
  }
216
+ if (Array.isArray(plan.externalInstalls) && plan.externalInstalls.length > 0) {
217
+ console.log('\nPlanned external installs:');
218
+ for (const externalInstall of plan.externalInstalls) {
219
+ console.log(`- ${externalInstall.id}: ${externalInstall.description || externalInstall.script}`);
220
+ }
221
+ }
213
222
 
214
223
  if (!dryRun) {
215
224
  console.log(`\nDone. Install-state written to ${plan.installStatePath}`);
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+ const { spawnSync } = require('child_process');
7
+
8
+ const DEFAULT_REPO_URL = 'https://github.com/nexu-io/open-design.git';
9
+ const DEFAULT_INSTALL_DIR = path.join(os.homedir(), '.tsp', 'open-design');
10
+ const DEFAULT_REF = 'main';
11
+
12
+ function parseArgs(argv) {
13
+ const parsed = {
14
+ installDir: process.env.TSP_OPEN_DESIGN_HOME || process.env.OPEN_DESIGN_HOME || DEFAULT_INSTALL_DIR,
15
+ repoUrl: process.env.TSP_OPEN_DESIGN_REPO || DEFAULT_REPO_URL,
16
+ ref: process.env.TSP_OPEN_DESIGN_REF || DEFAULT_REF,
17
+ skipDeps: process.env.TSP_OPEN_DESIGN_SKIP_DEPS === '1',
18
+ dryRun: false,
19
+ };
20
+
21
+ for (let index = 2; index < argv.length; index += 1) {
22
+ const arg = argv[index];
23
+ if (arg === '--dir') {
24
+ parsed.installDir = argv[index + 1] || parsed.installDir;
25
+ index += 1;
26
+ continue;
27
+ }
28
+ if (arg === '--repo') {
29
+ parsed.repoUrl = argv[index + 1] || parsed.repoUrl;
30
+ index += 1;
31
+ continue;
32
+ }
33
+ if (arg === '--ref') {
34
+ parsed.ref = argv[index + 1] || parsed.ref;
35
+ index += 1;
36
+ continue;
37
+ }
38
+ if (arg === '--skip-deps') {
39
+ parsed.skipDeps = true;
40
+ continue;
41
+ }
42
+ if (arg === '--dry-run') {
43
+ parsed.dryRun = true;
44
+ continue;
45
+ }
46
+ if (arg === '--help' || arg === '-h') {
47
+ parsed.help = true;
48
+ continue;
49
+ }
50
+ throw new Error(`Unknown argument: ${arg}`);
51
+ }
52
+
53
+ parsed.installDir = path.resolve(parsed.installDir);
54
+ return parsed;
55
+ }
56
+
57
+ function printHelp() {
58
+ console.log(`
59
+ Install or update Open Design for TSP.
60
+
61
+ Usage:
62
+ node scripts/install-open-design.js [--dir <path>] [--repo <url>] [--ref <git-ref>] [--skip-deps] [--dry-run]
63
+
64
+ Environment:
65
+ TSP_OPEN_DESIGN_HOME Override install directory. Default: ~/.tsp/open-design
66
+ TSP_OPEN_DESIGN_REPO Override upstream repository URL.
67
+ TSP_OPEN_DESIGN_REF Override git ref. Default: main
68
+ TSP_OPEN_DESIGN_SKIP_DEPS Set to 1 to skip pnpm dependency install.
69
+ `);
70
+ }
71
+
72
+ function commandExists(command) {
73
+ const result = spawnSync(command, ['--version'], {
74
+ encoding: 'utf8',
75
+ stdio: ['ignore', 'ignore', 'ignore'],
76
+ });
77
+ return result.status === 0;
78
+ }
79
+
80
+ function run(command, args, options = {}) {
81
+ const printable = [command, ...args].join(' ');
82
+ if (options.dryRun) {
83
+ console.log(`[dry-run] ${printable}`);
84
+ return;
85
+ }
86
+
87
+ const result = spawnSync(command, args, {
88
+ cwd: options.cwd || process.cwd(),
89
+ encoding: 'utf8',
90
+ stdio: options.quiet ? ['ignore', 'pipe', 'pipe'] : 'inherit',
91
+ });
92
+
93
+ if (result.status !== 0) {
94
+ const stderr = result.stderr ? `\n${result.stderr.trim()}` : '';
95
+ throw new Error(`Command failed: ${printable}${stderr}`);
96
+ }
97
+ }
98
+
99
+ function readGitRemote(installDir) {
100
+ const result = spawnSync('git', ['-C', installDir, 'remote', 'get-url', 'origin'], {
101
+ encoding: 'utf8',
102
+ stdio: ['ignore', 'pipe', 'ignore'],
103
+ });
104
+ return result.status === 0 ? result.stdout.trim() : null;
105
+ }
106
+
107
+ function isOpenDesignRemote(remoteUrl, expectedRepoUrl) {
108
+ const normalized = String(remoteUrl || '').replace(/\.git$/, '');
109
+ const expected = String(expectedRepoUrl || '').replace(/\.git$/, '');
110
+ return normalized === expected || normalized.endsWith('/nexu-io/open-design');
111
+ }
112
+
113
+ function ensureOpenDesignCheckout(options) {
114
+ const gitDir = path.join(options.installDir, '.git');
115
+ if (!fs.existsSync(options.installDir)) {
116
+ console.log(`Installing Open Design into ${options.installDir}`);
117
+ if (!options.dryRun) {
118
+ fs.mkdirSync(path.dirname(options.installDir), { recursive: true });
119
+ }
120
+ run('git', [
121
+ 'clone',
122
+ '--depth',
123
+ '1',
124
+ '--branch',
125
+ options.ref,
126
+ options.repoUrl,
127
+ options.installDir,
128
+ ], { dryRun: options.dryRun });
129
+ return;
130
+ }
131
+
132
+ if (!fs.existsSync(gitDir)) {
133
+ throw new Error(`Open Design install path exists but is not a git checkout: ${options.installDir}`);
134
+ }
135
+
136
+ const remoteUrl = readGitRemote(options.installDir);
137
+ if (!isOpenDesignRemote(remoteUrl, options.repoUrl)) {
138
+ throw new Error(
139
+ `Refusing to update ${options.installDir}; origin is ${remoteUrl || '(unknown)'}, expected ${options.repoUrl}`
140
+ );
141
+ }
142
+
143
+ console.log(`Updating Open Design at ${options.installDir}`);
144
+ run('git', ['-C', options.installDir, 'fetch', '--depth', '1', 'origin', options.ref], {
145
+ dryRun: options.dryRun,
146
+ });
147
+ run('git', ['-C', options.installDir, 'checkout', 'FETCH_HEAD'], {
148
+ dryRun: options.dryRun,
149
+ });
150
+ }
151
+
152
+ function installDependencies(options) {
153
+ if (options.skipDeps) {
154
+ console.log('Skipping Open Design dependency install because --skip-deps or TSP_OPEN_DESIGN_SKIP_DEPS=1 is set.');
155
+ return;
156
+ }
157
+
158
+ if (!commandExists('corepack')) {
159
+ console.warn(
160
+ 'Open Design source is installed, but corepack/pnpm is not available. '
161
+ + 'Install Node 24 with corepack, then run `corepack enable && pnpm install` in the Open Design directory.'
162
+ );
163
+ return;
164
+ }
165
+
166
+ run('corepack', ['enable'], {
167
+ cwd: options.installDir,
168
+ dryRun: options.dryRun,
169
+ });
170
+
171
+ if (!commandExists('pnpm')) {
172
+ console.warn(
173
+ 'Open Design source is installed, but pnpm is still not available after `corepack enable`. '
174
+ + 'Run `corepack prepare pnpm@10.33.2 --activate && pnpm install` in the Open Design directory.'
175
+ );
176
+ return;
177
+ }
178
+
179
+ run('pnpm', ['install'], {
180
+ cwd: options.installDir,
181
+ dryRun: options.dryRun,
182
+ });
183
+ }
184
+
185
+ function main() {
186
+ try {
187
+ const options = parseArgs(process.argv);
188
+ if (options.help) {
189
+ printHelp();
190
+ return;
191
+ }
192
+
193
+ if (!commandExists('git')) {
194
+ throw new Error('git is required to install Open Design');
195
+ }
196
+
197
+ ensureOpenDesignCheckout(options);
198
+ installDependencies(options);
199
+ console.log(`Open Design ready: ${options.installDir}`);
200
+ } catch (error) {
201
+ console.error(`Error: ${error.message}`);
202
+ process.exit(1);
203
+ }
204
+ }
205
+
206
+ main();
@@ -183,6 +183,23 @@ function printPlan(plan) {
183
183
  );
184
184
  }
185
185
  }
186
+
187
+ const externalInstalls = plan.selectedModules
188
+ .map(module => ({ module, externalInstall: module.externalInstall }))
189
+ .filter(({ externalInstall }) => externalInstall && typeof externalInstall === 'object' && !Array.isArray(externalInstall))
190
+ .filter(({ externalInstall }) => {
191
+ const profiles = Array.isArray(externalInstall.profiles)
192
+ ? externalInstall.profiles.map(value => String(value).trim()).filter(Boolean)
193
+ : [];
194
+ return profiles.length === 0 || profiles.includes(plan.profileId);
195
+ });
196
+ if (externalInstalls.length > 0) {
197
+ console.log('');
198
+ console.log(`External install plan (${externalInstalls.length}):`);
199
+ for (const { module, externalInstall } of externalInstalls) {
200
+ console.log(`- ${externalInstall.id || module.id}: ${externalInstall.description || externalInstall.script}`);
201
+ }
202
+ }
186
203
  }
187
204
 
188
205
  function main() {
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const { spawnSync } = require('child_process');
5
6
 
6
7
  const { writeInstallState } = require('../install-state');
7
8
  const { writeInstallAuditManifest } = require('../install-audit-manifest');
@@ -176,6 +177,32 @@ function buildMergedSettings(plan) {
176
177
  };
177
178
  }
178
179
 
180
+ function runExternalInstall(externalInstall) {
181
+ const args = [];
182
+ if (externalInstall.scriptPath) {
183
+ args.push(externalInstall.scriptPath);
184
+ } else if (externalInstall.script) {
185
+ args.push(externalInstall.script);
186
+ }
187
+ if (Array.isArray(externalInstall.args)) {
188
+ args.push(...externalInstall.args);
189
+ }
190
+
191
+ const command = externalInstall.command || 'node';
192
+ const label = externalInstall.id || externalInstall.moduleId || command;
193
+ console.log(`Running external install: ${label}`);
194
+
195
+ const result = spawnSync(command, args, {
196
+ cwd: externalInstall.cwd || process.cwd(),
197
+ encoding: 'utf8',
198
+ stdio: 'inherit',
199
+ });
200
+
201
+ if (result.status !== 0) {
202
+ throw new Error(`External install failed: ${label}`);
203
+ }
204
+ }
205
+
179
206
  function applyInstallPlan(plan) {
180
207
  const mergedSettingsPlan = buildMergedSettings(plan);
181
208
 
@@ -199,6 +226,10 @@ function applyInstallPlan(plan) {
199
226
  );
200
227
  }
201
228
 
229
+ for (const externalInstall of Array.isArray(plan.externalInstalls) ? plan.externalInstalls : []) {
230
+ runExternalInstall(externalInstall);
231
+ }
232
+
202
233
  writeInstallState(plan.installStatePath, plan.statePreview);
203
234
  const { installManifestPath } = writeInstallAuditManifest(plan);
204
235
 
@@ -133,6 +133,56 @@ function createStatePreview(options) {
133
133
  return createInstallState(options);
134
134
  }
135
135
 
136
+ function resolveExternalInstalls(selectedModules, options = {}) {
137
+ const profileId = options.profileId || null;
138
+ const sourceRoot = options.sourceRoot || getSourceRoot();
139
+ const target = options.target || null;
140
+ const installs = [];
141
+
142
+ for (const module of selectedModules) {
143
+ const externalInstall = module && module.externalInstall;
144
+ if (!externalInstall || typeof externalInstall !== 'object' || Array.isArray(externalInstall)) {
145
+ continue;
146
+ }
147
+
148
+ const profileFilter = Array.isArray(externalInstall.profiles)
149
+ ? externalInstall.profiles.map(value => String(value).trim()).filter(Boolean)
150
+ : [];
151
+ if (profileFilter.length > 0 && (!profileId || !profileFilter.includes(profileId))) {
152
+ continue;
153
+ }
154
+
155
+ const command = typeof externalInstall.command === 'string' && externalInstall.command.trim()
156
+ ? externalInstall.command.trim()
157
+ : 'node';
158
+ const script = typeof externalInstall.script === 'string' && externalInstall.script.trim()
159
+ ? externalInstall.script.trim()
160
+ : null;
161
+ const args = Array.isArray(externalInstall.args)
162
+ ? externalInstall.args.map(value => String(value))
163
+ : [];
164
+
165
+ if (!script) {
166
+ throw new Error(`Install module ${module.id} has externalInstall but no script`);
167
+ }
168
+
169
+ installs.push({
170
+ id: externalInstall.id || module.id,
171
+ moduleId: module.id,
172
+ description: externalInstall.description || '',
173
+ command,
174
+ script,
175
+ scriptPath: path.join(sourceRoot, script),
176
+ args,
177
+ cwd: sourceRoot,
178
+ target,
179
+ profileId,
180
+ });
181
+ }
182
+
183
+ return installs;
184
+ }
185
+
136
186
  function applyInstallPlan(plan) {
137
187
  const { applyInstallPlan: applyPlan } = require('./install/apply');
138
188
  return applyPlan(plan);
@@ -617,6 +667,11 @@ function createManifestInstallPlan(options = {}) {
617
667
  });
618
668
  const adapter = getInstallTargetAdapter(target);
619
669
  const operations = plan.operations.flatMap(operation => materializeScaffoldOperation(sourceRoot, operation));
670
+ const externalInstalls = resolveExternalInstalls(plan.selectedModules, {
671
+ profileId: plan.profileId,
672
+ sourceRoot,
673
+ target,
674
+ });
620
675
  const source = {
621
676
  repoVersion: getPackageVersion(sourceRoot),
622
677
  repoCommit: getRepoCommit(sourceRoot),
@@ -667,6 +722,7 @@ function createManifestInstallPlan(options = {}) {
667
722
  skippedModuleIds: plan.skippedModuleIds,
668
723
  excludedModuleIds: plan.excludedModuleIds,
669
724
  operations,
725
+ externalInstalls,
670
726
  statePreview,
671
727
  };
672
728
  }
@@ -66,10 +66,10 @@
66
66
  "默认以 `karpathy-guidelines` 的方式先暴露歧义、范围边界与更简单路径,不在入口阶段静默替用户补全高风险假设。",
67
67
  "检查现有证据是否齐备:PRD、delivery-plan、arch-design、handoff、execute-log、test-plan、launch-acceptance、deployment-context、release-plan、closeout-summary,以及 `docs/memory/project-context.md`。",
68
68
  "若任务边界清晰、影响面小、风险低,优先推荐 `/quick`;否则继续沿 `/team-*` 主链推进。",
69
- "若是既有项目(brownfield)且现状上下文不足,优先建议执行 `/update-codemaps` 并启用 `doc-architecture`,把现有模块、集成点、关键数据流和历史包袱回落到 `delivery-plan.md` / `arch-design.md`。",
69
+ "若是既有项目(brownfield)且现状上下文不足,优先建议执行 `/update-codemaps` 并启用 `doc-architecture`,需要轻量结构证据时选择 Graphify,需要跨模块影响面或 MCP 证据时选择 GitNexus,再把现有模块、集成点、关键数据流和历史包袱回落到 `delivery-plan.md` / `arch-design.md`。",
70
70
  "若需求规模较大或涉及多角色并行,实现前先要求把计划切成可独立验收、可独立 handoff 的 story-sized execution units,并确认 `artifact:persist` 已创建对应任务目录与关键 artifact,再进入 `/team-execute`。",
71
71
  "若缺少 PRD 或需求边界,推荐 `/team-intake`;若缺少 challenge、design review 或 implementation-readiness,推荐 `/team-plan`;若 readiness proof 与 handoff 齐备,推荐 `/team-execute`;若已完成实现与自测,推荐 `/team-review`;若已获得放行,推荐 `/team-release`;若发布观察窗口结束,推荐 `/team-closeout`。",
72
- "若是既有项目且上下文不足,提示先补齐 brownfield / doc-architecture 类上下文,再进入计划或执行。",
72
+ "若是既有项目且上下文不足,提示先补齐 brownfield / doc-architecture 类上下文;必要时用 Graphify 或 GitNexus 补图谱证据,再进入计划或执行。",
73
73
  "输出结构化建议:推荐命令、原因、阻塞项、降级路径,并说明是否需要先运行 `npm run workflow:readiness`。"
74
74
  ]
75
75
  },
@@ -136,7 +136,7 @@
136
136
  "默认把 `karpathy-guidelines` 作为计划收口护栏:要求显式写出假设、更简单备选路径、当前不做项,以及为什么本轮范围已经足够。",
137
137
  "按任务特征装配动态讨论分组,先讨论再收敛,避免未经质疑直接进入计划冻结。",
138
138
  "若启用 `doc-architecture`,补齐 Service Catalog、Communication Matrix、NFR Summary,并明确其 artifact 回落位置。",
139
- "若是既有项目(brownfield),先梳理现有模块边界、外部依赖、历史约束和缺失文档;必要时运行 `/update-codemaps`,再把 brownfield snapshot 回落到 `delivery-plan.md` 与 `arch-design.md`。",
139
+ "若是既有项目(brownfield),先梳理现有模块边界、外部依赖、历史约束和缺失文档;必要时运行 `/update-codemaps`,需要轻量结构证据时选择 Graphify,需要跨模块影响面或 MCP 证据时选择 GitNexus,再把 brownfield snapshot 回落到 `delivery-plan.md` 与 `arch-design.md`。",
140
140
  "若为企业内部应用,锁定应用等级、技术架构等级、关键组件偏离和资产入口要求,并判断是否必须输出 ADR。",
141
141
  "为本次任务显式装配 shared 能力、ECC 增强与可选 enterprise overlay 组合,并说明哪些私有 overlay 能力、runbook 或 overlay 仅按场景启用。",
142
142
  "若存在多参数、多角色、多配置或多终端组合,提前判断是否需要 `pairwise-test-design` 压缩测试矩阵。",
@@ -468,7 +468,7 @@
468
468
  },
469
469
  {
470
470
  "name": "update-codemaps",
471
- "summary": "扫描代码结构并生成 token-lean codemaps,适合作为 brownfield 项目的现状快照与主链前置上下文。",
471
+ "summary": "扫描代码结构并生成 token-lean codemaps,适合作为 brownfield 项目的现状快照与 Graphify / GitNexus 图谱分析前置上下文。",
472
472
  "primary_role": "doc-updater",
473
473
  "inputs": [
474
474
  "代码仓结构",
@@ -478,13 +478,14 @@
478
478
  "outputs": [
479
479
  "docs/CODEMAPS/ 下的结构化 codemap",
480
480
  ".reports/codemap-diff.txt 差异摘要",
481
- "可供 `/team-help` / `/team-plan` 消费的 brownfield context"
481
+ "可供 `/team-help` / `/team-plan` 消费的 brownfield context",
482
+ "可供 Graphify / GitNexus 继续深挖的结构化问题清单"
482
483
  ],
483
484
  "steps": [
484
485
  "先识别仓库类型、源码目录、入口文件和主要依赖边界。",
485
486
  "为 architecture/backend/frontend/data/dependencies 生成 token-lean 文档,不写实现细节噪音。",
486
487
  "若已有 codemap,先比较变更比例;超过阈值时要求人工确认再覆盖。",
487
- "把结果作为 brownfield context snapshot 的辅助输入,回落到 `delivery-plan.md` / `arch-design.md`,不要形成平行事实源。"
488
+ "把结果作为 brownfield context snapshot 的辅助输入;若需要图谱证据,再选择 Graphify 或 GitNexus,并把结论回落到 `delivery-plan.md` / `arch-design.md`,不要形成平行事实源。"
488
489
  ]
489
490
  },
490
491
  {