@bradygaster/squad-sdk 0.8.19 → 0.8.21
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 +296 -296
- package/dist/adapter/client.js +1 -1
- package/dist/adapter/client.js.map +1 -1
- package/dist/agents/charter-compiler.d.ts +4 -0
- package/dist/agents/charter-compiler.d.ts.map +1 -1
- package/dist/agents/charter-compiler.js +8 -0
- package/dist/agents/charter-compiler.js.map +1 -1
- package/dist/agents/history-shadow.js +30 -30
- package/dist/agents/index.js +1 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lifecycle.js +1 -1
- package/dist/agents/lifecycle.js.map +1 -1
- package/dist/build/github-dist.js +42 -42
- package/dist/builders/index.d.ts +156 -0
- package/dist/builders/index.d.ts.map +1 -0
- package/dist/builders/index.js +404 -0
- package/dist/builders/index.js.map +1 -0
- package/dist/builders/types.d.ts +187 -0
- package/dist/builders/types.d.ts.map +1 -0
- package/dist/builders/types.js +12 -0
- package/dist/builders/types.js.map +1 -0
- package/dist/config/init.d.ts +6 -22
- package/dist/config/init.d.ts.map +1 -1
- package/dist/config/init.js +273 -185
- package/dist/config/init.js.map +1 -1
- package/dist/coordinator/coordinator.js +1 -1
- package/dist/coordinator/coordinator.js.map +1 -1
- package/dist/coordinator/index.js +1 -1
- package/dist/coordinator/index.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/otel-api.d.ts +38 -0
- package/dist/runtime/otel-api.d.ts.map +1 -0
- package/dist/runtime/otel-api.js +94 -0
- package/dist/runtime/otel-api.js.map +1 -0
- package/dist/runtime/otel-bridge.js +1 -1
- package/dist/runtime/otel-bridge.js.map +1 -1
- package/dist/runtime/otel.d.ts +1 -1
- package/dist/runtime/otel.d.ts.map +1 -1
- package/dist/runtime/otel.js +28 -12
- package/dist/runtime/otel.js.map +1 -1
- package/dist/runtime/squad-observer.js +1 -1
- package/dist/runtime/squad-observer.js.map +1 -1
- package/dist/sharing/consult.js +78 -78
- package/dist/streams/filter.d.ts +33 -0
- package/dist/streams/filter.d.ts.map +1 -0
- package/dist/streams/filter.js +29 -0
- package/dist/streams/filter.js.map +1 -0
- package/dist/streams/index.d.ts +9 -0
- package/dist/streams/index.d.ts.map +1 -0
- package/dist/streams/index.js +9 -0
- package/dist/streams/index.js.map +1 -0
- package/dist/streams/resolver.d.ts +40 -0
- package/dist/streams/resolver.d.ts.map +1 -0
- package/dist/streams/resolver.js +162 -0
- package/dist/streams/resolver.js.map +1 -0
- package/dist/streams/types.d.ts +44 -0
- package/dist/streams/types.d.ts.map +1 -0
- package/dist/streams/types.js +10 -0
- package/dist/streams/types.js.map +1 -0
- package/dist/tools/index.js +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +208 -207
- package/templates/casting-history.json +4 -4
- package/templates/casting-policy.json +35 -35
- 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/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/mcp-config.md +98 -98
- package/templates/multi-agent-format.md +28 -28
- package/templates/orchestration-log.md +27 -27
- package/templates/plugin-marketplace.md +49 -49
- package/templates/raw-agent-output.md +37 -37
- package/templates/roster.md +60 -60
- package/templates/routing.md +54 -54
- package/templates/run-output.md +50 -50
- package/templates/scribe-charter.md +119 -119
- package/templates/skill.md +24 -24
- package/templates/skills/project-conventions/SKILL.md +56 -56
- package/templates/squad.agent.md +1146 -1146
- package/templates/workflows/squad-ci.yml +24 -24
- package/templates/workflows/squad-docs.yml +50 -50
- package/templates/workflows/squad-heartbeat.yml +316 -316
- 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 -121
- 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/runtime/event-bus-otel-bridge.d.ts +0 -19
- package/dist/runtime/event-bus-otel-bridge.d.ts.map +0 -1
- package/dist/runtime/event-bus-otel-bridge.js +0 -61
- package/dist/runtime/event-bus-otel-bridge.js.map +0 -1
- package/templates/workflows/squad-main-guard.yml +0 -129
package/dist/config/init.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module config/init
|
|
9
9
|
*/
|
|
10
|
+
import type { WorkstreamDefinition } from '../streams/types.js';
|
|
10
11
|
/**
|
|
11
12
|
* Get the SDK templates directory path.
|
|
12
13
|
*/
|
|
@@ -34,15 +35,15 @@ export interface InitOptions {
|
|
|
34
35
|
projectDescription?: string;
|
|
35
36
|
/** Agents to create */
|
|
36
37
|
agents: InitAgentSpec[];
|
|
37
|
-
/** Config format (typescript or json) */
|
|
38
|
-
configFormat?: 'typescript' | 'json';
|
|
38
|
+
/** Config format (typescript or json for old format, sdk for new builder syntax, markdown for no config file) */
|
|
39
|
+
configFormat?: 'typescript' | 'json' | 'sdk' | 'markdown';
|
|
39
40
|
/** User name for initial history entries */
|
|
40
41
|
userName?: string;
|
|
41
42
|
/** Skip files that already exist (default: true) */
|
|
42
43
|
skipExisting?: boolean;
|
|
43
44
|
/** Include GitHub workflows (default: true) */
|
|
44
45
|
includeWorkflows?: boolean;
|
|
45
|
-
/** Include .squad
|
|
46
|
+
/** Include .squad/templates/ copy (default: true) */
|
|
46
47
|
includeTemplates?: boolean;
|
|
47
48
|
/** Include sample MCP config (default: true) */
|
|
48
49
|
includeMcpConfig?: boolean;
|
|
@@ -54,6 +55,8 @@ export interface InitOptions {
|
|
|
54
55
|
prompt?: string;
|
|
55
56
|
/** If true, disable extraction from consult sessions (read-only consultations) */
|
|
56
57
|
extractionDisabled?: boolean;
|
|
58
|
+
/** Optional workstream definitions — generates .squad/workstreams.json when provided */
|
|
59
|
+
streams?: WorkstreamDefinition[];
|
|
57
60
|
}
|
|
58
61
|
/**
|
|
59
62
|
* Initialization result.
|
|
@@ -72,25 +75,6 @@ export interface InitResult {
|
|
|
72
75
|
/** Path to .squad/ directory */
|
|
73
76
|
squadDir: string;
|
|
74
77
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Initialize a new Squad project.
|
|
77
|
-
*
|
|
78
|
-
* Creates:
|
|
79
|
-
* - .squad/ directory structure (agents, casting, decisions, skills, identity, etc.)
|
|
80
|
-
* - squad.config.ts or squad.config.json
|
|
81
|
-
* - Agent directories with charter.md and history.md
|
|
82
|
-
* - .gitattributes for merge drivers
|
|
83
|
-
* - .gitignore entries for logs
|
|
84
|
-
* - .github/agents/squad.agent.md
|
|
85
|
-
* - .github/workflows/ (optional)
|
|
86
|
-
* - .squad-templates/ (optional)
|
|
87
|
-
* - .copilot/mcp-config.json (optional)
|
|
88
|
-
* - Identity files (now.md, wisdom.md)
|
|
89
|
-
* - ceremonies.md
|
|
90
|
-
*
|
|
91
|
-
* @param options - Initialization options
|
|
92
|
-
* @returns Result with created file paths
|
|
93
|
-
*/
|
|
94
78
|
export declare function initSquad(options: InitOptions): Promise<InitResult>;
|
|
95
79
|
/**
|
|
96
80
|
* Clean up orphan .init-prompt file.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/config/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/config/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAMhE;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAiBlD;AA0BD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB;IACvB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,iHAAiH;IACjH,YAAY,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;IAC1D,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IAChF,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wFAAwF;IACxF,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mDAAmD;IACnD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6WD,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA+dzE;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7E"}
|
package/dist/config/init.js
CHANGED
|
@@ -93,82 +93,82 @@ function formatModelArray(chain) {
|
|
|
93
93
|
*/
|
|
94
94
|
function generateTypeScriptConfig(options) {
|
|
95
95
|
const { projectName, projectDescription, agents } = options;
|
|
96
|
-
return `import type { SquadConfig } from '@bradygaster/squad';
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Squad Configuration for ${projectName}
|
|
100
|
-
* ${projectDescription ? `\n * ${projectDescription}` : ''}
|
|
101
|
-
*/
|
|
102
|
-
const config: SquadConfig = {
|
|
103
|
-
version: '1.0.0',
|
|
104
|
-
|
|
105
|
-
models: {
|
|
106
|
-
defaultModel: '${MODELS.DEFAULT}',
|
|
107
|
-
defaultTier: 'standard',
|
|
108
|
-
fallbackChains: {
|
|
109
|
-
premium: ${formatModelArray(MODELS.FALLBACK_CHAINS.premium)},
|
|
110
|
-
standard: ${formatModelArray(MODELS.FALLBACK_CHAINS.standard)},
|
|
111
|
-
fast: ${formatModelArray(MODELS.FALLBACK_CHAINS.fast)}
|
|
112
|
-
},
|
|
113
|
-
preferSameProvider: true,
|
|
114
|
-
respectTierCeiling: true,
|
|
115
|
-
nuclearFallback: {
|
|
116
|
-
enabled: false,
|
|
117
|
-
model: '${MODELS.NUCLEAR_FALLBACK}',
|
|
118
|
-
maxRetriesBeforeNuclear: ${MODELS.NUCLEAR_MAX_RETRIES}
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
routing: {
|
|
123
|
-
rules: [
|
|
124
|
-
{
|
|
125
|
-
workType: 'feature-dev',
|
|
126
|
-
agents: ['@${agents[0]?.name || 'coordinator'}'],
|
|
127
|
-
confidence: 'high'
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
workType: 'bug-fix',
|
|
131
|
-
agents: ['@${agents.find(a => a.role === 'developer')?.name || agents[0]?.name || 'coordinator'}'],
|
|
132
|
-
confidence: 'high'
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
workType: 'testing',
|
|
136
|
-
agents: ['@${agents.find(a => a.role === 'tester')?.name || agents[0]?.name || 'coordinator'}'],
|
|
137
|
-
confidence: 'high'
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
workType: 'documentation',
|
|
141
|
-
agents: ['@${agents.find(a => a.role === 'scribe')?.name || agents[0]?.name || 'coordinator'}'],
|
|
142
|
-
confidence: 'high'
|
|
143
|
-
}
|
|
144
|
-
],
|
|
145
|
-
governance: {
|
|
146
|
-
eagerByDefault: true,
|
|
147
|
-
scribeAutoRuns: false,
|
|
148
|
-
allowRecursiveSpawn: false
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
casting: {
|
|
153
|
-
allowlistUniverses: [
|
|
154
|
-
'The Usual Suspects',
|
|
155
|
-
'Breaking Bad',
|
|
156
|
-
'The Wire',
|
|
157
|
-
'Firefly'
|
|
158
|
-
],
|
|
159
|
-
overflowStrategy: 'generic',
|
|
160
|
-
universeCapacity: {}
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
platforms: {
|
|
164
|
-
vscode: {
|
|
165
|
-
disableModelSelection: false,
|
|
166
|
-
scribeMode: 'sync'
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
export default config;
|
|
96
|
+
return `import type { SquadConfig } from '@bradygaster/squad';
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Squad Configuration for ${projectName}
|
|
100
|
+
* ${projectDescription ? `\n * ${projectDescription}` : ''}
|
|
101
|
+
*/
|
|
102
|
+
const config: SquadConfig = {
|
|
103
|
+
version: '1.0.0',
|
|
104
|
+
|
|
105
|
+
models: {
|
|
106
|
+
defaultModel: '${MODELS.DEFAULT}',
|
|
107
|
+
defaultTier: 'standard',
|
|
108
|
+
fallbackChains: {
|
|
109
|
+
premium: ${formatModelArray(MODELS.FALLBACK_CHAINS.premium)},
|
|
110
|
+
standard: ${formatModelArray(MODELS.FALLBACK_CHAINS.standard)},
|
|
111
|
+
fast: ${formatModelArray(MODELS.FALLBACK_CHAINS.fast)}
|
|
112
|
+
},
|
|
113
|
+
preferSameProvider: true,
|
|
114
|
+
respectTierCeiling: true,
|
|
115
|
+
nuclearFallback: {
|
|
116
|
+
enabled: false,
|
|
117
|
+
model: '${MODELS.NUCLEAR_FALLBACK}',
|
|
118
|
+
maxRetriesBeforeNuclear: ${MODELS.NUCLEAR_MAX_RETRIES}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
routing: {
|
|
123
|
+
rules: [
|
|
124
|
+
{
|
|
125
|
+
workType: 'feature-dev',
|
|
126
|
+
agents: ['@${agents[0]?.name || 'coordinator'}'],
|
|
127
|
+
confidence: 'high'
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
workType: 'bug-fix',
|
|
131
|
+
agents: ['@${agents.find(a => a.role === 'developer')?.name || agents[0]?.name || 'coordinator'}'],
|
|
132
|
+
confidence: 'high'
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
workType: 'testing',
|
|
136
|
+
agents: ['@${agents.find(a => a.role === 'tester')?.name || agents[0]?.name || 'coordinator'}'],
|
|
137
|
+
confidence: 'high'
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
workType: 'documentation',
|
|
141
|
+
agents: ['@${agents.find(a => a.role === 'scribe')?.name || agents[0]?.name || 'coordinator'}'],
|
|
142
|
+
confidence: 'high'
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
governance: {
|
|
146
|
+
eagerByDefault: true,
|
|
147
|
+
scribeAutoRuns: false,
|
|
148
|
+
allowRecursiveSpawn: false
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
casting: {
|
|
153
|
+
allowlistUniverses: [
|
|
154
|
+
'The Usual Suspects',
|
|
155
|
+
'Breaking Bad',
|
|
156
|
+
'The Wire',
|
|
157
|
+
'Firefly'
|
|
158
|
+
],
|
|
159
|
+
overflowStrategy: 'generic',
|
|
160
|
+
universeCapacity: {}
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
platforms: {
|
|
164
|
+
vscode: {
|
|
165
|
+
disableModelSelection: false,
|
|
166
|
+
scribeMode: 'sync'
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export default config;
|
|
172
172
|
`;
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
@@ -242,6 +242,42 @@ function generateJsonConfig(options) {
|
|
|
242
242
|
};
|
|
243
243
|
return JSON.stringify(config, null, 2);
|
|
244
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Generate SDK builder config file content (new defineSquad() format).
|
|
247
|
+
*/
|
|
248
|
+
function generateSDKBuilderConfig(options) {
|
|
249
|
+
const { projectName, projectDescription, agents } = options;
|
|
250
|
+
// Generate imports
|
|
251
|
+
let code = `import {\n defineSquad,\n defineTeam,\n defineAgent,\n} from '@bradygaster/squad-sdk';\n\n`;
|
|
252
|
+
code += `/**\n * Squad Configuration — ${projectName}\n`;
|
|
253
|
+
if (projectDescription) {
|
|
254
|
+
code += ` *\n * ${projectDescription}\n`;
|
|
255
|
+
}
|
|
256
|
+
code += ` */\n`;
|
|
257
|
+
// Generate agent definitions
|
|
258
|
+
for (const agent of agents) {
|
|
259
|
+
const displayName = agent.displayName || titleCase(agent.name);
|
|
260
|
+
code += `const ${agent.name} = defineAgent({\n`;
|
|
261
|
+
code += ` name: '${agent.name}',\n`;
|
|
262
|
+
code += ` role: '${agent.role}',\n`;
|
|
263
|
+
code += ` description: '${displayName}',\n`;
|
|
264
|
+
code += ` status: 'active',\n`;
|
|
265
|
+
code += `});\n\n`;
|
|
266
|
+
}
|
|
267
|
+
// Generate squad config
|
|
268
|
+
code += `export default defineSquad({\n`;
|
|
269
|
+
code += ` version: '1.0.0',\n\n`;
|
|
270
|
+
code += ` team: defineTeam({\n`;
|
|
271
|
+
code += ` name: '${projectName}',\n`;
|
|
272
|
+
if (projectDescription) {
|
|
273
|
+
code += ` description: '${projectDescription.replace(/'/g, "\\'")}',\n`;
|
|
274
|
+
}
|
|
275
|
+
code += ` members: [${agents.map(a => `'${a.name}'`).join(', ')}],\n`;
|
|
276
|
+
code += ` }),\n\n`;
|
|
277
|
+
code += ` agents: [${agents.map(a => a.name).join(', ')}],\n`;
|
|
278
|
+
code += `});\n`;
|
|
279
|
+
return code;
|
|
280
|
+
}
|
|
245
281
|
// ============================================================================
|
|
246
282
|
// Agent Template Generation
|
|
247
283
|
// ============================================================================
|
|
@@ -252,26 +288,26 @@ function generateCharter(agent, projectName, projectDescription) {
|
|
|
252
288
|
const template = AGENT_TEMPLATES[agent.role];
|
|
253
289
|
const displayName = agent.displayName || template?.displayName || titleCase(agent.name);
|
|
254
290
|
const description = template?.description || 'Team member focused on their assigned responsibilities.';
|
|
255
|
-
return `# ${displayName} — ${titleCase(agent.role)}
|
|
256
|
-
|
|
257
|
-
${description}
|
|
258
|
-
|
|
259
|
-
## Project Context
|
|
260
|
-
|
|
261
|
-
**Project:** ${projectName}
|
|
262
|
-
${projectDescription ? `**Description:** ${projectDescription}\n` : ''}
|
|
263
|
-
|
|
264
|
-
## Responsibilities
|
|
265
|
-
|
|
266
|
-
- Collaborate with team members on assigned work
|
|
267
|
-
- Maintain code quality and project standards
|
|
268
|
-
- Document decisions and progress in history
|
|
269
|
-
|
|
270
|
-
## Work Style
|
|
271
|
-
|
|
272
|
-
- Read project context and team decisions before starting work
|
|
273
|
-
- Communicate clearly with team members
|
|
274
|
-
- Follow established patterns and conventions
|
|
291
|
+
return `# ${displayName} — ${titleCase(agent.role)}
|
|
292
|
+
|
|
293
|
+
${description}
|
|
294
|
+
|
|
295
|
+
## Project Context
|
|
296
|
+
|
|
297
|
+
**Project:** ${projectName}
|
|
298
|
+
${projectDescription ? `**Description:** ${projectDescription}\n` : ''}
|
|
299
|
+
|
|
300
|
+
## Responsibilities
|
|
301
|
+
|
|
302
|
+
- Collaborate with team members on assigned work
|
|
303
|
+
- Maintain code quality and project standards
|
|
304
|
+
- Document decisions and progress in history
|
|
305
|
+
|
|
306
|
+
## Work Style
|
|
307
|
+
|
|
308
|
+
- Read project context and team decisions before starting work
|
|
309
|
+
- Communicate clearly with team members
|
|
310
|
+
- Follow established patterns and conventions
|
|
275
311
|
`;
|
|
276
312
|
}
|
|
277
313
|
/**
|
|
@@ -280,22 +316,22 @@ ${projectDescription ? `**Description:** ${projectDescription}\n` : ''}
|
|
|
280
316
|
function generateInitialHistory(agent, projectName, projectDescription, userName) {
|
|
281
317
|
const displayName = agent.displayName || AGENT_TEMPLATES[agent.role]?.displayName || titleCase(agent.name);
|
|
282
318
|
const now = new Date().toISOString().split('T')[0];
|
|
283
|
-
return `# Project Context
|
|
284
|
-
|
|
285
|
-
${userName ? `- **Owner:** ${userName}\n` : ''}- **Project:** ${projectName}
|
|
286
|
-
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${now}
|
|
287
|
-
|
|
288
|
-
## Core Context
|
|
289
|
-
|
|
290
|
-
Agent ${displayName} initialized and ready for work.
|
|
291
|
-
|
|
292
|
-
## Recent Updates
|
|
293
|
-
|
|
294
|
-
📌 Team initialized on ${now}
|
|
295
|
-
|
|
296
|
-
## Learnings
|
|
297
|
-
|
|
298
|
-
Initial setup complete.
|
|
319
|
+
return `# Project Context
|
|
320
|
+
|
|
321
|
+
${userName ? `- **Owner:** ${userName}\n` : ''}- **Project:** ${projectName}
|
|
322
|
+
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${now}
|
|
323
|
+
|
|
324
|
+
## Core Context
|
|
325
|
+
|
|
326
|
+
Agent ${displayName} initialized and ready for work.
|
|
327
|
+
|
|
328
|
+
## Recent Updates
|
|
329
|
+
|
|
330
|
+
📌 Team initialized on ${now}
|
|
331
|
+
|
|
332
|
+
## Learnings
|
|
333
|
+
|
|
334
|
+
Initial setup complete.
|
|
299
335
|
`;
|
|
300
336
|
}
|
|
301
337
|
/**
|
|
@@ -327,7 +363,7 @@ function stampVersionInContent(content, version) {
|
|
|
327
363
|
* - .gitignore entries for logs
|
|
328
364
|
* - .github/agents/squad.agent.md
|
|
329
365
|
* - .github/workflows/ (optional)
|
|
330
|
-
* - .squad
|
|
366
|
+
* - .squad/templates/ (optional)
|
|
331
367
|
* - .copilot/mcp-config.json (optional)
|
|
332
368
|
* - Identity files (now.md, wisdom.md)
|
|
333
369
|
* - ceremonies.md
|
|
@@ -335,6 +371,16 @@ function stampVersionInContent(content, version) {
|
|
|
335
371
|
* @param options - Initialization options
|
|
336
372
|
* @returns Result with created file paths
|
|
337
373
|
*/
|
|
374
|
+
/**
|
|
375
|
+
* Workflow files that are part of the Squad framework and should always be installed.
|
|
376
|
+
* Other workflows in templates/workflows/ are generic CI/CD scaffolding and are opt-in.
|
|
377
|
+
*/
|
|
378
|
+
const FRAMEWORK_WORKFLOWS = [
|
|
379
|
+
'squad-heartbeat.yml',
|
|
380
|
+
'squad-issue-assign.yml',
|
|
381
|
+
'squad-triage.yml',
|
|
382
|
+
'sync-squad-labels.yml',
|
|
383
|
+
];
|
|
338
384
|
export async function initSquad(options) {
|
|
339
385
|
const { teamRoot, projectName, projectDescription, agents, configFormat = 'typescript', userName, skipExisting = true, includeWorkflows = true, includeTemplates = true, includeMcpConfig = true, projectType = 'unknown', version = '0.0.0', } = options;
|
|
340
386
|
const createdFiles = [];
|
|
@@ -425,12 +471,21 @@ export async function initSquad(options) {
|
|
|
425
471
|
// -------------------------------------------------------------------------
|
|
426
472
|
// Create configuration file
|
|
427
473
|
// -------------------------------------------------------------------------
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
?
|
|
432
|
-
|
|
433
|
-
|
|
474
|
+
// When configFormat is 'markdown', skip config file generation entirely
|
|
475
|
+
let configPath;
|
|
476
|
+
if (configFormat !== 'markdown') {
|
|
477
|
+
const configFileName = configFormat === 'sdk' ? 'squad.config.ts' :
|
|
478
|
+
configFormat === 'typescript' ? 'squad.config.ts' : 'squad.config.json';
|
|
479
|
+
configPath = join(teamRoot, configFileName);
|
|
480
|
+
const configContent = configFormat === 'sdk' ? generateSDKBuilderConfig(options) :
|
|
481
|
+
configFormat === 'typescript' ? generateTypeScriptConfig(options) :
|
|
482
|
+
generateJsonConfig(options);
|
|
483
|
+
await writeIfNotExists(configPath, configContent);
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
// No config file for markdown-only mode
|
|
487
|
+
configPath = '';
|
|
488
|
+
}
|
|
434
489
|
// -------------------------------------------------------------------------
|
|
435
490
|
// Create agent directories and files
|
|
436
491
|
// -------------------------------------------------------------------------
|
|
@@ -454,27 +509,27 @@ export async function initSquad(options) {
|
|
|
454
509
|
const identityDir = join(squadDir, 'identity');
|
|
455
510
|
const nowMdPath = join(identityDir, 'now.md');
|
|
456
511
|
const wisdomMdPath = join(identityDir, 'wisdom.md');
|
|
457
|
-
const nowContent = `---
|
|
458
|
-
updated_at: ${new Date().toISOString()}
|
|
459
|
-
focus_area: Initial setup
|
|
460
|
-
active_issues: []
|
|
461
|
-
---
|
|
462
|
-
|
|
463
|
-
# What We're Focused On
|
|
464
|
-
|
|
465
|
-
Getting started. Updated by coordinator at session start.
|
|
512
|
+
const nowContent = `---
|
|
513
|
+
updated_at: ${new Date().toISOString()}
|
|
514
|
+
focus_area: Initial setup
|
|
515
|
+
active_issues: []
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
# What We're Focused On
|
|
519
|
+
|
|
520
|
+
Getting started. Updated by coordinator at session start.
|
|
466
521
|
`;
|
|
467
|
-
const wisdomContent = `---
|
|
468
|
-
last_updated: ${new Date().toISOString()}
|
|
469
|
-
---
|
|
470
|
-
|
|
471
|
-
# Team Wisdom
|
|
472
|
-
|
|
473
|
-
Reusable patterns and heuristics learned through work. NOT transcripts — each entry is a distilled, actionable insight.
|
|
474
|
-
|
|
475
|
-
## Patterns
|
|
476
|
-
|
|
477
|
-
<!-- Append entries below. Format: **Pattern:** description. **Context:** when it applies. -->
|
|
522
|
+
const wisdomContent = `---
|
|
523
|
+
last_updated: ${new Date().toISOString()}
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
# Team Wisdom
|
|
527
|
+
|
|
528
|
+
Reusable patterns and heuristics learned through work. NOT transcripts — each entry is a distilled, actionable insight.
|
|
529
|
+
|
|
530
|
+
## Patterns
|
|
531
|
+
|
|
532
|
+
<!-- Append entries below. Format: **Pattern:** description. **Context:** when it applies. -->
|
|
478
533
|
`;
|
|
479
534
|
await writeIfNotExists(nowMdPath, nowContent);
|
|
480
535
|
await writeIfNotExists(wisdomMdPath, wisdomContent);
|
|
@@ -489,42 +544,42 @@ Reusable patterns and heuristics learned through work. NOT transcripts — each
|
|
|
489
544
|
// Create decisions.md (canonical location at squad root)
|
|
490
545
|
// -------------------------------------------------------------------------
|
|
491
546
|
const decisionsPath = join(squadDir, 'decisions.md');
|
|
492
|
-
const decisionsContent = `# Squad Decisions
|
|
493
|
-
|
|
494
|
-
## Active Decisions
|
|
495
|
-
|
|
496
|
-
No decisions recorded yet.
|
|
497
|
-
|
|
498
|
-
## Governance
|
|
499
|
-
|
|
500
|
-
- All meaningful changes require team consensus
|
|
501
|
-
- Document architectural decisions here
|
|
502
|
-
- Keep history focused on work, decisions focused on direction
|
|
547
|
+
const decisionsContent = `# Squad Decisions
|
|
548
|
+
|
|
549
|
+
## Active Decisions
|
|
550
|
+
|
|
551
|
+
No decisions recorded yet.
|
|
552
|
+
|
|
553
|
+
## Governance
|
|
554
|
+
|
|
555
|
+
- All meaningful changes require team consensus
|
|
556
|
+
- Document architectural decisions here
|
|
557
|
+
- Keep history focused on work, decisions focused on direction
|
|
503
558
|
`;
|
|
504
559
|
await writeIfNotExists(decisionsPath, decisionsContent);
|
|
505
560
|
// -------------------------------------------------------------------------
|
|
506
561
|
// Create team.md (required by shell lifecycle)
|
|
507
562
|
// -------------------------------------------------------------------------
|
|
508
563
|
const teamPath = join(squadDir, 'team.md');
|
|
509
|
-
const teamContent = `# Squad Team
|
|
510
|
-
|
|
511
|
-
> ${projectDescription || projectName}
|
|
512
|
-
|
|
513
|
-
## Coordinator
|
|
514
|
-
|
|
515
|
-
| Name | Role | Notes |
|
|
516
|
-
|------|------|-------|
|
|
517
|
-
| Squad | Coordinator | Routes work, enforces handoffs and reviewer gates. |
|
|
518
|
-
|
|
519
|
-
## Members
|
|
520
|
-
|
|
521
|
-
| Name | Role | Charter | Status |
|
|
522
|
-
|------|------|---------|--------|
|
|
523
|
-
|
|
524
|
-
## Project Context
|
|
525
|
-
|
|
526
|
-
- **Project:** ${projectName}
|
|
527
|
-
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${new Date().toISOString().split('T')[0]}
|
|
564
|
+
const teamContent = `# Squad Team
|
|
565
|
+
|
|
566
|
+
> ${projectDescription || projectName}
|
|
567
|
+
|
|
568
|
+
## Coordinator
|
|
569
|
+
|
|
570
|
+
| Name | Role | Notes |
|
|
571
|
+
|------|------|-------|
|
|
572
|
+
| Squad | Coordinator | Routes work, enforces handoffs and reviewer gates. |
|
|
573
|
+
|
|
574
|
+
## Members
|
|
575
|
+
|
|
576
|
+
| Name | Role | Charter | Status |
|
|
577
|
+
|------|------|---------|--------|
|
|
578
|
+
|
|
579
|
+
## Project Context
|
|
580
|
+
|
|
581
|
+
- **Project:** ${projectName}
|
|
582
|
+
${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Created:** ${new Date().toISOString().split('T')[0]}
|
|
528
583
|
`;
|
|
529
584
|
await writeIfNotExists(teamPath, teamContent);
|
|
530
585
|
// -------------------------------------------------------------------------
|
|
@@ -535,17 +590,17 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
535
590
|
await copyIfNotExists(join(templatesDir, 'routing.md'), routingPath);
|
|
536
591
|
}
|
|
537
592
|
else {
|
|
538
|
-
const routingContent = `# Squad Routing
|
|
539
|
-
|
|
540
|
-
## Work Type Rules
|
|
541
|
-
|
|
542
|
-
| Work Type | Primary Agent | Fallback |
|
|
543
|
-
|-----------|---------------|----------|
|
|
544
|
-
|
|
545
|
-
## Governance
|
|
546
|
-
|
|
547
|
-
- Route based on work type and agent expertise
|
|
548
|
-
- Update this file as team capabilities evolve
|
|
593
|
+
const routingContent = `# Squad Routing
|
|
594
|
+
|
|
595
|
+
## Work Type Rules
|
|
596
|
+
|
|
597
|
+
| Work Type | Primary Agent | Fallback |
|
|
598
|
+
|-----------|---------------|----------|
|
|
599
|
+
|
|
600
|
+
## Governance
|
|
601
|
+
|
|
602
|
+
- Route based on work type and agent expertise
|
|
603
|
+
- Update this file as team capabilities evolve
|
|
549
604
|
`;
|
|
550
605
|
await writeIfNotExists(routingPath, routingContent);
|
|
551
606
|
}
|
|
@@ -584,12 +639,16 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
584
639
|
createdFiles.push(toRelativePath(gitattributesPath));
|
|
585
640
|
}
|
|
586
641
|
// -------------------------------------------------------------------------
|
|
587
|
-
// Create .gitignore entries for logs
|
|
642
|
+
// Create .gitignore entries for runtime state (logs, inbox, sessions)
|
|
643
|
+
// These paths are written during normal squad operation but should not be
|
|
644
|
+
// committed to version control (they are runtime state).
|
|
588
645
|
// -------------------------------------------------------------------------
|
|
589
646
|
const gitignorePath = join(teamRoot, '.gitignore');
|
|
590
647
|
const ignoreEntries = [
|
|
591
648
|
'.squad/orchestration-log/',
|
|
592
649
|
'.squad/log/',
|
|
650
|
+
'.squad/decisions/inbox/',
|
|
651
|
+
'.squad/sessions/',
|
|
593
652
|
];
|
|
594
653
|
let existingIgnore = '';
|
|
595
654
|
if (existsSync(gitignorePath)) {
|
|
@@ -598,7 +657,7 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
598
657
|
const missingIgnore = ignoreEntries.filter(entry => !existingIgnore.includes(entry));
|
|
599
658
|
if (missingIgnore.length > 0) {
|
|
600
659
|
const block = (existingIgnore && !existingIgnore.endsWith('\n') ? '\n' : '')
|
|
601
|
-
+ '# Squad: ignore
|
|
660
|
+
+ '# Squad: ignore runtime state (logs, inbox, sessions)\n'
|
|
602
661
|
+ missingIgnore.join('\n') + '\n';
|
|
603
662
|
await appendFile(gitignorePath, block);
|
|
604
663
|
createdFiles.push(toRelativePath(gitignorePath));
|
|
@@ -620,10 +679,10 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
620
679
|
skippedFiles.push(toRelativePath(agentFile));
|
|
621
680
|
}
|
|
622
681
|
// -------------------------------------------------------------------------
|
|
623
|
-
// Copy .squad
|
|
682
|
+
// Copy .squad/templates/ (optional)
|
|
624
683
|
// -------------------------------------------------------------------------
|
|
625
684
|
if (includeTemplates && templatesDir) {
|
|
626
|
-
const templatesDest = join(teamRoot, '.squad
|
|
685
|
+
const templatesDest = join(teamRoot, '.squad', 'templates');
|
|
627
686
|
if (!existsSync(templatesDest)) {
|
|
628
687
|
cpSync(templatesDir, templatesDest, { recursive: true });
|
|
629
688
|
createdFiles.push(toRelativePath(templatesDest));
|
|
@@ -639,7 +698,8 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
639
698
|
const workflowsSrc = join(templatesDir, 'workflows');
|
|
640
699
|
const workflowsDest = join(teamRoot, '.github', 'workflows');
|
|
641
700
|
if (statSync(workflowsSrc).isDirectory()) {
|
|
642
|
-
const
|
|
701
|
+
const allWorkflowFiles = readdirSync(workflowsSrc).filter(f => f.endsWith('.yml'));
|
|
702
|
+
const workflowFiles = allWorkflowFiles.filter(f => FRAMEWORK_WORKFLOWS.includes(f));
|
|
643
703
|
await mkdir(workflowsDest, { recursive: true });
|
|
644
704
|
for (const file of workflowFiles) {
|
|
645
705
|
const destFile = join(workflowsDest, file);
|
|
@@ -680,6 +740,34 @@ ${projectDescription ? `- **Description:** ${projectDescription}\n` : ''}- **Cre
|
|
|
680
740
|
}
|
|
681
741
|
}
|
|
682
742
|
// -------------------------------------------------------------------------
|
|
743
|
+
// Generate .squad/workstreams.json (when streams provided)
|
|
744
|
+
// -------------------------------------------------------------------------
|
|
745
|
+
if (options.streams && options.streams.length > 0) {
|
|
746
|
+
const workstreamsConfig = {
|
|
747
|
+
workstreams: options.streams,
|
|
748
|
+
defaultWorkflow: 'branch-per-issue',
|
|
749
|
+
};
|
|
750
|
+
const workstreamsPath = join(squadDir, 'workstreams.json');
|
|
751
|
+
await writeIfNotExists(workstreamsPath, JSON.stringify(workstreamsConfig, null, 2) + '\n');
|
|
752
|
+
}
|
|
753
|
+
// -------------------------------------------------------------------------
|
|
754
|
+
// Add .squad-workstream to .gitignore
|
|
755
|
+
// -------------------------------------------------------------------------
|
|
756
|
+
{
|
|
757
|
+
const workstreamIgnoreEntry = '.squad-workstream';
|
|
758
|
+
let currentIgnore = '';
|
|
759
|
+
if (existsSync(gitignorePath)) {
|
|
760
|
+
currentIgnore = readFileSync(gitignorePath, 'utf-8');
|
|
761
|
+
}
|
|
762
|
+
if (!currentIgnore.includes(workstreamIgnoreEntry)) {
|
|
763
|
+
const block = (currentIgnore && !currentIgnore.endsWith('\n') ? '\n' : '')
|
|
764
|
+
+ '# Squad: workstream activation file (local to this machine)\n'
|
|
765
|
+
+ workstreamIgnoreEntry + '\n';
|
|
766
|
+
await appendFile(gitignorePath, block);
|
|
767
|
+
createdFiles.push(toRelativePath(gitignorePath));
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
// -------------------------------------------------------------------------
|
|
683
771
|
// Create .first-run marker
|
|
684
772
|
// -------------------------------------------------------------------------
|
|
685
773
|
const firstRunMarker = join(squadDir, '.first-run');
|