cc-codeconductor 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -6
- package/dist/index.js +674 -65
- package/package.json +1 -1
- package/presets/agy/AGENTS.md +24 -0
- package/presets/agy/workflows/cc-pipeline.md +69 -0
- package/presets/codex/AGENTS.md +34 -0
- package/presets/laravel-tall/agents/architect.md +8 -0
- package/presets/laravel-tall/agents/implementer.md +12 -0
- package/presets/laravel-tall/laravel-tall.yml +38 -0
- package/presets/opencode/agents/architect.md +154 -61
- package/presets/opencode/agents/docs.md +126 -40
- package/presets/opencode/agents/implementer.md +100 -38
- package/presets/opencode/agents/orchestrator.md +41 -60
- package/presets/opencode/agents/repo-explorer.md +1 -1
- package/presets/opencode/agents/reviewer.md +142 -74
- package/presets/opencode/agents/task-coach.md +111 -59
- package/presets/opencode/prompts/v0.4.0/architect.md +221 -0
- package/presets/opencode/prompts/v0.4.0/complexity-auditor.md +89 -0
- package/presets/opencode/prompts/v0.4.0/docs.md +189 -0
- package/presets/opencode/prompts/v0.4.0/implementer.md +162 -0
- package/presets/opencode/prompts/v0.4.0/orchestrator.md +348 -0
- package/presets/opencode/prompts/v0.4.0/repo-explorer.md +110 -0
- package/presets/opencode/prompts/v0.4.0/reviewer.md +225 -0
- package/presets/opencode/prompts/v0.4.0/task-coach.md +155 -0
- package/presets/opencode/prompts/v0.4.0/tester.md +251 -0
- package/presets/opencode/skills/auth-token-inspector/SKILL.md +31 -0
- package/presets/opencode/skills/drizzle-schema-architect/SKILL.md +51 -0
- package/presets/opencode/skills/fastapi-pydantic-strict/SKILL.md +44 -0
- package/presets/opencode/skills/jpa-nplusone-detector/SKILL.md +46 -0
- package/presets/opencode/skills/livewire-alpine-bridge/SKILL.md +36 -0
- package/presets/opencode/skills/seo-analytics-injector/SKILL.md +44 -0
- package/presets/opencode/skills/spring-auth-auditor/SKILL.md +30 -0
- package/presets/opencode/skills/tailwind-responsive-auditor/SKILL.md +30 -0
- package/presets/opencode/skills/tdd-mutation-tester/SKILL.md +28 -0
- package/presets/python-data-api/agents/architect.md +8 -0
- package/presets/python-data-api/agents/implementer.md +9 -0
- package/presets/python-data-api/python-data-api.yml +37 -0
- package/presets/spring-kotlin-jpa/agents/architect.md +8 -0
- package/presets/spring-kotlin-jpa/agents/implementer.md +9 -0
- package/presets/spring-kotlin-jpa/spring-kotlin-jpa.yml +38 -0
- package/presets/ts-next-drizzle/agents/architect.md +8 -0
- package/presets/ts-next-drizzle/agents/implementer.md +10 -0
- package/presets/ts-next-drizzle/ts-next-drizzle.yml +41 -0
- package/src/presets/manifests/agy.yml +2 -2
- package/src/presets/manifests/claude.yml +2 -2
- package/src/presets/manifests/codex.yml +2 -2
- package/src/presets/manifests/cursor.yml +2 -2
- package/src/presets/manifests/gemini.yml +2 -2
- package/src/presets/manifests/opencode.yml +2 -2
- package/src/presets/models/agy.yml +7 -0
- package/src/presets/models/claude.yml +6 -0
- package/src/presets/models/codex.yml +6 -0
- package/src/presets/models/cursor.yml +6 -0
- package/src/presets/models/gemini.yml +6 -0
- package/src/presets/models/opencode.yml +6 -0
package/dist/index.js
CHANGED
|
@@ -11126,7 +11126,7 @@ function validateCouncilSpec(data) {
|
|
|
11126
11126
|
function validateConfig(data) {
|
|
11127
11127
|
return CodeConductorConfigSchema.parse(data);
|
|
11128
11128
|
}
|
|
11129
|
-
var CouncilAgentSpecSchema, CouncilSpecSchema, ProjectProfileSchema, CompileCheckConfigSchema, LoopConfigSchema, CodeConductorConfigSchema, RunnerTargetSchema, InstallStrategySchema, ManifestEntrySchema, InstallManifestSchema, ToolProviderNamesSchema, PermissionProviderNamesSchema, ModelConfigSchema, ContractTargetSchema, ContractFormatSchema, AgentContractSchema, CouncilFindingSchema, CouncilVerdictInputSchema, ConsensusConfigSchema, CouncilVerdictSchema, ClaudeAgentFileSchema, OpenCodeAgentFileSchema, SentryStackFrameSchema, SentryWebhookSchema;
|
|
11129
|
+
var CouncilAgentSpecSchema, CouncilSpecSchema, ProjectProfileSchema, CompileCheckConfigSchema, LoopConfigSchema, CodeConductorConfigSchema, RunnerTargetSchema, InstallStrategySchema, ManifestEntrySchema, InstallManifestSchema, ToolProviderNamesSchema, PermissionProviderNamesSchema, ModelConfigSchema, ContractTargetSchema, ContractFormatSchema, AgentContractSchema, CouncilFindingSchema, CouncilVerdictInputSchema, ConsensusConfigSchema, CouncilVerdictSchema, ClaudeAgentFileSchema, OpenCodeAgentFileSchema, SentryStackFrameSchema, SentryWebhookSchema, MemoryPointerSchema, MemoryIndexSchema, GoalTaskSchema, GoalGraphSchema;
|
|
11130
11130
|
var init_schemas = __esm(() => {
|
|
11131
11131
|
init_zod();
|
|
11132
11132
|
CouncilAgentSpecSchema = exports_external.object({
|
|
@@ -11167,7 +11167,11 @@ var init_schemas = __esm(() => {
|
|
|
11167
11167
|
LoopConfigSchema = exports_external.object({
|
|
11168
11168
|
enabled: exports_external.boolean().optional().default(true),
|
|
11169
11169
|
maxIterations: exports_external.number().int().positive().optional().default(3),
|
|
11170
|
-
maxTokenBudget: exports_external.number().nonnegative().optional().default(0)
|
|
11170
|
+
maxTokenBudget: exports_external.number().nonnegative().optional().default(0),
|
|
11171
|
+
compaction: exports_external.object({
|
|
11172
|
+
enabled: exports_external.boolean().optional().default(true),
|
|
11173
|
+
historyFile: exports_external.string().optional()
|
|
11174
|
+
}).optional()
|
|
11171
11175
|
});
|
|
11172
11176
|
CodeConductorConfigSchema = exports_external.object({
|
|
11173
11177
|
version: exports_external.string(),
|
|
@@ -11309,6 +11313,34 @@ var init_schemas = __esm(() => {
|
|
|
11309
11313
|
environment: exports_external.string().optional(),
|
|
11310
11314
|
release: exports_external.string().optional()
|
|
11311
11315
|
});
|
|
11316
|
+
MemoryPointerSchema = exports_external.object({
|
|
11317
|
+
topic_key: exports_external.string().min(1).max(128),
|
|
11318
|
+
id: exports_external.number().int().positive(),
|
|
11319
|
+
file: exports_external.string().min(1),
|
|
11320
|
+
summary: exports_external.string().min(1).max(200),
|
|
11321
|
+
timestamp: exports_external.string().datetime(),
|
|
11322
|
+
tags: exports_external.array(exports_external.string().max(64)).max(10).optional().default([])
|
|
11323
|
+
});
|
|
11324
|
+
MemoryIndexSchema = exports_external.object({
|
|
11325
|
+
version: exports_external.literal(1),
|
|
11326
|
+
pointers: exports_external.array(MemoryPointerSchema)
|
|
11327
|
+
});
|
|
11328
|
+
GoalTaskSchema = exports_external.object({
|
|
11329
|
+
id: exports_external.string(),
|
|
11330
|
+
title: exports_external.string(),
|
|
11331
|
+
type: exports_external.enum(["feature", "fix", "refactor", "test", "docs"]),
|
|
11332
|
+
risk: exports_external.enum(["low", "medium", "high"]),
|
|
11333
|
+
status: exports_external.enum(["pending", "in-progress", "done", "blocked"]),
|
|
11334
|
+
depends_on: exports_external.array(exports_external.string()).optional().default([]),
|
|
11335
|
+
acceptance_criteria: exports_external.array(exports_external.string()),
|
|
11336
|
+
blocked_reason: exports_external.string().optional(),
|
|
11337
|
+
context_scope: exports_external.enum(["isolated", "continuation", "full"]).optional().default("isolated")
|
|
11338
|
+
});
|
|
11339
|
+
GoalGraphSchema = exports_external.object({
|
|
11340
|
+
objective: exports_external.string(),
|
|
11341
|
+
tasks: exports_external.array(GoalTaskSchema),
|
|
11342
|
+
created_at: exports_external.string()
|
|
11343
|
+
});
|
|
11312
11344
|
});
|
|
11313
11345
|
|
|
11314
11346
|
// src/core/presets/package-paths.ts
|
|
@@ -12134,7 +12166,7 @@ init_errors();
|
|
|
12134
12166
|
// package.json
|
|
12135
12167
|
var package_default = {
|
|
12136
12168
|
name: "cc-codeconductor",
|
|
12137
|
-
version: "0.4.
|
|
12169
|
+
version: "0.4.3",
|
|
12138
12170
|
description: "A multi-agent orchestration framework for AI-assisted software engineering workflows.",
|
|
12139
12171
|
keywords: [
|
|
12140
12172
|
"ai",
|
|
@@ -13056,7 +13088,8 @@ function renderTemplate(content, modelConfig, filePath, locale = "en") {
|
|
|
13056
13088
|
"tester",
|
|
13057
13089
|
"reviewer",
|
|
13058
13090
|
"docs",
|
|
13059
|
-
"repo-explorer"
|
|
13091
|
+
"repo-explorer",
|
|
13092
|
+
"goal-planner"
|
|
13060
13093
|
];
|
|
13061
13094
|
let result = templatedContent;
|
|
13062
13095
|
for (const role of knownRoles) {
|
|
@@ -13144,8 +13177,20 @@ function injectMcpServers(jsonString, filePath) {
|
|
|
13144
13177
|
if (isClaudeSettings || isAgyMcpConfig) {
|
|
13145
13178
|
obj.mcpServers = mergeDeep(obj.mcpServers || {}, mcpServers);
|
|
13146
13179
|
} else if (isOpencodeJsonc) {
|
|
13147
|
-
|
|
13148
|
-
|
|
13180
|
+
const opencodeMcp = {};
|
|
13181
|
+
for (const [key, server] of Object.entries(mcpServers)) {
|
|
13182
|
+
const commandArray = typeof server.command === "string" ? [server.command, ...server.args || []] : server.command;
|
|
13183
|
+
const formattedServer = {
|
|
13184
|
+
type: "local",
|
|
13185
|
+
command: commandArray,
|
|
13186
|
+
enabled: true
|
|
13187
|
+
};
|
|
13188
|
+
if (server.env) {
|
|
13189
|
+
formattedServer.environment = server.env;
|
|
13190
|
+
}
|
|
13191
|
+
opencodeMcp[key] = formattedServer;
|
|
13192
|
+
}
|
|
13193
|
+
obj.mcp = mergeDeep(obj.mcp || {}, opencodeMcp);
|
|
13149
13194
|
}
|
|
13150
13195
|
return JSON.stringify(obj, null, 2);
|
|
13151
13196
|
} catch {
|
|
@@ -13887,7 +13932,7 @@ async function writeConfig(projectRoot, config = {}, force = false) {
|
|
|
13887
13932
|
init_package_paths();
|
|
13888
13933
|
|
|
13889
13934
|
// src/core/presets/preset-resolver.ts
|
|
13890
|
-
var CURRENT_PRESET_VERSION = "v0.
|
|
13935
|
+
var CURRENT_PRESET_VERSION = "v0.4.0";
|
|
13891
13936
|
function resolvePreset(target, profile) {
|
|
13892
13937
|
const stack = resolveStack(profile);
|
|
13893
13938
|
const isMonorepo = profile.signals.some((s) => [
|
|
@@ -13950,17 +13995,17 @@ function resolveStack(profile) {
|
|
|
13950
13995
|
function resolveAssets(target) {
|
|
13951
13996
|
switch (target) {
|
|
13952
13997
|
case "opencode":
|
|
13953
|
-
return ["opencode.jsonc", "agents", "commands", "prompts/v0.
|
|
13998
|
+
return ["opencode.jsonc", "agents", "commands", "prompts/v0.4.0", "skills"];
|
|
13954
13999
|
case "claude":
|
|
13955
|
-
return ["CLAUDE.md", "settings.json", "commands", "skills", "agents", "prompts/v0.
|
|
14000
|
+
return ["CLAUDE.md", "settings.json", "commands", "skills", "agents", "prompts/v0.4.0"];
|
|
13956
14001
|
case "codex":
|
|
13957
|
-
return ["AGENTS.md", "skills", "prompts/v0.
|
|
14002
|
+
return ["AGENTS.md", "skills", "prompts/v0.4.0"];
|
|
13958
14003
|
case "gemini":
|
|
13959
|
-
return ["agents", "prompts/v0.
|
|
14004
|
+
return ["agents", "prompts/v0.4.0"];
|
|
13960
14005
|
case "cursor":
|
|
13961
|
-
return ["agents", "prompts/v0.
|
|
14006
|
+
return ["agents", "prompts/v0.4.0"];
|
|
13962
14007
|
case "agy":
|
|
13963
|
-
return ["AGENTS.md", "rules", "workflows", "skills", "prompts/v0.
|
|
14008
|
+
return ["AGENTS.md", "rules", "workflows", "skills", "prompts/v0.4.0"];
|
|
13964
14009
|
}
|
|
13965
14010
|
}
|
|
13966
14011
|
|
|
@@ -15080,6 +15125,522 @@ async function debtHarvestCommand(options) {
|
|
|
15080
15125
|
}
|
|
15081
15126
|
}
|
|
15082
15127
|
|
|
15128
|
+
// src/core/goal/goal-planner.ts
|
|
15129
|
+
var TEMPLATES = [
|
|
15130
|
+
{
|
|
15131
|
+
keywords: ["login", "auth", "authentication", "signin", "sign-in"],
|
|
15132
|
+
tasks: [
|
|
15133
|
+
{
|
|
15134
|
+
id: "auth-schema",
|
|
15135
|
+
title: "Define auth data model and DB schema",
|
|
15136
|
+
type: "feature",
|
|
15137
|
+
risk: "high",
|
|
15138
|
+
status: "pending",
|
|
15139
|
+
context_scope: "isolated",
|
|
15140
|
+
depends_on: [],
|
|
15141
|
+
acceptance_criteria: [
|
|
15142
|
+
"User entity with email, password_hash, created_at fields",
|
|
15143
|
+
"Migration script creates users table",
|
|
15144
|
+
"Schema supports password reset token"
|
|
15145
|
+
]
|
|
15146
|
+
},
|
|
15147
|
+
{
|
|
15148
|
+
id: "auth-api",
|
|
15149
|
+
title: "Define auth API contract",
|
|
15150
|
+
type: "feature",
|
|
15151
|
+
risk: "medium",
|
|
15152
|
+
status: "pending",
|
|
15153
|
+
context_scope: "isolated",
|
|
15154
|
+
depends_on: ["auth-schema"],
|
|
15155
|
+
acceptance_criteria: [
|
|
15156
|
+
"POST /auth/register endpoint defined",
|
|
15157
|
+
"POST /auth/login endpoint defined",
|
|
15158
|
+
"POST /auth/logout endpoint defined",
|
|
15159
|
+
"OpenAPI spec updated"
|
|
15160
|
+
]
|
|
15161
|
+
},
|
|
15162
|
+
{
|
|
15163
|
+
id: "auth-impl",
|
|
15164
|
+
title: "Implement auth endpoints",
|
|
15165
|
+
type: "feature",
|
|
15166
|
+
risk: "high",
|
|
15167
|
+
status: "pending",
|
|
15168
|
+
context_scope: "isolated",
|
|
15169
|
+
depends_on: ["auth-api"],
|
|
15170
|
+
acceptance_criteria: [
|
|
15171
|
+
"Register endpoint hashes password and stores user",
|
|
15172
|
+
"Login endpoint validates credentials and returns session",
|
|
15173
|
+
"Logout endpoint invalidates session",
|
|
15174
|
+
"Input validation on all endpoints"
|
|
15175
|
+
]
|
|
15176
|
+
},
|
|
15177
|
+
{
|
|
15178
|
+
id: "auth-tests",
|
|
15179
|
+
title: "Write auth tests",
|
|
15180
|
+
type: "test",
|
|
15181
|
+
risk: "medium",
|
|
15182
|
+
status: "pending",
|
|
15183
|
+
context_scope: "isolated",
|
|
15184
|
+
depends_on: ["auth-impl"],
|
|
15185
|
+
acceptance_criteria: [
|
|
15186
|
+
"Unit tests for password hashing",
|
|
15187
|
+
"Integration tests for register/login/logout flow",
|
|
15188
|
+
"Edge cases: duplicate email, invalid password, expired token"
|
|
15189
|
+
]
|
|
15190
|
+
}
|
|
15191
|
+
]
|
|
15192
|
+
},
|
|
15193
|
+
{
|
|
15194
|
+
keywords: ["crud", "resource", "api", "endpoint", "rest"],
|
|
15195
|
+
tasks: [
|
|
15196
|
+
{
|
|
15197
|
+
id: "crud-model",
|
|
15198
|
+
title: "Define data model and schema",
|
|
15199
|
+
type: "feature",
|
|
15200
|
+
risk: "medium",
|
|
15201
|
+
status: "pending",
|
|
15202
|
+
context_scope: "isolated",
|
|
15203
|
+
depends_on: [],
|
|
15204
|
+
acceptance_criteria: [
|
|
15205
|
+
"Entity definition with required fields",
|
|
15206
|
+
"Database migration script",
|
|
15207
|
+
"Schema follows project conventions"
|
|
15208
|
+
]
|
|
15209
|
+
},
|
|
15210
|
+
{
|
|
15211
|
+
id: "crud-service",
|
|
15212
|
+
title: "Implement repository/service layer",
|
|
15213
|
+
type: "feature",
|
|
15214
|
+
risk: "medium",
|
|
15215
|
+
status: "pending",
|
|
15216
|
+
context_scope: "isolated",
|
|
15217
|
+
depends_on: ["crud-model"],
|
|
15218
|
+
acceptance_criteria: [
|
|
15219
|
+
"Create, Read (list + by id), Update, Delete operations",
|
|
15220
|
+
"Input validation",
|
|
15221
|
+
"Error handling for not-found and conflict"
|
|
15222
|
+
]
|
|
15223
|
+
},
|
|
15224
|
+
{
|
|
15225
|
+
id: "crud-api",
|
|
15226
|
+
title: "Implement API endpoints",
|
|
15227
|
+
type: "feature",
|
|
15228
|
+
risk: "medium",
|
|
15229
|
+
status: "pending",
|
|
15230
|
+
context_scope: "isolated",
|
|
15231
|
+
depends_on: ["crud-service"],
|
|
15232
|
+
acceptance_criteria: [
|
|
15233
|
+
"REST endpoints for all CRUD operations",
|
|
15234
|
+
"Proper HTTP status codes",
|
|
15235
|
+
"Request/response schemas"
|
|
15236
|
+
]
|
|
15237
|
+
},
|
|
15238
|
+
{
|
|
15239
|
+
id: "crud-tests",
|
|
15240
|
+
title: "Write tests",
|
|
15241
|
+
type: "test",
|
|
15242
|
+
risk: "low",
|
|
15243
|
+
status: "pending",
|
|
15244
|
+
context_scope: "isolated",
|
|
15245
|
+
depends_on: ["crud-api"],
|
|
15246
|
+
acceptance_criteria: [
|
|
15247
|
+
"Unit tests for service layer",
|
|
15248
|
+
"Integration tests for API endpoints",
|
|
15249
|
+
"Edge cases covered"
|
|
15250
|
+
]
|
|
15251
|
+
}
|
|
15252
|
+
]
|
|
15253
|
+
},
|
|
15254
|
+
{
|
|
15255
|
+
keywords: ["search", "filter", "query", "full-text", "fts"],
|
|
15256
|
+
tasks: [
|
|
15257
|
+
{
|
|
15258
|
+
id: "search-schema",
|
|
15259
|
+
title: "Design search schema and indexing strategy",
|
|
15260
|
+
type: "feature",
|
|
15261
|
+
risk: "medium",
|
|
15262
|
+
status: "pending",
|
|
15263
|
+
context_scope: "isolated",
|
|
15264
|
+
depends_on: [],
|
|
15265
|
+
acceptance_criteria: [
|
|
15266
|
+
"Search index definition",
|
|
15267
|
+
"Indexing strategy documented",
|
|
15268
|
+
"Performance requirements defined"
|
|
15269
|
+
]
|
|
15270
|
+
},
|
|
15271
|
+
{
|
|
15272
|
+
id: "search-service",
|
|
15273
|
+
title: "Implement search service",
|
|
15274
|
+
type: "feature",
|
|
15275
|
+
risk: "medium",
|
|
15276
|
+
status: "pending",
|
|
15277
|
+
context_scope: "isolated",
|
|
15278
|
+
depends_on: ["search-schema"],
|
|
15279
|
+
acceptance_criteria: [
|
|
15280
|
+
"Full-text search with ranking",
|
|
15281
|
+
"Filter support",
|
|
15282
|
+
"Pagination"
|
|
15283
|
+
]
|
|
15284
|
+
},
|
|
15285
|
+
{
|
|
15286
|
+
id: "search-api",
|
|
15287
|
+
title: "Implement search API",
|
|
15288
|
+
type: "feature",
|
|
15289
|
+
risk: "low",
|
|
15290
|
+
status: "pending",
|
|
15291
|
+
context_scope: "isolated",
|
|
15292
|
+
depends_on: ["search-service"],
|
|
15293
|
+
acceptance_criteria: [
|
|
15294
|
+
"GET /search endpoint with query params",
|
|
15295
|
+
"Response includes results + metadata",
|
|
15296
|
+
"Rate limiting applied"
|
|
15297
|
+
]
|
|
15298
|
+
},
|
|
15299
|
+
{
|
|
15300
|
+
id: "search-tests",
|
|
15301
|
+
title: "Write search tests",
|
|
15302
|
+
type: "test",
|
|
15303
|
+
risk: "low",
|
|
15304
|
+
status: "pending",
|
|
15305
|
+
context_scope: "isolated",
|
|
15306
|
+
depends_on: ["search-api"],
|
|
15307
|
+
acceptance_criteria: [
|
|
15308
|
+
"Unit tests for search logic",
|
|
15309
|
+
"Integration tests with sample data",
|
|
15310
|
+
"Performance test for large datasets"
|
|
15311
|
+
]
|
|
15312
|
+
}
|
|
15313
|
+
]
|
|
15314
|
+
},
|
|
15315
|
+
{
|
|
15316
|
+
keywords: ["notification", "email", "alert", "push", "notify"],
|
|
15317
|
+
tasks: [
|
|
15318
|
+
{
|
|
15319
|
+
id: "notif-model",
|
|
15320
|
+
title: "Design notification data model",
|
|
15321
|
+
type: "feature",
|
|
15322
|
+
risk: "medium",
|
|
15323
|
+
status: "pending",
|
|
15324
|
+
context_scope: "isolated",
|
|
15325
|
+
depends_on: [],
|
|
15326
|
+
acceptance_criteria: [
|
|
15327
|
+
"Notification entity with type, payload, status, user_id",
|
|
15328
|
+
"Database migration",
|
|
15329
|
+
"Enum for notification types"
|
|
15330
|
+
]
|
|
15331
|
+
},
|
|
15332
|
+
{
|
|
15333
|
+
id: "notif-service",
|
|
15334
|
+
title: "Implement notification service",
|
|
15335
|
+
type: "feature",
|
|
15336
|
+
risk: "medium",
|
|
15337
|
+
status: "pending",
|
|
15338
|
+
context_scope: "isolated",
|
|
15339
|
+
depends_on: ["notif-model"],
|
|
15340
|
+
acceptance_criteria: [
|
|
15341
|
+
"Send notification by type",
|
|
15342
|
+
"Queue-based delivery",
|
|
15343
|
+
"Retry logic for failed deliveries"
|
|
15344
|
+
]
|
|
15345
|
+
},
|
|
15346
|
+
{
|
|
15347
|
+
id: "notif-api",
|
|
15348
|
+
title: "Implement notification API",
|
|
15349
|
+
type: "feature",
|
|
15350
|
+
risk: "low",
|
|
15351
|
+
status: "pending",
|
|
15352
|
+
context_scope: "isolated",
|
|
15353
|
+
depends_on: ["notif-service"],
|
|
15354
|
+
acceptance_criteria: [
|
|
15355
|
+
"POST /notifications endpoint",
|
|
15356
|
+
"GET /notifications endpoint with read/unread filter",
|
|
15357
|
+
"PATCH /notifications/:id/read endpoint"
|
|
15358
|
+
]
|
|
15359
|
+
},
|
|
15360
|
+
{
|
|
15361
|
+
id: "notif-tests",
|
|
15362
|
+
title: "Write notification tests",
|
|
15363
|
+
type: "test",
|
|
15364
|
+
risk: "low",
|
|
15365
|
+
status: "pending",
|
|
15366
|
+
context_scope: "isolated",
|
|
15367
|
+
depends_on: ["notif-api"],
|
|
15368
|
+
acceptance_criteria: [
|
|
15369
|
+
"Unit tests for notification logic",
|
|
15370
|
+
"Integration tests for API",
|
|
15371
|
+
"Edge cases: invalid type, missing user"
|
|
15372
|
+
]
|
|
15373
|
+
}
|
|
15374
|
+
]
|
|
15375
|
+
},
|
|
15376
|
+
{
|
|
15377
|
+
keywords: ["migration", "migrate", "schema change", "database change", "column"],
|
|
15378
|
+
tasks: [
|
|
15379
|
+
{
|
|
15380
|
+
id: "migrate-script",
|
|
15381
|
+
title: "Write migration script",
|
|
15382
|
+
type: "feature",
|
|
15383
|
+
risk: "high",
|
|
15384
|
+
status: "pending",
|
|
15385
|
+
context_scope: "isolated",
|
|
15386
|
+
depends_on: [],
|
|
15387
|
+
acceptance_criteria: [
|
|
15388
|
+
"Migration is reversible",
|
|
15389
|
+
"Handles existing data gracefully",
|
|
15390
|
+
"Rollback script included"
|
|
15391
|
+
]
|
|
15392
|
+
},
|
|
15393
|
+
{
|
|
15394
|
+
id: "migrate-model",
|
|
15395
|
+
title: "Update domain model",
|
|
15396
|
+
type: "refactor",
|
|
15397
|
+
risk: "medium",
|
|
15398
|
+
status: "pending",
|
|
15399
|
+
context_scope: "isolated",
|
|
15400
|
+
depends_on: ["migrate-script"],
|
|
15401
|
+
acceptance_criteria: [
|
|
15402
|
+
"Domain model reflects new schema",
|
|
15403
|
+
"Existing code paths updated",
|
|
15404
|
+
"Backward compatibility maintained"
|
|
15405
|
+
]
|
|
15406
|
+
},
|
|
15407
|
+
{
|
|
15408
|
+
id: "migrate-dal",
|
|
15409
|
+
title: "Update data access layer",
|
|
15410
|
+
type: "refactor",
|
|
15411
|
+
risk: "medium",
|
|
15412
|
+
status: "pending",
|
|
15413
|
+
context_scope: "isolated",
|
|
15414
|
+
depends_on: ["migrate-model"],
|
|
15415
|
+
acceptance_criteria: [
|
|
15416
|
+
"Repository/service reads/writes new schema",
|
|
15417
|
+
"No broken queries",
|
|
15418
|
+
"Performance not degraded"
|
|
15419
|
+
]
|
|
15420
|
+
},
|
|
15421
|
+
{
|
|
15422
|
+
id: "migrate-tests",
|
|
15423
|
+
title: "Write migration tests",
|
|
15424
|
+
type: "test",
|
|
15425
|
+
risk: "high",
|
|
15426
|
+
status: "pending",
|
|
15427
|
+
context_scope: "isolated",
|
|
15428
|
+
depends_on: ["migrate-dal"],
|
|
15429
|
+
acceptance_criteria: [
|
|
15430
|
+
"Migration up/down test",
|
|
15431
|
+
"Data integrity test",
|
|
15432
|
+
"Integration tests with new schema"
|
|
15433
|
+
]
|
|
15434
|
+
}
|
|
15435
|
+
]
|
|
15436
|
+
}
|
|
15437
|
+
];
|
|
15438
|
+
var GENERIC_TEMPLATE = [
|
|
15439
|
+
{
|
|
15440
|
+
id: "plan-scope",
|
|
15441
|
+
title: "Clarify requirements and scope",
|
|
15442
|
+
type: "feature",
|
|
15443
|
+
risk: "low",
|
|
15444
|
+
status: "pending",
|
|
15445
|
+
context_scope: "isolated",
|
|
15446
|
+
depends_on: [],
|
|
15447
|
+
acceptance_criteria: ["Objective is well-defined", "Scope boundaries identified"]
|
|
15448
|
+
},
|
|
15449
|
+
{
|
|
15450
|
+
id: "plan-design",
|
|
15451
|
+
title: "Design technical approach",
|
|
15452
|
+
type: "feature",
|
|
15453
|
+
risk: "medium",
|
|
15454
|
+
status: "pending",
|
|
15455
|
+
context_scope: "isolated",
|
|
15456
|
+
depends_on: ["plan-scope"],
|
|
15457
|
+
acceptance_criteria: ["Architecture decisions documented", "API contracts defined"]
|
|
15458
|
+
},
|
|
15459
|
+
{
|
|
15460
|
+
id: "plan-impl",
|
|
15461
|
+
title: "Implement solution",
|
|
15462
|
+
type: "feature",
|
|
15463
|
+
risk: "medium",
|
|
15464
|
+
status: "pending",
|
|
15465
|
+
context_scope: "isolated",
|
|
15466
|
+
depends_on: ["plan-design"],
|
|
15467
|
+
acceptance_criteria: ["Core functionality implemented", "Follows project conventions"]
|
|
15468
|
+
},
|
|
15469
|
+
{
|
|
15470
|
+
id: "plan-tests",
|
|
15471
|
+
title: "Write tests and verify",
|
|
15472
|
+
type: "test",
|
|
15473
|
+
risk: "low",
|
|
15474
|
+
status: "pending",
|
|
15475
|
+
context_scope: "isolated",
|
|
15476
|
+
depends_on: ["plan-impl"],
|
|
15477
|
+
acceptance_criteria: ["Unit tests pass", "Integration tests pass", "No regressions"]
|
|
15478
|
+
}
|
|
15479
|
+
];
|
|
15480
|
+
function matchTemplate(objective) {
|
|
15481
|
+
const lower = objective.toLowerCase();
|
|
15482
|
+
for (const template of TEMPLATES) {
|
|
15483
|
+
const matched = template.keywords.some((kw) => lower.includes(kw));
|
|
15484
|
+
if (matched)
|
|
15485
|
+
return template.tasks;
|
|
15486
|
+
}
|
|
15487
|
+
return GENERIC_TEMPLATE;
|
|
15488
|
+
}
|
|
15489
|
+
function planGoal(objective) {
|
|
15490
|
+
const tasks = matchTemplate(objective);
|
|
15491
|
+
return {
|
|
15492
|
+
objective,
|
|
15493
|
+
tasks: tasks.map((t) => ({ ...t, status: "pending" })),
|
|
15494
|
+
created_at: new Date().toISOString()
|
|
15495
|
+
};
|
|
15496
|
+
}
|
|
15497
|
+
|
|
15498
|
+
// src/core/goal/goal-state.ts
|
|
15499
|
+
init_dist();
|
|
15500
|
+
init_schemas();
|
|
15501
|
+
import { mkdir as mkdir7, readFile as readFile10, writeFile as writeFile6 } from "node:fs/promises";
|
|
15502
|
+
import { resolve as resolve10 } from "node:path";
|
|
15503
|
+
function validateGoalGraph(graph) {
|
|
15504
|
+
const ids = new Set(graph.tasks.map((t) => t.id));
|
|
15505
|
+
if (ids.size !== graph.tasks.length) {
|
|
15506
|
+
return err(new Error("Duplicate task IDs in goal graph"));
|
|
15507
|
+
}
|
|
15508
|
+
for (const task of graph.tasks) {
|
|
15509
|
+
for (const dep of task.depends_on ?? []) {
|
|
15510
|
+
if (!ids.has(dep)) {
|
|
15511
|
+
return err(new Error(`Task "${task.id}" depends on unknown task "${dep}"`));
|
|
15512
|
+
}
|
|
15513
|
+
}
|
|
15514
|
+
}
|
|
15515
|
+
const visited = new Set;
|
|
15516
|
+
const inStack = new Set;
|
|
15517
|
+
function dfs(taskId) {
|
|
15518
|
+
if (inStack.has(taskId))
|
|
15519
|
+
return true;
|
|
15520
|
+
if (visited.has(taskId))
|
|
15521
|
+
return false;
|
|
15522
|
+
visited.add(taskId);
|
|
15523
|
+
inStack.add(taskId);
|
|
15524
|
+
const task = graph.tasks.find((t) => t.id === taskId);
|
|
15525
|
+
if (task) {
|
|
15526
|
+
for (const dep of task.depends_on ?? []) {
|
|
15527
|
+
if (dfs(dep))
|
|
15528
|
+
return true;
|
|
15529
|
+
}
|
|
15530
|
+
}
|
|
15531
|
+
inStack.delete(taskId);
|
|
15532
|
+
return false;
|
|
15533
|
+
}
|
|
15534
|
+
for (const task of graph.tasks) {
|
|
15535
|
+
if (dfs(task.id)) {
|
|
15536
|
+
return err(new Error(`Cycle detected involving task "${task.id}"`));
|
|
15537
|
+
}
|
|
15538
|
+
}
|
|
15539
|
+
return ok(graph);
|
|
15540
|
+
}
|
|
15541
|
+
async function writeGoal(projectRoot, graph) {
|
|
15542
|
+
const validation = validateGoalGraph(graph);
|
|
15543
|
+
if (!validation.success)
|
|
15544
|
+
return validation;
|
|
15545
|
+
const dir = resolve10(projectRoot, ".codeconductor");
|
|
15546
|
+
await mkdir7(dir, { recursive: true });
|
|
15547
|
+
const yaml = $stringify(graph);
|
|
15548
|
+
await writeFile6(resolve10(dir, "current-goal.yml"), yaml, "utf-8");
|
|
15549
|
+
return ok(undefined);
|
|
15550
|
+
}
|
|
15551
|
+
|
|
15552
|
+
// src/commands/goal.command.ts
|
|
15553
|
+
function renderDependencyTree(tasks) {
|
|
15554
|
+
const lines = [];
|
|
15555
|
+
const taskMap = new Map(tasks.map((t) => [t.id, t]));
|
|
15556
|
+
const roots = tasks.filter((t) => !t.depends_on || t.depends_on.length === 0);
|
|
15557
|
+
function render(taskId, prefix, isLast) {
|
|
15558
|
+
const task = taskMap.get(taskId);
|
|
15559
|
+
if (!task)
|
|
15560
|
+
return;
|
|
15561
|
+
const connector = isLast ? "└── " : "├── ";
|
|
15562
|
+
const label = `${task.id}: ${task.title}`;
|
|
15563
|
+
lines.push(`${prefix}${connector}${label}`);
|
|
15564
|
+
const children = tasks.filter((t) => t.depends_on && t.depends_on.includes(taskId));
|
|
15565
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
15566
|
+
children.forEach((child, i) => {
|
|
15567
|
+
render(child.id, childPrefix, i === children.length - 1);
|
|
15568
|
+
});
|
|
15569
|
+
}
|
|
15570
|
+
roots.forEach((root, i) => {
|
|
15571
|
+
render(root.id, "", i === roots.length - 1);
|
|
15572
|
+
});
|
|
15573
|
+
return lines.join(`
|
|
15574
|
+
`);
|
|
15575
|
+
}
|
|
15576
|
+
async function goalCommand(options) {
|
|
15577
|
+
const { objective, projectRoot, output } = options;
|
|
15578
|
+
if (!objective || objective.trim().length === 0) {
|
|
15579
|
+
return {
|
|
15580
|
+
code: 1,
|
|
15581
|
+
data: {
|
|
15582
|
+
success: false,
|
|
15583
|
+
command: "goal",
|
|
15584
|
+
errors: ['Objective is required. Usage: codeconductor goal "<objective>"']
|
|
15585
|
+
}
|
|
15586
|
+
};
|
|
15587
|
+
}
|
|
15588
|
+
try {
|
|
15589
|
+
const graph = planGoal(objective);
|
|
15590
|
+
const writeResult = await writeGoal(projectRoot, graph);
|
|
15591
|
+
if (!writeResult.success) {
|
|
15592
|
+
return {
|
|
15593
|
+
code: 1,
|
|
15594
|
+
data: {
|
|
15595
|
+
success: false,
|
|
15596
|
+
command: "goal",
|
|
15597
|
+
errors: [`Failed to write goal: ${writeResult.error.message}`]
|
|
15598
|
+
}
|
|
15599
|
+
};
|
|
15600
|
+
}
|
|
15601
|
+
if (output === "json") {
|
|
15602
|
+
return {
|
|
15603
|
+
code: 0,
|
|
15604
|
+
data: {
|
|
15605
|
+
success: true,
|
|
15606
|
+
command: "goal",
|
|
15607
|
+
objective: graph.objective,
|
|
15608
|
+
tasks: graph.tasks,
|
|
15609
|
+
file: ".codeconductor/current-goal.yml"
|
|
15610
|
+
}
|
|
15611
|
+
};
|
|
15612
|
+
}
|
|
15613
|
+
const tree = renderDependencyTree(graph.tasks);
|
|
15614
|
+
const lines = [
|
|
15615
|
+
`Objective: ${graph.objective}`,
|
|
15616
|
+
"",
|
|
15617
|
+
"Task dependency graph:",
|
|
15618
|
+
tree,
|
|
15619
|
+
"",
|
|
15620
|
+
`Tasks: ${graph.tasks.length} total`,
|
|
15621
|
+
`File: .codeconductor/current-goal.yml`
|
|
15622
|
+
];
|
|
15623
|
+
return {
|
|
15624
|
+
code: 0,
|
|
15625
|
+
data: {
|
|
15626
|
+
success: true,
|
|
15627
|
+
command: "goal",
|
|
15628
|
+
output: lines.join(`
|
|
15629
|
+
`)
|
|
15630
|
+
}
|
|
15631
|
+
};
|
|
15632
|
+
} catch (e) {
|
|
15633
|
+
return {
|
|
15634
|
+
code: 1,
|
|
15635
|
+
data: {
|
|
15636
|
+
success: false,
|
|
15637
|
+
command: "goal",
|
|
15638
|
+
errors: [e instanceof Error ? e.message : String(e)]
|
|
15639
|
+
}
|
|
15640
|
+
};
|
|
15641
|
+
}
|
|
15642
|
+
}
|
|
15643
|
+
|
|
15083
15644
|
// src/commands/help.command.ts
|
|
15084
15645
|
import { readdir as readdir3 } from "node:fs/promises";
|
|
15085
15646
|
import { join as join8 } from "node:path";
|
|
@@ -15159,6 +15720,14 @@ function renderHuman(inventory, defaultTarget) {
|
|
|
15159
15720
|
lines.push(` - ${wf}`);
|
|
15160
15721
|
}
|
|
15161
15722
|
}
|
|
15723
|
+
lines.push("");
|
|
15724
|
+
lines.push("Stack-specific presets (v0.4.0):");
|
|
15725
|
+
lines.push(" ts-next-drizzle Next.js / Astro, Tailwind, Drizzle ORM, Bun, Postgres");
|
|
15726
|
+
lines.push(" spring-kotlin-jpa Spring Boot, Kotlin/Java, Gradle, JPA, Hibernate");
|
|
15727
|
+
lines.push(" laravel-tall Laravel, Blade, Livewire, Alpine.js");
|
|
15728
|
+
lines.push(" python-data-api Python, FastAPI, Django, uv");
|
|
15729
|
+
lines.push(" Browse: presets/<preset-name>/agents/ — copy into the target runner.");
|
|
15730
|
+
lines.push(" Registry: src/core/presets/preset-registry.ts (listPresets / getPreset).");
|
|
15162
15731
|
return lines.join(`
|
|
15163
15732
|
`);
|
|
15164
15733
|
}
|
|
@@ -15207,8 +15776,8 @@ async function helpCommand(options) {
|
|
|
15207
15776
|
}
|
|
15208
15777
|
|
|
15209
15778
|
// src/commands/seo-audit.command.ts
|
|
15210
|
-
import { writeFile as
|
|
15211
|
-
import { dirname as dirname4, resolve as
|
|
15779
|
+
import { writeFile as writeFile7, mkdir as mkdir8 } from "node:fs/promises";
|
|
15780
|
+
import { dirname as dirname4, resolve as resolve11 } from "node:path";
|
|
15212
15781
|
|
|
15213
15782
|
// src/infrastructure/http/safe-fetch.ts
|
|
15214
15783
|
import { lookup } from "node:dns/promises";
|
|
@@ -15295,7 +15864,7 @@ async function safeFetch(urlString, options = {}) {
|
|
|
15295
15864
|
}
|
|
15296
15865
|
}
|
|
15297
15866
|
async function delay(ms) {
|
|
15298
|
-
return new Promise((
|
|
15867
|
+
return new Promise((resolve11) => setTimeout(resolve11, ms));
|
|
15299
15868
|
}
|
|
15300
15869
|
|
|
15301
15870
|
// src/infrastructure/parsers/sitemap-parser.ts
|
|
@@ -16499,14 +17068,14 @@ async function seoAuditCommand(options) {
|
|
|
16499
17068
|
formattedOutput = formatCli(report);
|
|
16500
17069
|
}
|
|
16501
17070
|
if (output) {
|
|
16502
|
-
const outputPath =
|
|
16503
|
-
await
|
|
16504
|
-
await
|
|
17071
|
+
const outputPath = resolve11(options.projectRoot, output);
|
|
17072
|
+
await mkdir8(dirname4(outputPath), { recursive: true });
|
|
17073
|
+
await writeFile7(outputPath, formattedOutput, "utf-8");
|
|
16505
17074
|
} else if (format === "markdown") {
|
|
16506
17075
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16507
|
-
const defaultPath =
|
|
16508
|
-
await
|
|
16509
|
-
await
|
|
17076
|
+
const defaultPath = resolve11(options.projectRoot, "seo-reports", `audit-report-${timestamp}.md`);
|
|
17077
|
+
await mkdir8(dirname4(defaultPath), { recursive: true });
|
|
17078
|
+
await writeFile7(defaultPath, formattedOutput, "utf-8");
|
|
16510
17079
|
process.stderr.write(`Report saved to: ${defaultPath}
|
|
16511
17080
|
`);
|
|
16512
17081
|
}
|
|
@@ -16518,7 +17087,7 @@ async function seoAuditCommand(options) {
|
|
|
16518
17087
|
command: "seo audit",
|
|
16519
17088
|
report,
|
|
16520
17089
|
output: formattedOutput,
|
|
16521
|
-
outputFile: output ?
|
|
17090
|
+
outputFile: output ? resolve11(options.projectRoot, output) : format === "markdown" ? resolve11(options.projectRoot, "seo-reports") : undefined
|
|
16522
17091
|
}
|
|
16523
17092
|
};
|
|
16524
17093
|
} catch (error) {
|
|
@@ -16534,8 +17103,8 @@ async function seoAuditCommand(options) {
|
|
|
16534
17103
|
}
|
|
16535
17104
|
|
|
16536
17105
|
// src/commands/seo-llms.command.ts
|
|
16537
|
-
import { writeFile as
|
|
16538
|
-
import { dirname as dirname5, resolve as
|
|
17106
|
+
import { writeFile as writeFile8, mkdir as mkdir9 } from "node:fs/promises";
|
|
17107
|
+
import { dirname as dirname5, resolve as resolve12 } from "node:path";
|
|
16539
17108
|
|
|
16540
17109
|
// src/domain/seo/llms-generator.ts
|
|
16541
17110
|
function extractTitle2(html) {
|
|
@@ -16678,9 +17247,9 @@ async function seoLlmsCommand(options) {
|
|
|
16678
17247
|
}
|
|
16679
17248
|
}) : await generateLlmsTxtFromUrl(url);
|
|
16680
17249
|
process.stderr.write("\r" + " ".repeat(80) + "\r");
|
|
16681
|
-
const outputPath = output ?
|
|
16682
|
-
await
|
|
16683
|
-
await
|
|
17250
|
+
const outputPath = output ? resolve12(options.projectRoot, output) : resolve12(options.projectRoot, "llms.txt");
|
|
17251
|
+
await mkdir9(dirname5(outputPath), { recursive: true });
|
|
17252
|
+
await writeFile8(outputPath, result.content, "utf-8");
|
|
16684
17253
|
process.stderr.write(`Generated: ${outputPath} (${result.entries.length} entries)
|
|
16685
17254
|
`);
|
|
16686
17255
|
return {
|
|
@@ -16707,8 +17276,8 @@ async function seoLlmsCommand(options) {
|
|
|
16707
17276
|
|
|
16708
17277
|
// src/commands/update.command.ts
|
|
16709
17278
|
import { homedir as homedir9 } from "node:os";
|
|
16710
|
-
import { resolve as
|
|
16711
|
-
import { mkdir as
|
|
17279
|
+
import { resolve as resolve13, dirname as dirname6 } from "node:path";
|
|
17280
|
+
import { mkdir as mkdir10, readFile as readFile11, writeFile as writeFile9, stat as stat3 } from "node:fs/promises";
|
|
16712
17281
|
init_package_paths();
|
|
16713
17282
|
async function updateCommand(options) {
|
|
16714
17283
|
const { dryRun, force, global: isGlobal, output, projectRoot } = options;
|
|
@@ -16774,23 +17343,23 @@ async function updateCommand(options) {
|
|
|
16774
17343
|
}
|
|
16775
17344
|
const updated = [];
|
|
16776
17345
|
if (updateResults.council) {
|
|
16777
|
-
const localCouncil =
|
|
16778
|
-
const bundledCouncil =
|
|
17346
|
+
const localCouncil = resolve13(basePath, ".codeconductor", "presets", "council.yml");
|
|
17347
|
+
const bundledCouncil = resolve13(SRC_PRESETS_DIR, "council", "council.yml");
|
|
16779
17348
|
try {
|
|
16780
|
-
const content = await
|
|
16781
|
-
await
|
|
16782
|
-
await
|
|
17349
|
+
const content = await readFile11(bundledCouncil, "utf-8");
|
|
17350
|
+
await mkdir10(dirname6(localCouncil), { recursive: true });
|
|
17351
|
+
await writeFile9(localCouncil, content, "utf-8");
|
|
16783
17352
|
updated.push(localCouncil);
|
|
16784
17353
|
} catch (e) {
|
|
16785
17354
|
throw new Error(`Failed to update council.yml: ${e}`);
|
|
16786
17355
|
}
|
|
16787
17356
|
}
|
|
16788
17357
|
if (updateResults.policy) {
|
|
16789
|
-
const localPolicy =
|
|
17358
|
+
const localPolicy = resolve13(basePath, ".codeconductor", "presets", "policy.yml");
|
|
16790
17359
|
try {
|
|
16791
|
-
const content = await
|
|
16792
|
-
await
|
|
16793
|
-
await
|
|
17360
|
+
const content = await readFile11(POLICY_PATH, "utf-8");
|
|
17361
|
+
await mkdir10(dirname6(localPolicy), { recursive: true });
|
|
17362
|
+
await writeFile9(localPolicy, content, "utf-8");
|
|
16794
17363
|
updated.push(localPolicy);
|
|
16795
17364
|
} catch (e) {
|
|
16796
17365
|
throw new Error(`Failed to update policy.yml: ${e}`);
|
|
@@ -16842,12 +17411,12 @@ async function updateCommand(options) {
|
|
|
16842
17411
|
let targetPath = f.path;
|
|
16843
17412
|
let targetBase = basePath;
|
|
16844
17413
|
if ((targetName === "agy" || targetName === "gemini") && isGlobal) {
|
|
16845
|
-
targetBase =
|
|
17414
|
+
targetBase = resolve13(homedir9(), ".gemini", "config");
|
|
16846
17415
|
targetPath = targetPath.replace(/^\.agents\/?/, "");
|
|
16847
17416
|
}
|
|
16848
17417
|
return {
|
|
16849
17418
|
...f,
|
|
16850
|
-
path:
|
|
17419
|
+
path: resolve13(targetBase, targetPath)
|
|
16851
17420
|
};
|
|
16852
17421
|
});
|
|
16853
17422
|
const filesToWrite = resolvedFiles.filter((f) => t.files.includes(f.path));
|
|
@@ -16875,19 +17444,19 @@ async function updateCommand(options) {
|
|
|
16875
17444
|
for (const s of updateResults.skills) {
|
|
16876
17445
|
newSkillsLock[s.id] = s.latestVersion;
|
|
16877
17446
|
}
|
|
16878
|
-
let lockDest =
|
|
17447
|
+
let lockDest = resolve13(basePath, ".codeconductor", "skills-lock.json");
|
|
16879
17448
|
try {
|
|
16880
|
-
const statAgents = await stat3(
|
|
17449
|
+
const statAgents = await stat3(resolve13(basePath, ".agents"));
|
|
16881
17450
|
if (statAgents.isDirectory()) {
|
|
16882
|
-
const statCodeConductor = await stat3(
|
|
17451
|
+
const statCodeConductor = await stat3(resolve13(basePath, ".codeconductor")).catch(() => null);
|
|
16883
17452
|
if (!statCodeConductor) {
|
|
16884
|
-
lockDest =
|
|
17453
|
+
lockDest = resolve13(basePath, ".agents", "skills-lock.json");
|
|
16885
17454
|
}
|
|
16886
17455
|
}
|
|
16887
17456
|
} catch {}
|
|
16888
17457
|
try {
|
|
16889
|
-
await
|
|
16890
|
-
await
|
|
17458
|
+
await mkdir10(dirname6(lockDest), { recursive: true });
|
|
17459
|
+
await writeFile9(lockDest, JSON.stringify(newSkillsLock, null, 2), "utf-8");
|
|
16891
17460
|
updated.push(lockDest);
|
|
16892
17461
|
} catch (e) {
|
|
16893
17462
|
throw new Error(`Failed to write skills-lock.json: ${e}`);
|
|
@@ -16988,26 +17557,47 @@ Usage: npx cc-codeconductor <command> [options]
|
|
|
16988
17557
|
|
|
16989
17558
|
Commands:
|
|
16990
17559
|
init Initialize CodeConductor in a project
|
|
16991
|
-
detect
|
|
16992
|
-
install council
|
|
16993
|
-
install preset
|
|
16994
|
-
install lsp
|
|
16995
|
-
seo audit
|
|
16996
|
-
seo llms
|
|
16997
|
-
doctor
|
|
16998
|
-
update
|
|
16999
|
-
help / cc-help
|
|
17000
|
-
debt-harvest / harvest
|
|
17560
|
+
detect Detect project stack and recommended presets
|
|
17561
|
+
install council Install generated council spec files to runner targets
|
|
17562
|
+
install preset Install full preset (agents, prompts, skills, commands)
|
|
17563
|
+
install lsp Install and configure LSP servers for AI coding tools
|
|
17564
|
+
seo audit Run SEO audit on a URL or sitemap
|
|
17565
|
+
seo llms Generate llms.txt from a URL or sitemap
|
|
17566
|
+
doctor Validate configuration and generated files
|
|
17567
|
+
update Update installed presets
|
|
17568
|
+
help / cc-help Show preset inventory (skills, subagents, commands)
|
|
17569
|
+
debt-harvest / harvest Scan source files for deferred debt items
|
|
17570
|
+
goal / cc-goal Plan goal into task graph with dependencies
|
|
17001
17571
|
|
|
17002
17572
|
Options:
|
|
17003
|
-
--help, -h
|
|
17004
|
-
--version, -v
|
|
17005
|
-
--dry-run
|
|
17006
|
-
--force
|
|
17007
|
-
--global
|
|
17008
|
-
--output, -o
|
|
17009
|
-
--lang
|
|
17010
|
-
--locale
|
|
17573
|
+
--help, -h Show this help message
|
|
17574
|
+
--version, -v Show package version
|
|
17575
|
+
--dry-run Show what would happen without writing files
|
|
17576
|
+
--force Allow overwriting existing files
|
|
17577
|
+
--global Install to home directory (~/.claude, ~/.opencode, etc.)
|
|
17578
|
+
--output, -o Output mode: human or json
|
|
17579
|
+
--lang Comma-separated list of languages (e.g., typescript,php,python)
|
|
17580
|
+
--locale Instruction language for agent files: en (default) | es
|
|
17581
|
+
--target Runner target: opencode, claude, codex, gemini, cursor, agy, all
|
|
17582
|
+
|
|
17583
|
+
Stack-specific presets (v0.4.0, registered in preset-registry):
|
|
17584
|
+
ts-next-drizzle Next.js / Astro, Tailwind, Drizzle ORM, Bun, Postgres
|
|
17585
|
+
spring-kotlin-jpa Spring Boot, Kotlin/Java, Gradle, JPA, Hibernate
|
|
17586
|
+
laravel-tall Laravel, Blade, Livewire, Alpine.js
|
|
17587
|
+
python-data-api Python, FastAPI, Django, uv
|
|
17588
|
+
Listed programmatically via listPresets() in src/core/presets/preset-registry.ts.
|
|
17589
|
+
Stack detection wires matching specialized skills automatically when
|
|
17590
|
+
init/detect identifies the stack.
|
|
17591
|
+
|
|
17592
|
+
Workflow Loop Core (v0.4.0):
|
|
17593
|
+
runWorkflowPipeline() in src/core/pipeline/workflow-loop.ts runs the
|
|
17594
|
+
8-phase loop (intake -> structure -> design -> test -> implement ->
|
|
17595
|
+
validate -> council -> compact) with wall-clock, files-modified and
|
|
17596
|
+
lines-changed guardrails and STOP gates after Design and Council.
|
|
17597
|
+
|
|
17598
|
+
Council consensus v0.4.0:
|
|
17599
|
+
Per-agent confidence thresholds (< 0.6 or average < 0.7 escalate)
|
|
17600
|
+
and a complianceVeto channel that overrides majority like securityVeto.
|
|
17011
17601
|
|
|
17012
17602
|
Examples:
|
|
17013
17603
|
npx cc-codeconductor init
|
|
@@ -17036,6 +17626,16 @@ Examples:
|
|
|
17036
17626
|
npx cc-codeconductor seo audit --sitemap https://example.com/sitemap.xml --format markdown
|
|
17037
17627
|
npx cc-codeconductor seo llms --sitemap https://example.com/sitemap.xml
|
|
17038
17628
|
npx cc-codeconductor seo llms --url https://example.com --output llms.txt
|
|
17629
|
+
npx cc-codeconductor goal "Add user authentication"
|
|
17630
|
+
npx cc-codeconductor cc-goal "Implement CRUD for invoices"
|
|
17631
|
+
npx cc-codeconductor help --target opencode
|
|
17632
|
+
npx cc-codeconductor help --target claude --output json
|
|
17633
|
+
|
|
17634
|
+
Docs: https://github.com/lgzarturo/codeconductor/tree/main/docs
|
|
17635
|
+
docs/v0.4.0-release-notes.md v0.4.0 feature breakdown
|
|
17636
|
+
docs/routing-policy.md Risk-based routing (v0.4.0)
|
|
17637
|
+
docs/prompt-versioning.md Agent contract versions
|
|
17638
|
+
docs/usage-cli.md Detailed CLI reference
|
|
17039
17639
|
`;
|
|
17040
17640
|
}
|
|
17041
17641
|
async function routeCommand(args, projectRoot) {
|
|
@@ -17123,6 +17723,13 @@ async function routeCommand(args, projectRoot) {
|
|
|
17123
17723
|
dir: options.dir,
|
|
17124
17724
|
output: flags.output
|
|
17125
17725
|
});
|
|
17726
|
+
case "goal":
|
|
17727
|
+
case "cc-goal":
|
|
17728
|
+
return goalCommand({
|
|
17729
|
+
objective: subcommand || options.objective || "",
|
|
17730
|
+
projectRoot,
|
|
17731
|
+
output: flags.output
|
|
17732
|
+
});
|
|
17126
17733
|
case "seo": {
|
|
17127
17734
|
if (subcommand === "audit") {
|
|
17128
17735
|
return seoAuditCommand({
|
|
@@ -17187,6 +17794,8 @@ async function runCli(args) {
|
|
|
17187
17794
|
const data = result.data;
|
|
17188
17795
|
if ("help" in data) {
|
|
17189
17796
|
console.log(data.help);
|
|
17797
|
+
} else if ("message" in data && typeof data.message === "string") {
|
|
17798
|
+
console.log(data.message);
|
|
17190
17799
|
} else {
|
|
17191
17800
|
if ("errors" in data && Array.isArray(data.errors) && data.errors.length > 0) {
|
|
17192
17801
|
data.errors.forEach((e) => console.error(e));
|