@bradygaster/squad-sdk 0.9.1 → 0.9.2-insider.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +340 -296
- package/dist/agents/history-shadow.d.ts +7 -5
- package/dist/agents/history-shadow.d.ts.map +1 -1
- package/dist/agents/history-shadow.js +69 -78
- package/dist/agents/history-shadow.js.map +1 -1
- package/dist/agents/index.d.ts +12 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +62 -9
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lifecycle.d.ts +4 -0
- package/dist/agents/lifecycle.d.ts.map +1 -1
- package/dist/agents/lifecycle.js +6 -7
- package/dist/agents/lifecycle.js.map +1 -1
- package/dist/agents/onboarding.d.ts +4 -2
- package/dist/agents/onboarding.d.ts.map +1 -1
- package/dist/agents/onboarding.js +26 -16
- package/dist/agents/onboarding.js.map +1 -1
- package/dist/agents/personal.d.ts +2 -1
- package/dist/agents/personal.d.ts.map +1 -1
- package/dist/agents/personal.js +11 -12
- package/dist/agents/personal.js.map +1 -1
- package/dist/build/bundle.d.ts.map +1 -1
- package/dist/build/bundle.js +6 -6
- package/dist/build/bundle.js.map +1 -1
- package/dist/build/github-dist.js +42 -42
- package/dist/build/release.d.ts.map +1 -1
- package/dist/build/release.js +7 -5
- package/dist/build/release.js.map +1 -1
- package/dist/casting/index.d.ts.map +1 -1
- package/dist/casting/index.js +4 -3
- package/dist/casting/index.js.map +1 -1
- package/dist/config/agent-source.d.ts +5 -1
- package/dist/config/agent-source.d.ts.map +1 -1
- package/dist/config/agent-source.js +85 -41
- package/dist/config/agent-source.js.map +1 -1
- package/dist/config/init.d.ts +4 -3
- package/dist/config/init.d.ts.map +1 -1
- package/dist/config/init.js +257 -236
- package/dist/config/init.js.map +1 -1
- package/dist/config/legacy-fallback.d.ts +3 -2
- package/dist/config/legacy-fallback.d.ts.map +1 -1
- package/dist/config/legacy-fallback.js +16 -14
- package/dist/config/legacy-fallback.js.map +1 -1
- package/dist/config/models.d.ts +9 -6
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +35 -25
- package/dist/config/models.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/marketplace/packaging.d.ts.map +1 -1
- package/dist/marketplace/packaging.js +18 -16
- package/dist/marketplace/packaging.js.map +1 -1
- package/dist/multi-squad.d.ts.map +1 -1
- package/dist/multi-squad.js +10 -9
- package/dist/multi-squad.js.map +1 -1
- package/dist/platform/comms-file-log.d.ts.map +1 -1
- package/dist/platform/comms-file-log.js +7 -6
- package/dist/platform/comms-file-log.js.map +1 -1
- package/dist/platform/comms.d.ts.map +1 -1
- package/dist/platform/comms.js +6 -5
- package/dist/platform/comms.js.map +1 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +4 -3
- package/dist/platform/index.js.map +1 -1
- package/dist/ralph/capabilities.d.ts +30 -1
- package/dist/ralph/capabilities.d.ts.map +1 -1
- package/dist/ralph/capabilities.js +51 -6
- package/dist/ralph/capabilities.js.map +1 -1
- package/dist/ralph/index.d.ts +1 -1
- package/dist/ralph/index.d.ts.map +1 -1
- package/dist/ralph/index.js +4 -3
- package/dist/ralph/index.js.map +1 -1
- package/dist/ralph/rate-limiting.d.ts.map +1 -1
- package/dist/ralph/rate-limiting.js +4 -4
- package/dist/ralph/rate-limiting.js.map +1 -1
- package/dist/remote/bridge.d.ts.map +1 -1
- package/dist/remote/bridge.js +2 -2
- package/dist/remote/bridge.js.map +1 -1
- package/dist/resolution.d.ts +9 -0
- package/dist/resolution.d.ts.map +1 -1
- package/dist/resolution.js +39 -16
- package/dist/resolution.js.map +1 -1
- package/dist/roles/catalog.d.ts +1 -1
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +8 -7
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/cross-squad.d.ts.map +1 -1
- package/dist/runtime/cross-squad.js +8 -7
- package/dist/runtime/cross-squad.js.map +1 -1
- package/dist/runtime/scheduler.d.ts.map +1 -1
- package/dist/runtime/scheduler.js +8 -8
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/squad-observer.d.ts.map +1 -1
- package/dist/runtime/squad-observer.js +7 -4
- package/dist/runtime/squad-observer.js.map +1 -1
- package/dist/sharing/consult.d.ts +1 -1
- package/dist/sharing/consult.d.ts.map +1 -1
- package/dist/sharing/consult.js +144 -142
- package/dist/sharing/consult.js.map +1 -1
- package/dist/sharing/export.d.ts.map +1 -1
- package/dist/sharing/export.js +16 -16
- package/dist/sharing/export.js.map +1 -1
- package/dist/sharing/import.d.ts.map +1 -1
- package/dist/sharing/import.js +13 -12
- package/dist/sharing/import.js.map +1 -1
- package/dist/skills/skill-loader.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +10 -9
- package/dist/skills/skill-loader.js.map +1 -1
- package/dist/skills/skill-script-loader.d.ts.map +1 -1
- package/dist/skills/skill-script-loader.js +6 -4
- package/dist/skills/skill-script-loader.js.map +1 -1
- package/dist/skills/skill-source.d.ts +3 -1
- package/dist/skills/skill-source.d.ts.map +1 -1
- package/dist/skills/skill-source.js +18 -16
- package/dist/skills/skill-source.js.map +1 -1
- package/dist/state/collection-map.d.ts +43 -0
- package/dist/state/collection-map.d.ts.map +1 -0
- package/dist/state/collection-map.js +9 -0
- package/dist/state/collection-map.js.map +1 -0
- package/dist/state/collections.d.ts +102 -0
- package/dist/state/collections.d.ts.map +1 -0
- package/dist/state/collections.js +317 -0
- package/dist/state/collections.js.map +1 -0
- package/dist/state/domain-types.d.ts +122 -0
- package/dist/state/domain-types.d.ts.map +1 -0
- package/dist/state/domain-types.js +54 -0
- package/dist/state/domain-types.js.map +1 -0
- package/dist/state/handles.d.ts +16 -0
- package/dist/state/handles.d.ts.map +1 -0
- package/dist/state/handles.js +161 -0
- package/dist/state/handles.js.map +1 -0
- package/dist/state/index.d.ts +17 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +15 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/io/charter-io.d.ts +28 -0
- package/dist/state/io/charter-io.d.ts.map +1 -0
- package/dist/state/io/charter-io.js +94 -0
- package/dist/state/io/charter-io.js.map +1 -0
- package/dist/state/io/decisions-io.d.ts +42 -0
- package/dist/state/io/decisions-io.d.ts.map +1 -0
- package/dist/state/io/decisions-io.js +66 -0
- package/dist/state/io/decisions-io.js.map +1 -0
- package/dist/state/io/history-io.d.ts +37 -0
- package/dist/state/io/history-io.d.ts.map +1 -0
- package/dist/state/io/history-io.js +102 -0
- package/dist/state/io/history-io.js.map +1 -0
- package/dist/state/io/index.d.ts +19 -0
- package/dist/state/io/index.d.ts.map +1 -0
- package/dist/state/io/index.js +19 -0
- package/dist/state/io/index.js.map +1 -0
- package/dist/state/io/routing-io.d.ts +37 -0
- package/dist/state/io/routing-io.d.ts.map +1 -0
- package/dist/state/io/routing-io.js +99 -0
- package/dist/state/io/routing-io.js.map +1 -0
- package/dist/state/io/team-io.d.ts +46 -0
- package/dist/state/io/team-io.d.ts.map +1 -0
- package/dist/state/io/team-io.js +82 -0
- package/dist/state/io/team-io.js.map +1 -0
- package/dist/state/schema.d.ts +24 -0
- package/dist/state/schema.d.ts.map +1 -0
- package/dist/state/schema.js +41 -0
- package/dist/state/schema.js.map +1 -0
- package/dist/state/squad-state.d.ts +42 -0
- package/dist/state/squad-state.d.ts.map +1 -0
- package/dist/state/squad-state.js +68 -0
- package/dist/state/squad-state.js.map +1 -0
- package/dist/storage/fs-storage-provider.d.ts +60 -0
- package/dist/storage/fs-storage-provider.d.ts.map +1 -0
- package/dist/storage/fs-storage-provider.js +377 -0
- package/dist/storage/fs-storage-provider.js.map +1 -0
- package/dist/storage/in-memory-storage-provider.d.ts +46 -0
- package/dist/storage/in-memory-storage-provider.d.ts.map +1 -0
- package/dist/storage/in-memory-storage-provider.js +264 -0
- package/dist/storage/in-memory-storage-provider.js.map +1 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/sqlite-storage-provider.d.ts +95 -0
- package/dist/storage/sqlite-storage-provider.d.ts.map +1 -0
- package/dist/storage/sqlite-storage-provider.js +383 -0
- package/dist/storage/sqlite-storage-provider.js.map +1 -0
- package/dist/storage/storage-error.d.ts +28 -0
- package/dist/storage/storage-error.d.ts.map +1 -0
- package/dist/storage/storage-error.js +35 -0
- package/dist/storage/storage-error.js.map +1 -0
- package/dist/storage/storage-provider.d.ts +161 -0
- package/dist/storage/storage-provider.d.ts.map +1 -0
- package/dist/storage/storage-provider.js +18 -0
- package/dist/storage/storage-provider.js.map +1 -0
- package/dist/streams/resolver.d.ts.map +1 -1
- package/dist/streams/resolver.js +6 -5
- package/dist/streams/resolver.js.map +1 -1
- package/dist/tools/index.d.ts +5 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +54 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/upstream/resolver.d.ts +3 -2
- package/dist/upstream/resolver.d.ts.map +1 -1
- package/dist/upstream/resolver.js +33 -32
- package/dist/upstream/resolver.js.map +1 -1
- package/package.json +33 -1
- package/templates/casting/Futurama.json +9 -9
- package/templates/casting-history.json +4 -4
- package/templates/casting-policy.json +37 -37
- package/templates/casting-reference.md +104 -104
- package/templates/casting-registry.json +3 -3
- package/templates/ceremonies.md +41 -41
- package/templates/charter.md +53 -53
- package/templates/constraint-tracking.md +38 -38
- package/templates/cooperative-rate-limiting.md +229 -229
- package/templates/copilot-instructions.md +46 -46
- package/templates/history.md +10 -10
- package/templates/identity/now.md +9 -9
- package/templates/identity/wisdom.md +15 -15
- package/templates/issue-lifecycle.md +412 -412
- package/templates/keda-scaler.md +164 -164
- package/templates/machine-capabilities.md +74 -74
- package/templates/mcp-config.md +90 -90
- package/templates/multi-agent-format.md +28 -28
- package/templates/plugin-marketplace.md +49 -49
- package/templates/ralph-circuit-breaker.md +313 -313
- package/templates/raw-agent-output.md +37 -37
- package/templates/roster.md +60 -60
- package/templates/routing.md +39 -39
- package/templates/run-output.md +50 -50
- package/templates/schedule.json +19 -19
- package/templates/scribe-charter.md +123 -119
- package/templates/skill.md +24 -24
- package/templates/skills/agent-collaboration/SKILL.md +42 -42
- package/templates/skills/agent-conduct/SKILL.md +24 -24
- package/templates/skills/architectural-proposals/SKILL.md +151 -151
- package/templates/skills/ci-validation-gates/SKILL.md +84 -84
- package/templates/skills/cli-wiring/SKILL.md +47 -47
- package/templates/skills/client-compatibility/SKILL.md +89 -89
- package/templates/skills/cross-machine-coordination/SKILL.md +434 -0
- package/templates/skills/cross-squad/SKILL.md +114 -114
- package/templates/skills/distributed-mesh/SKILL.md +287 -287
- package/templates/skills/distributed-mesh/mesh.json.example +30 -30
- package/templates/skills/distributed-mesh/sync-mesh.ps1 +111 -111
- package/templates/skills/distributed-mesh/sync-mesh.sh +104 -104
- package/templates/skills/docs-standards/SKILL.md +71 -71
- package/templates/skills/economy-mode/SKILL.md +114 -114
- package/templates/skills/error-recovery/SKILL.md +99 -0
- package/templates/skills/external-comms/SKILL.md +329 -329
- package/templates/skills/gh-auth-isolation/SKILL.md +183 -183
- package/templates/skills/git-workflow/SKILL.md +204 -204
- package/templates/skills/github-multi-account/SKILL.md +95 -95
- package/templates/skills/history-hygiene/SKILL.md +36 -36
- package/templates/skills/humanizer/SKILL.md +105 -105
- package/templates/skills/init-mode/SKILL.md +102 -102
- package/templates/skills/iterative-retrieval/SKILL.md +165 -0
- package/templates/skills/model-selection/SKILL.md +117 -117
- package/templates/skills/nap/SKILL.md +24 -24
- package/templates/skills/notification-routing/SKILL.md +105 -0
- package/templates/skills/personal-squad/SKILL.md +57 -57
- package/templates/skills/pr-screenshots/SKILL.md +149 -0
- package/templates/skills/project-conventions/SKILL.md +56 -56
- package/templates/skills/ralph-two-pass-scan/SKILL.md +35 -0
- package/templates/skills/reflect/SKILL.md +229 -0
- package/templates/skills/release-process/SKILL.md +131 -423
- package/templates/skills/reskill/SKILL.md +92 -92
- package/templates/skills/retro-enforcement/SKILL.md +148 -0
- package/templates/skills/reviewer-protocol/SKILL.md +79 -79
- package/templates/skills/secret-handling/SKILL.md +200 -200
- package/templates/skills/session-recovery/SKILL.md +155 -155
- package/templates/skills/squad-conventions/SKILL.md +69 -69
- package/templates/skills/test-discipline/SKILL.md +37 -37
- package/templates/skills/tiered-memory/SKILL.md +234 -0
- package/templates/skills/windows-compatibility/SKILL.md +98 -74
- package/templates/{squad.agent.md → squad.agent.md.template} +57 -28
- package/templates/workflows/squad-ci.yml +24 -24
- package/templates/workflows/squad-docs.yml +54 -54
- package/templates/workflows/squad-heartbeat.yml +167 -171
- package/templates/workflows/squad-insider-release.yml +61 -61
- package/templates/workflows/squad-issue-assign.yml +161 -161
- package/templates/workflows/squad-label-enforce.yml +181 -181
- package/templates/workflows/squad-preview.yml +55 -55
- package/templates/workflows/squad-promote.yml +120 -120
- package/templates/workflows/squad-release.yml +77 -77
- package/templates/workflows/squad-triage.yml +260 -260
- package/templates/workflows/sync-squad-labels.yml +169 -169
package/dist/config/init.js
CHANGED
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module config/init
|
|
9
9
|
*/
|
|
10
|
-
import { mkdir, writeFile, appendFile, unlink } from 'fs/promises';
|
|
11
10
|
import { join, dirname } from 'path';
|
|
12
11
|
import { fileURLToPath } from 'url';
|
|
13
|
-
import {
|
|
12
|
+
import { FSStorageProvider } from '../storage/index.js';
|
|
14
13
|
import { execFileSync } from 'node:child_process';
|
|
15
14
|
import { MODELS } from '../runtime/constants.js';
|
|
16
15
|
import { getRoleById } from '../roles/index.js';
|
|
@@ -20,17 +19,17 @@ import { getRoleById } from '../roles/index.js';
|
|
|
20
19
|
/**
|
|
21
20
|
* Get the SDK templates directory path.
|
|
22
21
|
*/
|
|
23
|
-
export function getSDKTemplatesDir() {
|
|
22
|
+
export function getSDKTemplatesDir(storage = new FSStorageProvider()) {
|
|
24
23
|
// Use fileURLToPath for cross-platform compatibility (handles Windows drive letters, URL encoding)
|
|
25
24
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
26
25
|
// Try relative to this file (in dist/)
|
|
27
26
|
const distPath = join(currentDir, '../../templates');
|
|
28
|
-
if (existsSync(distPath)) {
|
|
27
|
+
if (storage.existsSync(distPath)) {
|
|
29
28
|
return distPath;
|
|
30
29
|
}
|
|
31
30
|
// Try relative to package root (for dev)
|
|
32
31
|
const pkgPath = join(currentDir, '../../../templates');
|
|
33
|
-
if (existsSync(pkgPath)) {
|
|
32
|
+
if (storage.existsSync(pkgPath)) {
|
|
34
33
|
return pkgPath;
|
|
35
34
|
}
|
|
36
35
|
return null;
|
|
@@ -38,18 +37,18 @@ export function getSDKTemplatesDir() {
|
|
|
38
37
|
/**
|
|
39
38
|
* Copy a directory recursively.
|
|
40
39
|
*/
|
|
41
|
-
function copyRecursiveSync(src, dest) {
|
|
42
|
-
if (!existsSync(dest)) {
|
|
43
|
-
mkdirSync(dest, { recursive: true });
|
|
40
|
+
function copyRecursiveSync(src, dest, storage = new FSStorageProvider()) {
|
|
41
|
+
if (!storage.existsSync(dest)) {
|
|
42
|
+
storage.mkdirSync(dest, { recursive: true });
|
|
44
43
|
}
|
|
45
|
-
for (const entry of
|
|
44
|
+
for (const entry of storage.isDirectorySync(src) ? storage.listSync(src) : []) {
|
|
46
45
|
const srcPath = join(src, entry);
|
|
47
46
|
const destPath = join(dest, entry);
|
|
48
|
-
if (
|
|
49
|
-
copyRecursiveSync(srcPath, destPath);
|
|
47
|
+
if (storage.isDirectorySync(srcPath)) {
|
|
48
|
+
copyRecursiveSync(srcPath, destPath, storage);
|
|
50
49
|
}
|
|
51
50
|
else {
|
|
52
|
-
|
|
51
|
+
storage.copySync(srcPath, destPath);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
}
|
|
@@ -95,82 +94,82 @@ function formatModelArray(chain) {
|
|
|
95
94
|
*/
|
|
96
95
|
function generateTypeScriptConfig(options) {
|
|
97
96
|
const { projectName, projectDescription, agents } = options;
|
|
98
|
-
return `import type { SquadConfig } from '@bradygaster/squad';
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Squad Configuration for ${projectName}
|
|
102
|
-
* ${projectDescription ? `\n * ${projectDescription}` : ''}
|
|
103
|
-
*/
|
|
104
|
-
const config: SquadConfig = {
|
|
105
|
-
version: '1.0.0',
|
|
106
|
-
|
|
107
|
-
models: {
|
|
108
|
-
defaultModel: '${MODELS.DEFAULT}',
|
|
109
|
-
defaultTier: 'standard',
|
|
110
|
-
fallbackChains: {
|
|
111
|
-
premium: ${formatModelArray(MODELS.FALLBACK_CHAINS.premium)},
|
|
112
|
-
standard: ${formatModelArray(MODELS.FALLBACK_CHAINS.standard)},
|
|
113
|
-
fast: ${formatModelArray(MODELS.FALLBACK_CHAINS.fast)}
|
|
114
|
-
},
|
|
115
|
-
preferSameProvider: true,
|
|
116
|
-
respectTierCeiling: true,
|
|
117
|
-
nuclearFallback: {
|
|
118
|
-
enabled: false,
|
|
119
|
-
model: '${MODELS.NUCLEAR_FALLBACK}',
|
|
120
|
-
maxRetriesBeforeNuclear: ${MODELS.NUCLEAR_MAX_RETRIES}
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
routing: {
|
|
125
|
-
rules: [
|
|
126
|
-
{
|
|
127
|
-
workType: 'feature-dev',
|
|
128
|
-
agents: ['@${agents[0]?.name || 'coordinator'}'],
|
|
129
|
-
confidence: 'high'
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
workType: 'bug-fix',
|
|
133
|
-
agents: ['@${agents.find(a => a.role === 'developer')?.name || agents[0]?.name || 'coordinator'}'],
|
|
134
|
-
confidence: 'high'
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
workType: 'testing',
|
|
138
|
-
agents: ['@${agents.find(a => a.role === 'tester')?.name || agents[0]?.name || 'coordinator'}'],
|
|
139
|
-
confidence: 'high'
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
workType: 'documentation',
|
|
143
|
-
agents: ['@${agents.find(a => a.role === 'scribe')?.name || agents[0]?.name || 'coordinator'}'],
|
|
144
|
-
confidence: 'high'
|
|
145
|
-
}
|
|
146
|
-
],
|
|
147
|
-
governance: {
|
|
148
|
-
eagerByDefault: true,
|
|
149
|
-
scribeAutoRuns: false,
|
|
150
|
-
allowRecursiveSpawn: false
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
casting: {
|
|
155
|
-
allowlistUniverses: [
|
|
156
|
-
'The Usual Suspects',
|
|
157
|
-
'Breaking Bad',
|
|
158
|
-
'The Wire',
|
|
159
|
-
'Firefly'
|
|
160
|
-
],
|
|
161
|
-
overflowStrategy: 'generic',
|
|
162
|
-
universeCapacity: {}
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
platforms: {
|
|
166
|
-
vscode: {
|
|
167
|
-
disableModelSelection: false,
|
|
168
|
-
scribeMode: 'sync'
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
export default config;
|
|
97
|
+
return `import type { SquadConfig } from '@bradygaster/squad';
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Squad Configuration for ${projectName}
|
|
101
|
+
* ${projectDescription ? `\n * ${projectDescription}` : ''}
|
|
102
|
+
*/
|
|
103
|
+
const config: SquadConfig = {
|
|
104
|
+
version: '1.0.0',
|
|
105
|
+
|
|
106
|
+
models: {
|
|
107
|
+
defaultModel: '${MODELS.DEFAULT}',
|
|
108
|
+
defaultTier: 'standard',
|
|
109
|
+
fallbackChains: {
|
|
110
|
+
premium: ${formatModelArray(MODELS.FALLBACK_CHAINS.premium)},
|
|
111
|
+
standard: ${formatModelArray(MODELS.FALLBACK_CHAINS.standard)},
|
|
112
|
+
fast: ${formatModelArray(MODELS.FALLBACK_CHAINS.fast)}
|
|
113
|
+
},
|
|
114
|
+
preferSameProvider: true,
|
|
115
|
+
respectTierCeiling: true,
|
|
116
|
+
nuclearFallback: {
|
|
117
|
+
enabled: false,
|
|
118
|
+
model: '${MODELS.NUCLEAR_FALLBACK}',
|
|
119
|
+
maxRetriesBeforeNuclear: ${MODELS.NUCLEAR_MAX_RETRIES}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
routing: {
|
|
124
|
+
rules: [
|
|
125
|
+
{
|
|
126
|
+
workType: 'feature-dev',
|
|
127
|
+
agents: ['@${agents[0]?.name || 'coordinator'}'],
|
|
128
|
+
confidence: 'high'
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
workType: 'bug-fix',
|
|
132
|
+
agents: ['@${agents.find(a => a.role === 'developer')?.name || agents[0]?.name || 'coordinator'}'],
|
|
133
|
+
confidence: 'high'
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
workType: 'testing',
|
|
137
|
+
agents: ['@${agents.find(a => a.role === 'tester')?.name || agents[0]?.name || 'coordinator'}'],
|
|
138
|
+
confidence: 'high'
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
workType: 'documentation',
|
|
142
|
+
agents: ['@${agents.find(a => a.role === 'scribe')?.name || agents[0]?.name || 'coordinator'}'],
|
|
143
|
+
confidence: 'high'
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
governance: {
|
|
147
|
+
eagerByDefault: true,
|
|
148
|
+
scribeAutoRuns: false,
|
|
149
|
+
allowRecursiveSpawn: false
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
casting: {
|
|
154
|
+
allowlistUniverses: [
|
|
155
|
+
'The Usual Suspects',
|
|
156
|
+
'Breaking Bad',
|
|
157
|
+
'The Wire',
|
|
158
|
+
'Firefly'
|
|
159
|
+
],
|
|
160
|
+
overflowStrategy: 'generic',
|
|
161
|
+
universeCapacity: {}
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
platforms: {
|
|
165
|
+
vscode: {
|
|
166
|
+
disableModelSelection: false,
|
|
167
|
+
scribeMode: 'sync'
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export default config;
|
|
174
173
|
`;
|
|
175
174
|
}
|
|
176
175
|
/**
|
|
@@ -367,26 +366,26 @@ function generateCharter(agent, projectName, projectDescription) {
|
|
|
367
366
|
const template = AGENT_TEMPLATES[agent.role];
|
|
368
367
|
const displayName = agent.displayName || template?.displayName || titleCase(agent.name);
|
|
369
368
|
const description = template?.description || 'Team member focused on their assigned responsibilities.';
|
|
370
|
-
return `# ${displayName} — ${titleCase(agent.role)}
|
|
371
|
-
|
|
372
|
-
${description}
|
|
373
|
-
|
|
374
|
-
## Project Context
|
|
375
|
-
|
|
376
|
-
**Project:** ${projectName}
|
|
377
|
-
${projectDescription ? `**Description:** ${projectDescription}\n` : ''}
|
|
378
|
-
|
|
379
|
-
## Responsibilities
|
|
380
|
-
|
|
381
|
-
- Collaborate with team members on assigned work
|
|
382
|
-
- Maintain code quality and project standards
|
|
383
|
-
- Document decisions and progress in history
|
|
384
|
-
|
|
385
|
-
## Work Style
|
|
386
|
-
|
|
387
|
-
- Read project context and team decisions before starting work
|
|
388
|
-
- Communicate clearly with team members
|
|
389
|
-
- Follow established patterns and conventions
|
|
369
|
+
return `# ${displayName} — ${titleCase(agent.role)}
|
|
370
|
+
|
|
371
|
+
${description}
|
|
372
|
+
|
|
373
|
+
## Project Context
|
|
374
|
+
|
|
375
|
+
**Project:** ${projectName}
|
|
376
|
+
${projectDescription ? `**Description:** ${projectDescription}\n` : ''}
|
|
377
|
+
|
|
378
|
+
## Responsibilities
|
|
379
|
+
|
|
380
|
+
- Collaborate with team members on assigned work
|
|
381
|
+
- Maintain code quality and project standards
|
|
382
|
+
- Document decisions and progress in history
|
|
383
|
+
|
|
384
|
+
## Work Style
|
|
385
|
+
|
|
386
|
+
- Read project context and team decisions before starting work
|
|
387
|
+
- Communicate clearly with team members
|
|
388
|
+
- Follow established patterns and conventions
|
|
390
389
|
`;
|
|
391
390
|
}
|
|
392
391
|
/**
|
|
@@ -395,22 +394,22 @@ ${projectDescription ? `**Description:** ${projectDescription}\n` : ''}
|
|
|
395
394
|
function generateInitialHistory(agent, projectName, projectDescription, userName) {
|
|
396
395
|
const displayName = agent.displayName || AGENT_TEMPLATES[agent.role]?.displayName || titleCase(agent.name);
|
|
397
396
|
const now = new Date().toISOString().split('T')[0];
|
|
398
|
-
return `# Project Context
|
|
399
|
-
|
|
400
|
-
${userName ? `- **Owner:** ${userName}\n` : ''}- **Project:** ${projectName}
|
|
401
|
-
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${now}
|
|
402
|
-
|
|
403
|
-
## Core Context
|
|
404
|
-
|
|
405
|
-
Agent ${displayName} initialized and ready for work.
|
|
406
|
-
|
|
407
|
-
## Recent Updates
|
|
408
|
-
|
|
409
|
-
📌 Team initialized on ${now}
|
|
410
|
-
|
|
411
|
-
## Learnings
|
|
412
|
-
|
|
413
|
-
Initial setup complete.
|
|
397
|
+
return `# Project Context
|
|
398
|
+
|
|
399
|
+
${userName ? `- **Owner:** ${userName}\n` : ''}- **Project:** ${projectName}
|
|
400
|
+
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${now}
|
|
401
|
+
|
|
402
|
+
## Core Context
|
|
403
|
+
|
|
404
|
+
Agent ${displayName} initialized and ready for work.
|
|
405
|
+
|
|
406
|
+
## Recent Updates
|
|
407
|
+
|
|
408
|
+
📌 Team initialized on ${now}
|
|
409
|
+
|
|
410
|
+
## Learnings
|
|
411
|
+
|
|
412
|
+
Initial setup complete.
|
|
414
413
|
`;
|
|
415
414
|
}
|
|
416
415
|
/**
|
|
@@ -467,7 +466,7 @@ const FRAMEWORK_WORKFLOWS = [
|
|
|
467
466
|
'squad-triage.yml',
|
|
468
467
|
'sync-squad-labels.yml',
|
|
469
468
|
];
|
|
470
|
-
export async function initSquad(options) {
|
|
469
|
+
export async function initSquad(options, storage = new FSStorageProvider()) {
|
|
471
470
|
const { teamRoot, projectName, projectDescription, agents, configFormat = 'typescript', userName, skipExisting = true, includeWorkflows = true, includeTemplates = true, includeMcpConfig = true, projectType = 'unknown', version = '0.0.0', } = options;
|
|
472
471
|
const createdFiles = [];
|
|
473
472
|
const skippedFiles = [];
|
|
@@ -498,23 +497,22 @@ export async function initSquad(options) {
|
|
|
498
497
|
};
|
|
499
498
|
// Helper to write file (respects skipExisting)
|
|
500
499
|
const writeIfNotExists = async (filePath, content) => {
|
|
501
|
-
if (existsSync(filePath) && skipExisting) {
|
|
500
|
+
if (storage.existsSync(filePath) && skipExisting) {
|
|
502
501
|
skippedFiles.push(toRelativePath(filePath));
|
|
503
502
|
return false;
|
|
504
503
|
}
|
|
505
|
-
await
|
|
506
|
-
await writeFile(filePath, content, 'utf-8');
|
|
504
|
+
await storage.write(filePath, content);
|
|
507
505
|
createdFiles.push(toRelativePath(filePath));
|
|
508
506
|
return true;
|
|
509
507
|
};
|
|
510
508
|
// Helper to copy file (respects skipExisting)
|
|
511
509
|
const copyIfNotExists = async (src, dest) => {
|
|
512
|
-
if (existsSync(dest) && skipExisting) {
|
|
510
|
+
if (storage.existsSync(dest) && skipExisting) {
|
|
513
511
|
skippedFiles.push(toRelativePath(dest));
|
|
514
512
|
return false;
|
|
515
513
|
}
|
|
516
|
-
await mkdir(dirname(dest), { recursive: true });
|
|
517
|
-
|
|
514
|
+
await storage.mkdir(dirname(dest), { recursive: true });
|
|
515
|
+
storage.copySync(src, dest);
|
|
518
516
|
createdFiles.push(toRelativePath(dest));
|
|
519
517
|
return true;
|
|
520
518
|
};
|
|
@@ -534,19 +532,45 @@ export async function initSquad(options) {
|
|
|
534
532
|
join(squadDir, 'log'),
|
|
535
533
|
];
|
|
536
534
|
for (const dir of directories) {
|
|
537
|
-
if (!existsSync(dir)) {
|
|
538
|
-
await mkdir(dir, { recursive: true });
|
|
535
|
+
if (!storage.existsSync(dir)) {
|
|
536
|
+
await storage.mkdir(dir, { recursive: true });
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
// -------------------------------------------------------------------------
|
|
540
|
+
// Scaffold .squad/casting/ files (policy, registry, history)
|
|
541
|
+
// -------------------------------------------------------------------------
|
|
542
|
+
const castingDir = join(squadDir, 'casting');
|
|
543
|
+
const castingFiles = [
|
|
544
|
+
{ name: 'policy.json', templateName: 'casting-policy.json', fallback: JSON.stringify({ casting_policy_version: '1.1', allowlist_universes: [], universe_capacity: {} }, null, 2) + '\n' },
|
|
545
|
+
{ name: 'registry.json', templateName: 'casting-registry.json', fallback: JSON.stringify({ agents: {} }, null, 2) + '\n' },
|
|
546
|
+
{ name: 'history.json', templateName: 'casting-history.json', fallback: JSON.stringify({ universe_usage_history: [], assignment_cast_snapshots: {} }, null, 2) + '\n' },
|
|
547
|
+
];
|
|
548
|
+
for (const cf of castingFiles) {
|
|
549
|
+
const dest = join(castingDir, cf.name);
|
|
550
|
+
if (!storage.existsSync(dest)) {
|
|
551
|
+
// Try to copy from SDK templates first, fall back to inline defaults
|
|
552
|
+
const templateSrc = templatesDir ? join(templatesDir, cf.templateName) : null;
|
|
553
|
+
if (templateSrc && storage.existsSync(templateSrc)) {
|
|
554
|
+
storage.copySync(templateSrc, dest);
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
await storage.write(dest, cf.fallback);
|
|
558
|
+
}
|
|
559
|
+
createdFiles.push(toRelativePath(dest));
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
skippedFiles.push(toRelativePath(dest));
|
|
539
563
|
}
|
|
540
564
|
}
|
|
541
565
|
// -------------------------------------------------------------------------
|
|
542
566
|
// Create .squad/config.json for squad settings
|
|
543
567
|
// -------------------------------------------------------------------------
|
|
544
568
|
const squadConfigPath = join(squadDir, 'config.json');
|
|
545
|
-
if (!existsSync(squadConfigPath)) {
|
|
569
|
+
if (!storage.existsSync(squadConfigPath)) {
|
|
546
570
|
// Detect platform from git remote for config
|
|
547
571
|
let detectedPlatform;
|
|
548
572
|
try {
|
|
549
|
-
const remoteUrl = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: teamRoot, encoding: 'utf-8' }).trim();
|
|
573
|
+
const remoteUrl = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: teamRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
550
574
|
const remoteUrlLower = remoteUrl.toLowerCase();
|
|
551
575
|
if (remoteUrlLower.includes('dev.azure.com') || remoteUrlLower.includes('visualstudio.com') || remoteUrlLower.includes('ssh.dev.azure.com')) {
|
|
552
576
|
detectedPlatform = 'azure-devops';
|
|
@@ -566,7 +590,7 @@ export async function initSquad(options) {
|
|
|
566
590
|
// to discover available work item types for the project.
|
|
567
591
|
let introspectedTypes;
|
|
568
592
|
try {
|
|
569
|
-
const remoteUrl = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: teamRoot, encoding: 'utf-8' }).trim();
|
|
593
|
+
const remoteUrl = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: teamRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
570
594
|
// Parse org/project from remote URL for introspection
|
|
571
595
|
const httpsMatch = remoteUrl.match(/dev\.azure\.com\/([^/]+)\/([^/]+)\/_git/i);
|
|
572
596
|
const sshMatch = remoteUrl.match(/ssh\.dev\.azure\.com:v3\/([^/]+)\/([^/]+)\//i);
|
|
@@ -605,7 +629,7 @@ export async function initSquad(options) {
|
|
|
605
629
|
if (options.extractionDisabled) {
|
|
606
630
|
squadConfig.extractionDisabled = true;
|
|
607
631
|
}
|
|
608
|
-
await
|
|
632
|
+
await storage.write(squadConfigPath, JSON.stringify(squadConfig, null, 2));
|
|
609
633
|
createdFiles.push(toRelativePath(squadConfigPath));
|
|
610
634
|
}
|
|
611
635
|
// -------------------------------------------------------------------------
|
|
@@ -633,7 +657,6 @@ export async function initSquad(options) {
|
|
|
633
657
|
const agentsDir = join(squadDir, 'agents');
|
|
634
658
|
for (const agent of agents) {
|
|
635
659
|
const agentDir = join(agentsDir, agent.name);
|
|
636
|
-
await mkdir(agentDir, { recursive: true });
|
|
637
660
|
agentDirs.push(agentDir);
|
|
638
661
|
// Create charter.md
|
|
639
662
|
const charterPath = join(agentDir, 'charter.md');
|
|
@@ -650,27 +673,27 @@ export async function initSquad(options) {
|
|
|
650
673
|
const identityDir = join(squadDir, 'identity');
|
|
651
674
|
const nowMdPath = join(identityDir, 'now.md');
|
|
652
675
|
const wisdomMdPath = join(identityDir, 'wisdom.md');
|
|
653
|
-
const nowContent = `---
|
|
654
|
-
updated_at: ${new Date().toISOString()}
|
|
655
|
-
focus_area: Initial setup
|
|
656
|
-
active_issues: []
|
|
657
|
-
---
|
|
658
|
-
|
|
659
|
-
# What We're Focused On
|
|
660
|
-
|
|
661
|
-
Getting started. Updated by coordinator at session start.
|
|
676
|
+
const nowContent = `---
|
|
677
|
+
updated_at: ${new Date().toISOString()}
|
|
678
|
+
focus_area: Initial setup
|
|
679
|
+
active_issues: []
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
# What We're Focused On
|
|
683
|
+
|
|
684
|
+
Getting started. Updated by coordinator at session start.
|
|
662
685
|
`;
|
|
663
|
-
const wisdomContent = `---
|
|
664
|
-
last_updated: ${new Date().toISOString()}
|
|
665
|
-
---
|
|
666
|
-
|
|
667
|
-
# Team Wisdom
|
|
668
|
-
|
|
669
|
-
Reusable patterns and heuristics learned through work. NOT transcripts — each entry is a distilled, actionable insight.
|
|
670
|
-
|
|
671
|
-
## Patterns
|
|
672
|
-
|
|
673
|
-
<!-- Append entries below. Format: **Pattern:** description. **Context:** when it applies. -->
|
|
686
|
+
const wisdomContent = `---
|
|
687
|
+
last_updated: ${new Date().toISOString()}
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
# Team Wisdom
|
|
691
|
+
|
|
692
|
+
Reusable patterns and heuristics learned through work. NOT transcripts — each entry is a distilled, actionable insight.
|
|
693
|
+
|
|
694
|
+
## Patterns
|
|
695
|
+
|
|
696
|
+
<!-- Append entries below. Format: **Pattern:** description. **Context:** when it applies. -->
|
|
674
697
|
`;
|
|
675
698
|
await writeIfNotExists(nowMdPath, nowContent);
|
|
676
699
|
await writeIfNotExists(wisdomMdPath, wisdomContent);
|
|
@@ -678,70 +701,70 @@ Reusable patterns and heuristics learned through work. NOT transcripts — each
|
|
|
678
701
|
// Create ceremonies.md
|
|
679
702
|
// -------------------------------------------------------------------------
|
|
680
703
|
const ceremoniesDest = join(squadDir, 'ceremonies.md');
|
|
681
|
-
if (templatesDir && existsSync(join(templatesDir, 'ceremonies.md'))) {
|
|
704
|
+
if (templatesDir && storage.existsSync(join(templatesDir, 'ceremonies.md'))) {
|
|
682
705
|
await copyIfNotExists(join(templatesDir, 'ceremonies.md'), ceremoniesDest);
|
|
683
706
|
}
|
|
684
707
|
// -------------------------------------------------------------------------
|
|
685
708
|
// Create decisions.md (canonical location at squad root)
|
|
686
709
|
// -------------------------------------------------------------------------
|
|
687
710
|
const decisionsPath = join(squadDir, 'decisions.md');
|
|
688
|
-
const decisionsContent = `# Squad Decisions
|
|
689
|
-
|
|
690
|
-
## Active Decisions
|
|
691
|
-
|
|
692
|
-
No decisions recorded yet.
|
|
693
|
-
|
|
694
|
-
## Governance
|
|
695
|
-
|
|
696
|
-
- All meaningful changes require team consensus
|
|
697
|
-
- Document architectural decisions here
|
|
698
|
-
- Keep history focused on work, decisions focused on direction
|
|
711
|
+
const decisionsContent = `# Squad Decisions
|
|
712
|
+
|
|
713
|
+
## Active Decisions
|
|
714
|
+
|
|
715
|
+
No decisions recorded yet.
|
|
716
|
+
|
|
717
|
+
## Governance
|
|
718
|
+
|
|
719
|
+
- All meaningful changes require team consensus
|
|
720
|
+
- Document architectural decisions here
|
|
721
|
+
- Keep history focused on work, decisions focused on direction
|
|
699
722
|
`;
|
|
700
723
|
await writeIfNotExists(decisionsPath, decisionsContent);
|
|
701
724
|
// -------------------------------------------------------------------------
|
|
702
725
|
// Create team.md (required by shell lifecycle)
|
|
703
726
|
// -------------------------------------------------------------------------
|
|
704
727
|
const teamPath = join(squadDir, 'team.md');
|
|
705
|
-
const teamContent = `# Squad Team
|
|
706
|
-
|
|
707
|
-
> ${projectDescription || projectName}
|
|
708
|
-
|
|
709
|
-
## Coordinator
|
|
710
|
-
|
|
711
|
-
| Name | Role | Notes |
|
|
712
|
-
|------|------|-------|
|
|
713
|
-
| Squad | Coordinator | Routes work, enforces handoffs and reviewer gates. |
|
|
714
|
-
|
|
715
|
-
## Members
|
|
716
|
-
|
|
717
|
-
| Name | Role | Charter | Status |
|
|
718
|
-
|------|------|---------|--------|
|
|
719
|
-
|
|
720
|
-
## Project Context
|
|
721
|
-
|
|
722
|
-
- **Project:** ${projectName}
|
|
723
|
-
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${new Date().toISOString().split('T')[0]}
|
|
728
|
+
const teamContent = `# Squad Team
|
|
729
|
+
|
|
730
|
+
> ${projectDescription || projectName}
|
|
731
|
+
|
|
732
|
+
## Coordinator
|
|
733
|
+
|
|
734
|
+
| Name | Role | Notes |
|
|
735
|
+
|------|------|-------|
|
|
736
|
+
| Squad | Coordinator | Routes work, enforces handoffs and reviewer gates. |
|
|
737
|
+
|
|
738
|
+
## Members
|
|
739
|
+
|
|
740
|
+
| Name | Role | Charter | Status |
|
|
741
|
+
|------|------|---------|--------|
|
|
742
|
+
|
|
743
|
+
## Project Context
|
|
744
|
+
|
|
745
|
+
- **Project:** ${projectName}
|
|
746
|
+
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${new Date().toISOString().split('T')[0]}
|
|
724
747
|
`;
|
|
725
748
|
await writeIfNotExists(teamPath, teamContent);
|
|
726
749
|
// -------------------------------------------------------------------------
|
|
727
750
|
// Create routing.md
|
|
728
751
|
// -------------------------------------------------------------------------
|
|
729
752
|
const routingPath = join(squadDir, 'routing.md');
|
|
730
|
-
if (templatesDir && existsSync(join(templatesDir, 'routing.md'))) {
|
|
753
|
+
if (templatesDir && storage.existsSync(join(templatesDir, 'routing.md'))) {
|
|
731
754
|
await copyIfNotExists(join(templatesDir, 'routing.md'), routingPath);
|
|
732
755
|
}
|
|
733
756
|
else {
|
|
734
|
-
const routingContent = `# Squad Routing
|
|
735
|
-
|
|
736
|
-
## Work Type Rules
|
|
737
|
-
|
|
738
|
-
| Work Type | Primary Agent | Fallback |
|
|
739
|
-
|-----------|---------------|----------|
|
|
740
|
-
|
|
741
|
-
## Governance
|
|
742
|
-
|
|
743
|
-
- Route based on work type and agent expertise
|
|
744
|
-
- Update this file as team capabilities evolve
|
|
757
|
+
const routingContent = `# Squad Routing
|
|
758
|
+
|
|
759
|
+
## Work Type Rules
|
|
760
|
+
|
|
761
|
+
| Work Type | Primary Agent | Fallback |
|
|
762
|
+
|-----------|---------------|----------|
|
|
763
|
+
|
|
764
|
+
## Governance
|
|
765
|
+
|
|
766
|
+
- Route based on work type and agent expertise
|
|
767
|
+
- Update this file as team capabilities evolve
|
|
745
768
|
`;
|
|
746
769
|
await writeIfNotExists(routingPath, routingContent);
|
|
747
770
|
}
|
|
@@ -749,11 +772,11 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
749
772
|
// Copy starter skills
|
|
750
773
|
// -------------------------------------------------------------------------
|
|
751
774
|
const skillsDir = join(teamRoot, '.copilot', 'skills');
|
|
752
|
-
if (templatesDir && existsSync(join(templatesDir, 'skills'))) {
|
|
775
|
+
if (templatesDir && storage.existsSync(join(templatesDir, 'skills'))) {
|
|
753
776
|
const skillsSrc = join(templatesDir, 'skills');
|
|
754
|
-
const existingSkills = existsSync(skillsDir) ?
|
|
777
|
+
const existingSkills = storage.existsSync(skillsDir) ? storage.listSync(skillsDir) : [];
|
|
755
778
|
if (existingSkills.length === 0) {
|
|
756
|
-
|
|
779
|
+
copyRecursiveSync(skillsSrc, skillsDir, storage);
|
|
757
780
|
createdFiles.push('.copilot/skills');
|
|
758
781
|
}
|
|
759
782
|
}
|
|
@@ -768,15 +791,15 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
768
791
|
'.squad/orchestration-log/** merge=union',
|
|
769
792
|
];
|
|
770
793
|
let existingAttrs = '';
|
|
771
|
-
if (existsSync(gitattributesPath)) {
|
|
772
|
-
existingAttrs =
|
|
794
|
+
if (storage.existsSync(gitattributesPath)) {
|
|
795
|
+
existingAttrs = storage.readSync(gitattributesPath) ?? '';
|
|
773
796
|
}
|
|
774
797
|
const missingRules = unionRules.filter(rule => !existingAttrs.includes(rule));
|
|
775
798
|
if (missingRules.length > 0) {
|
|
776
799
|
const block = (existingAttrs && !existingAttrs.endsWith('\n') ? '\n' : '')
|
|
777
800
|
+ '# Squad: union merge for append-only team state files\n'
|
|
778
801
|
+ missingRules.join('\n') + '\n';
|
|
779
|
-
await
|
|
802
|
+
await storage.append(gitattributesPath, block);
|
|
780
803
|
createdFiles.push(toRelativePath(gitattributesPath));
|
|
781
804
|
}
|
|
782
805
|
// -------------------------------------------------------------------------
|
|
@@ -792,27 +815,26 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
792
815
|
'.squad/sessions/',
|
|
793
816
|
];
|
|
794
817
|
let existingIgnore = '';
|
|
795
|
-
if (existsSync(gitignorePath)) {
|
|
796
|
-
existingIgnore =
|
|
818
|
+
if (storage.existsSync(gitignorePath)) {
|
|
819
|
+
existingIgnore = storage.readSync(gitignorePath) ?? '';
|
|
797
820
|
}
|
|
798
821
|
const missingIgnore = ignoreEntries.filter(entry => !existingIgnore.includes(entry));
|
|
799
822
|
if (missingIgnore.length > 0) {
|
|
800
823
|
const block = (existingIgnore && !existingIgnore.endsWith('\n') ? '\n' : '')
|
|
801
824
|
+ '# Squad: ignore runtime state (logs, inbox, sessions)\n'
|
|
802
825
|
+ missingIgnore.join('\n') + '\n';
|
|
803
|
-
await
|
|
826
|
+
await storage.append(gitignorePath, block);
|
|
804
827
|
createdFiles.push(toRelativePath(gitignorePath));
|
|
805
828
|
}
|
|
806
829
|
// -------------------------------------------------------------------------
|
|
807
830
|
// Create .github/agents/squad.agent.md
|
|
808
831
|
// -------------------------------------------------------------------------
|
|
809
832
|
const agentFile = join(teamRoot, '.github', 'agents', 'squad.agent.md');
|
|
810
|
-
if (!existsSync(agentFile) || !skipExisting) {
|
|
811
|
-
if (templatesDir && existsSync(join(templatesDir, 'squad.agent.md'))) {
|
|
812
|
-
let agentContent =
|
|
833
|
+
if (!storage.existsSync(agentFile) || !skipExisting) {
|
|
834
|
+
if (templatesDir && storage.existsSync(join(templatesDir, 'squad.agent.md.template'))) {
|
|
835
|
+
let agentContent = storage.readSync(join(templatesDir, 'squad.agent.md.template')) ?? '';
|
|
813
836
|
agentContent = stampVersionInContent(agentContent, version);
|
|
814
|
-
await
|
|
815
|
-
await writeFile(agentFile, agentContent, 'utf-8');
|
|
837
|
+
await storage.write(agentFile, agentContent);
|
|
816
838
|
createdFiles.push(toRelativePath(agentFile));
|
|
817
839
|
}
|
|
818
840
|
}
|
|
@@ -824,8 +846,8 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
824
846
|
// -------------------------------------------------------------------------
|
|
825
847
|
if (includeTemplates && templatesDir) {
|
|
826
848
|
const templatesDest = join(teamRoot, '.squad', 'templates');
|
|
827
|
-
if (!existsSync(templatesDest)) {
|
|
828
|
-
|
|
849
|
+
if (!storage.existsSync(templatesDest)) {
|
|
850
|
+
copyRecursiveSync(templatesDir, templatesDest, storage);
|
|
829
851
|
createdFiles.push(toRelativePath(templatesDest));
|
|
830
852
|
}
|
|
831
853
|
else {
|
|
@@ -837,7 +859,7 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
837
859
|
// -------------------------------------------------------------------------
|
|
838
860
|
let isGitHub = true;
|
|
839
861
|
try {
|
|
840
|
-
const remoteUrl = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: teamRoot, encoding: 'utf-8' }).trim();
|
|
862
|
+
const remoteUrl = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: teamRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
841
863
|
const remoteUrlLower = remoteUrl.toLowerCase();
|
|
842
864
|
if (remoteUrlLower.includes('dev.azure.com') || remoteUrlLower.includes('visualstudio.com') || remoteUrlLower.includes('ssh.dev.azure.com')) {
|
|
843
865
|
isGitHub = false;
|
|
@@ -849,17 +871,17 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
849
871
|
// -------------------------------------------------------------------------
|
|
850
872
|
// Copy workflows (optional) — skip for ADO repos
|
|
851
873
|
// -------------------------------------------------------------------------
|
|
852
|
-
if (includeWorkflows && isGitHub && templatesDir && existsSync(join(templatesDir, 'workflows'))) {
|
|
874
|
+
if (includeWorkflows && isGitHub && templatesDir && storage.existsSync(join(templatesDir, 'workflows'))) {
|
|
853
875
|
const workflowsSrc = join(templatesDir, 'workflows');
|
|
854
876
|
const workflowsDest = join(teamRoot, '.github', 'workflows');
|
|
855
|
-
if (
|
|
856
|
-
const allWorkflowFiles =
|
|
877
|
+
if (storage.isDirectorySync(workflowsSrc)) {
|
|
878
|
+
const allWorkflowFiles = storage.listSync(workflowsSrc).filter(f => f.endsWith('.yml'));
|
|
857
879
|
const workflowFiles = allWorkflowFiles.filter(f => FRAMEWORK_WORKFLOWS.includes(f));
|
|
858
|
-
await mkdir(workflowsDest, { recursive: true });
|
|
880
|
+
await storage.mkdir(workflowsDest, { recursive: true });
|
|
859
881
|
for (const file of workflowFiles) {
|
|
860
882
|
const destFile = join(workflowsDest, file);
|
|
861
|
-
if (!existsSync(destFile) || !skipExisting) {
|
|
862
|
-
|
|
883
|
+
if (!storage.existsSync(destFile) || !skipExisting) {
|
|
884
|
+
storage.copySync(join(workflowsSrc, file), destFile);
|
|
863
885
|
createdFiles.push(toRelativePath(destFile));
|
|
864
886
|
}
|
|
865
887
|
else {
|
|
@@ -873,7 +895,7 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
873
895
|
// -------------------------------------------------------------------------
|
|
874
896
|
if (includeMcpConfig) {
|
|
875
897
|
const mcpConfigPath = join(teamRoot, '.copilot', 'mcp-config.json');
|
|
876
|
-
if (!existsSync(mcpConfigPath)) {
|
|
898
|
+
if (!storage.existsSync(mcpConfigPath)) {
|
|
877
899
|
const mcpSample = isGitHub
|
|
878
900
|
? {
|
|
879
901
|
mcpServers: {
|
|
@@ -898,8 +920,7 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
898
920
|
}
|
|
899
921
|
}
|
|
900
922
|
};
|
|
901
|
-
await
|
|
902
|
-
await writeFile(mcpConfigPath, JSON.stringify(mcpSample, null, 2) + '\n', 'utf-8');
|
|
923
|
+
await storage.write(mcpConfigPath, JSON.stringify(mcpSample, null, 2) + '\n');
|
|
903
924
|
createdFiles.push(toRelativePath(mcpConfigPath));
|
|
904
925
|
}
|
|
905
926
|
else {
|
|
@@ -923,14 +944,14 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
923
944
|
{
|
|
924
945
|
const workstreamIgnoreEntry = '.squad-workstream';
|
|
925
946
|
let currentIgnore = '';
|
|
926
|
-
if (existsSync(gitignorePath)) {
|
|
927
|
-
currentIgnore =
|
|
947
|
+
if (storage.existsSync(gitignorePath)) {
|
|
948
|
+
currentIgnore = storage.readSync(gitignorePath) ?? '';
|
|
928
949
|
}
|
|
929
950
|
if (!currentIgnore.includes(workstreamIgnoreEntry)) {
|
|
930
951
|
const block = (currentIgnore && !currentIgnore.endsWith('\n') ? '\n' : '')
|
|
931
952
|
+ '# Squad: SubSquad activation file (local to this machine)\n'
|
|
932
953
|
+ workstreamIgnoreEntry + '\n';
|
|
933
|
-
await
|
|
954
|
+
await storage.append(gitignorePath, block);
|
|
934
955
|
createdFiles.push(toRelativePath(gitignorePath));
|
|
935
956
|
}
|
|
936
957
|
}
|
|
@@ -938,8 +959,8 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
938
959
|
// Create .first-run marker
|
|
939
960
|
// -------------------------------------------------------------------------
|
|
940
961
|
const firstRunMarker = join(squadDir, '.first-run');
|
|
941
|
-
if (!existsSync(firstRunMarker)) {
|
|
942
|
-
await
|
|
962
|
+
if (!storage.existsSync(firstRunMarker)) {
|
|
963
|
+
await storage.write(firstRunMarker, new Date().toISOString() + '\n');
|
|
943
964
|
createdFiles.push(toRelativePath(firstRunMarker));
|
|
944
965
|
}
|
|
945
966
|
// -------------------------------------------------------------------------
|
|
@@ -947,7 +968,7 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
947
968
|
// -------------------------------------------------------------------------
|
|
948
969
|
if (options.prompt) {
|
|
949
970
|
const promptFile = join(squadDir, '.init-prompt');
|
|
950
|
-
await
|
|
971
|
+
await storage.write(promptFile, options.prompt);
|
|
951
972
|
createdFiles.push(toRelativePath(promptFile));
|
|
952
973
|
}
|
|
953
974
|
return {
|
|
@@ -965,10 +986,10 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
965
986
|
*
|
|
966
987
|
* @param squadDir - Path to the .squad directory
|
|
967
988
|
*/
|
|
968
|
-
export async function cleanupOrphanInitPrompt(squadDir) {
|
|
989
|
+
export async function cleanupOrphanInitPrompt(squadDir, storage = new FSStorageProvider()) {
|
|
969
990
|
const promptFile = join(squadDir, '.init-prompt');
|
|
970
|
-
if (existsSync(promptFile)) {
|
|
971
|
-
await
|
|
991
|
+
if (storage.existsSync(promptFile)) {
|
|
992
|
+
await storage.delete(promptFile);
|
|
972
993
|
}
|
|
973
994
|
}
|
|
974
995
|
//# sourceMappingURL=init.js.map
|