cc-codeconductor 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -4
- package/dist/index.js +595 -39
- package/package.json +1 -1
- package/presets/agy/AGENTS.md +24 -0
- package/presets/codex/AGENTS.md +34 -0
- 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/README.md
CHANGED
|
@@ -40,6 +40,9 @@ contracts, task cards, and risk-based routing.
|
|
|
40
40
|
> (skills, subagents, commands) for the active or specified target
|
|
41
41
|
> - `npx cc-codeconductor debt-harvest` (alias: `harvest`) — scans source files
|
|
42
42
|
> for `// defer` comments and writes `.codeconductor/debt-ledger.md`
|
|
43
|
+
> - `npx cc-codeconductor goal "<objective>"` (alias: `cc-goal`) — decomposes an
|
|
44
|
+
> objective into a dependency-ordered task graph, writes
|
|
45
|
+
> `.codeconductor/current-goal.yml`
|
|
43
46
|
> - `/cc-pagespeed --url <url>` — audits web performance using the PageSpeed
|
|
44
47
|
> Insights API; applies the 80/20 principle to produce a prioritized report of
|
|
45
48
|
> Core Web Vitals (LCP, TBT, CLS, FCP, TTFB) with framework-specific fixes;
|
|
@@ -120,21 +123,22 @@ Task Card → Risk Classification → Routing Policy → Conductor Agent → Del
|
|
|
120
123
|
|
|
121
124
|
---
|
|
122
125
|
|
|
123
|
-
## Current Support
|
|
126
|
+
## Current Support
|
|
124
127
|
|
|
125
128
|
- OpenCode preset
|
|
126
129
|
- Claude Code-compatible preset (see [Claude Environment Options & Best Practices](file:///c:/Users/R2D2/Documents/GitHub/codeconductor/docs/claude-env-options.md))
|
|
127
130
|
- Codex preset
|
|
128
131
|
- Spring Boot / Kotlin workflow
|
|
129
132
|
- Python / Django workflow guidance
|
|
130
|
-
-
|
|
131
|
-
- Routing Policy v0.
|
|
133
|
+
- 12 core Conductor Agents
|
|
134
|
+
- Routing Policy v0.3.0
|
|
132
135
|
- Task Card template
|
|
133
136
|
- Scorecard template
|
|
134
137
|
- End-to-end example
|
|
135
138
|
- YAML-driven model configuration
|
|
136
139
|
- Provider-agnostic `AgentContract` abstraction with target renderers for Claude, OpenCode, Codex, and Agy
|
|
137
140
|
- Council consensus engine (`councilConsensus()`) for multi-agent governance with majority/unanimous algorithms and security veto
|
|
141
|
+
- Phase 5 runtime modules — scoped context injection, TDD history compaction, concise inter-agent messaging, and token budget enforcement in the compile-fix loop
|
|
138
142
|
|
|
139
143
|
---
|
|
140
144
|
|
|
@@ -300,6 +304,20 @@ into `.codeconductor/debt-ledger.md`, grouped by optional tag
|
|
|
300
304
|
Supported extensions: `.ts`, `.tsx`, `.js`, `.jsx`, `.go`, `.rs`, `.java`,
|
|
301
305
|
`.kt`, `.swift`, `.cs`, `.php`, `.scala`, `.dart`, `.c`, `.cpp`, `.h`, `.hpp`.
|
|
302
306
|
|
|
307
|
+
#### `goal` — decompose objective into task graph
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
npx cc-codeconductor goal "Add user authentication"
|
|
311
|
+
npx cc-codeconductor goal "Implement CRUD for invoices"
|
|
312
|
+
npx cc-codeconductor cc-goal "Add search with filters" # alias
|
|
313
|
+
npx cc-codeconductor goal "Add user authentication" --output json
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Matches the objective against built-in templates (auth, crud, search,
|
|
317
|
+
notification, migration) or falls back to a generic 4-task chain. Writes the
|
|
318
|
+
resulting task graph to `.codeconductor/current-goal.yml` with dependency
|
|
319
|
+
ordering. The orchestrator uses this file to delegate tasks in dependency order.
|
|
320
|
+
|
|
303
321
|
|
|
304
322
|
### Global options
|
|
305
323
|
|
|
@@ -404,9 +422,14 @@ codeconductor/
|
|
|
404
422
|
├── src/ ← CLI source (TypeScript + Bun)
|
|
405
423
|
│ ├── cli/ ← entry point, router, error codes
|
|
406
424
|
│ ├── commands/ ← init, detect, install, doctor, update
|
|
407
|
-
│ ├── core/ ← config, detection, filesystem, presets
|
|
425
|
+
│ ├── core/ ← config, detection, filesystem, presets, goal
|
|
426
|
+
│ │ ├── context/ ← scoped context injection (Phase 5)
|
|
427
|
+
│ │ ├── compaction/ ← TDD history compaction hook (Phase 5)
|
|
428
|
+
│ │ ├── messages/ ← concise inter-agent formatter (Phase 5)
|
|
429
|
+
│ │ └── loop/ ← compile-fix loop controller (Phase 5)
|
|
408
430
|
│ ├── adapters/ ← opencode, claude, codex generators
|
|
409
431
|
│ ├── domain/council/ ← council spec, agent, contract
|
|
432
|
+
│ ├── domain/loop/ ← loop state machine
|
|
410
433
|
│ ├── validation/ ← Zod schemas
|
|
411
434
|
│ ├── utils/ ← Result type, logger, invariant
|
|
412
435
|
│ └── presets/council/ ← bundled council.yml preset
|
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, 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,22 @@ var init_schemas = __esm(() => {
|
|
|
11309
11313
|
environment: exports_external.string().optional(),
|
|
11310
11314
|
release: exports_external.string().optional()
|
|
11311
11315
|
});
|
|
11316
|
+
GoalTaskSchema = exports_external.object({
|
|
11317
|
+
id: exports_external.string(),
|
|
11318
|
+
title: exports_external.string(),
|
|
11319
|
+
type: exports_external.enum(["feature", "fix", "refactor", "test", "docs"]),
|
|
11320
|
+
risk: exports_external.enum(["low", "medium", "high"]),
|
|
11321
|
+
status: exports_external.enum(["pending", "in-progress", "done", "blocked"]),
|
|
11322
|
+
depends_on: exports_external.array(exports_external.string()).optional().default([]),
|
|
11323
|
+
acceptance_criteria: exports_external.array(exports_external.string()),
|
|
11324
|
+
blocked_reason: exports_external.string().optional(),
|
|
11325
|
+
context_scope: exports_external.enum(["isolated", "continuation", "full"]).optional().default("isolated")
|
|
11326
|
+
});
|
|
11327
|
+
GoalGraphSchema = exports_external.object({
|
|
11328
|
+
objective: exports_external.string(),
|
|
11329
|
+
tasks: exports_external.array(GoalTaskSchema),
|
|
11330
|
+
created_at: exports_external.string()
|
|
11331
|
+
});
|
|
11312
11332
|
});
|
|
11313
11333
|
|
|
11314
11334
|
// src/core/presets/package-paths.ts
|
|
@@ -12000,10 +12020,9 @@ var init_agy_installer = __esm(() => {
|
|
|
12000
12020
|
|
|
12001
12021
|
// src/core/filesystem/credential-guard.ts
|
|
12002
12022
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
12003
|
-
import { resolve as resolve6 } from "node:path";
|
|
12004
12023
|
async function loadPolicyPatterns() {
|
|
12005
12024
|
try {
|
|
12006
|
-
const content = await readFile7(
|
|
12025
|
+
const content = await readFile7(POLICY_PATH, "utf-8");
|
|
12007
12026
|
const parsed = $parse(content);
|
|
12008
12027
|
if (Array.isArray(parsed.secretPatterns) && parsed.secretPatterns.length > 0) {
|
|
12009
12028
|
return parsed.secretPatterns;
|
|
@@ -12035,9 +12054,10 @@ async function loadCredentialPatterns(config) {
|
|
|
12035
12054
|
}
|
|
12036
12055
|
return DEFAULT_SECRET_PATTERNS;
|
|
12037
12056
|
}
|
|
12038
|
-
var DEFAULT_SECRET_PATTERNS
|
|
12057
|
+
var DEFAULT_SECRET_PATTERNS;
|
|
12039
12058
|
var init_credential_guard = __esm(() => {
|
|
12040
12059
|
init_dist();
|
|
12060
|
+
init_package_paths();
|
|
12041
12061
|
DEFAULT_SECRET_PATTERNS = [
|
|
12042
12062
|
"password",
|
|
12043
12063
|
"secret",
|
|
@@ -12048,7 +12068,6 @@ var init_credential_guard = __esm(() => {
|
|
|
12048
12068
|
"auth[_-]?token",
|
|
12049
12069
|
"private[_-]?key"
|
|
12050
12070
|
];
|
|
12051
|
-
POLICY_PATH2 = resolve6(import.meta.dir, "..", "..", "..", "policy.yml");
|
|
12052
12071
|
});
|
|
12053
12072
|
|
|
12054
12073
|
// src/core/filesystem/file-writer.ts
|
|
@@ -12135,7 +12154,7 @@ init_errors();
|
|
|
12135
12154
|
// package.json
|
|
12136
12155
|
var package_default = {
|
|
12137
12156
|
name: "cc-codeconductor",
|
|
12138
|
-
version: "0.4.
|
|
12157
|
+
version: "0.4.2",
|
|
12139
12158
|
description: "A multi-agent orchestration framework for AI-assisted software engineering workflows.",
|
|
12140
12159
|
keywords: [
|
|
12141
12160
|
"ai",
|
|
@@ -13057,7 +13076,8 @@ function renderTemplate(content, modelConfig, filePath, locale = "en") {
|
|
|
13057
13076
|
"tester",
|
|
13058
13077
|
"reviewer",
|
|
13059
13078
|
"docs",
|
|
13060
|
-
"repo-explorer"
|
|
13079
|
+
"repo-explorer",
|
|
13080
|
+
"goal-planner"
|
|
13061
13081
|
];
|
|
13062
13082
|
let result = templatedContent;
|
|
13063
13083
|
for (const role of knownRoles) {
|
|
@@ -13145,8 +13165,20 @@ function injectMcpServers(jsonString, filePath) {
|
|
|
13145
13165
|
if (isClaudeSettings || isAgyMcpConfig) {
|
|
13146
13166
|
obj.mcpServers = mergeDeep(obj.mcpServers || {}, mcpServers);
|
|
13147
13167
|
} else if (isOpencodeJsonc) {
|
|
13148
|
-
|
|
13149
|
-
|
|
13168
|
+
const opencodeMcp = {};
|
|
13169
|
+
for (const [key, server] of Object.entries(mcpServers)) {
|
|
13170
|
+
const commandArray = typeof server.command === "string" ? [server.command, ...server.args || []] : server.command;
|
|
13171
|
+
const formattedServer = {
|
|
13172
|
+
type: "local",
|
|
13173
|
+
command: commandArray,
|
|
13174
|
+
enabled: true
|
|
13175
|
+
};
|
|
13176
|
+
if (server.env) {
|
|
13177
|
+
formattedServer.environment = server.env;
|
|
13178
|
+
}
|
|
13179
|
+
opencodeMcp[key] = formattedServer;
|
|
13180
|
+
}
|
|
13181
|
+
obj.mcp = mergeDeep(obj.mcp || {}, opencodeMcp);
|
|
13150
13182
|
}
|
|
13151
13183
|
return JSON.stringify(obj, null, 2);
|
|
13152
13184
|
} catch {
|
|
@@ -13800,13 +13832,13 @@ async function doctorCommand(options) {
|
|
|
13800
13832
|
// src/commands/init.command.ts
|
|
13801
13833
|
import { access as access3, mkdir as mkdir3, readFile as readFile8, writeFile as writeFile3 } from "node:fs/promises";
|
|
13802
13834
|
import { homedir as homedir5 } from "node:os";
|
|
13803
|
-
import { basename, resolve as
|
|
13835
|
+
import { basename, resolve as resolve7 } from "node:path";
|
|
13804
13836
|
|
|
13805
13837
|
// src/core/config/config-writer.ts
|
|
13806
13838
|
init_dist();
|
|
13807
13839
|
init_errors();
|
|
13808
13840
|
import { access as access2, mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
13809
|
-
import { resolve as
|
|
13841
|
+
import { resolve as resolve6 } from "node:path";
|
|
13810
13842
|
|
|
13811
13843
|
// src/core/config/codeconductor-config.ts
|
|
13812
13844
|
init_credential_guard();
|
|
@@ -13847,9 +13879,9 @@ var CONFIG_DIR = ".codeconductor";
|
|
|
13847
13879
|
var CONFIG_FILE2 = "config.yml";
|
|
13848
13880
|
async function writeConfig(projectRoot, config = {}, force = false) {
|
|
13849
13881
|
try {
|
|
13850
|
-
const configDir =
|
|
13882
|
+
const configDir = resolve6(projectRoot, CONFIG_DIR);
|
|
13851
13883
|
await mkdir2(configDir, { recursive: true });
|
|
13852
|
-
const configPath =
|
|
13884
|
+
const configPath = resolve6(configDir, CONFIG_FILE2);
|
|
13853
13885
|
if (!force) {
|
|
13854
13886
|
try {
|
|
13855
13887
|
await access2(configPath);
|
|
@@ -14075,7 +14107,7 @@ async function initCommand(options) {
|
|
|
14075
14107
|
}
|
|
14076
14108
|
async function resolvePresetsToCopy() {
|
|
14077
14109
|
const sources = [];
|
|
14078
|
-
const bundledCouncil =
|
|
14110
|
+
const bundledCouncil = resolve7(SRC_PRESETS_DIR, "council", "council.yml");
|
|
14079
14111
|
if (await fileExists2(bundledCouncil)) {
|
|
14080
14112
|
sources.push({ name: "council.yml", sourcePath: bundledCouncil });
|
|
14081
14113
|
}
|
|
@@ -14086,11 +14118,11 @@ async function resolvePresetsToCopy() {
|
|
|
14086
14118
|
return sources;
|
|
14087
14119
|
}
|
|
14088
14120
|
async function copyPresets(baseDir, presets, force) {
|
|
14089
|
-
const presetsDir =
|
|
14121
|
+
const presetsDir = resolve7(baseDir, ".codeconductor", "presets");
|
|
14090
14122
|
await mkdir3(presetsDir, { recursive: true });
|
|
14091
14123
|
const copied = [];
|
|
14092
14124
|
for (const preset of presets) {
|
|
14093
|
-
const destPath =
|
|
14125
|
+
const destPath = resolve7(presetsDir, preset.name);
|
|
14094
14126
|
if (!force && await fileExists2(destPath)) {
|
|
14095
14127
|
continue;
|
|
14096
14128
|
}
|
|
@@ -14123,7 +14155,7 @@ init_claude_installer();
|
|
|
14123
14155
|
init_codex_installer();
|
|
14124
14156
|
init_opencode_installer();
|
|
14125
14157
|
import { homedir as homedir6 } from "node:os";
|
|
14126
|
-
import { resolve as
|
|
14158
|
+
import { resolve as resolve8 } from "node:path";
|
|
14127
14159
|
init_file_writer();
|
|
14128
14160
|
init_preset_loader();
|
|
14129
14161
|
|
|
@@ -14193,12 +14225,12 @@ async function installCommand(options) {
|
|
|
14193
14225
|
let targetPath = f.path;
|
|
14194
14226
|
let targetBase = baseDir;
|
|
14195
14227
|
if ((t === "agy" || t === "gemini") && isGlobal) {
|
|
14196
|
-
targetBase =
|
|
14228
|
+
targetBase = resolve8(homedir6(), ".gemini", "config");
|
|
14197
14229
|
targetPath = targetPath.replace(/^\.agents\/?/, "");
|
|
14198
14230
|
}
|
|
14199
14231
|
return {
|
|
14200
14232
|
...f,
|
|
14201
|
-
path:
|
|
14233
|
+
path: resolve8(targetBase, targetPath)
|
|
14202
14234
|
};
|
|
14203
14235
|
});
|
|
14204
14236
|
const results = await writeGeneratedFiles(resolvedFiles, writeOptions);
|
|
@@ -14309,7 +14341,7 @@ async function installPresetCommand(options) {
|
|
|
14309
14341
|
|
|
14310
14342
|
// src/commands/install-lsp.command.ts
|
|
14311
14343
|
import { homedir as homedir8 } from "node:os";
|
|
14312
|
-
import { resolve as
|
|
14344
|
+
import { resolve as resolve9 } from "node:path";
|
|
14313
14345
|
|
|
14314
14346
|
// src/core/lsp/lsp-config-utils.ts
|
|
14315
14347
|
function getLanguageServerConfig(lspIds) {
|
|
@@ -14846,7 +14878,7 @@ async function installLspCommand(options) {
|
|
|
14846
14878
|
const generatedFiles = generator.generate(installReport.results);
|
|
14847
14879
|
const resolvedFiles = generatedFiles.map((f) => ({
|
|
14848
14880
|
...f,
|
|
14849
|
-
path:
|
|
14881
|
+
path: resolve9(baseDir, f.path)
|
|
14850
14882
|
}));
|
|
14851
14883
|
const results = await writeGeneratedFiles(resolvedFiles, writeOptions);
|
|
14852
14884
|
for (const result of results) {
|
|
@@ -15081,6 +15113,522 @@ async function debtHarvestCommand(options) {
|
|
|
15081
15113
|
}
|
|
15082
15114
|
}
|
|
15083
15115
|
|
|
15116
|
+
// src/core/goal/goal-planner.ts
|
|
15117
|
+
var TEMPLATES = [
|
|
15118
|
+
{
|
|
15119
|
+
keywords: ["login", "auth", "authentication", "signin", "sign-in"],
|
|
15120
|
+
tasks: [
|
|
15121
|
+
{
|
|
15122
|
+
id: "auth-schema",
|
|
15123
|
+
title: "Define auth data model and DB schema",
|
|
15124
|
+
type: "feature",
|
|
15125
|
+
risk: "high",
|
|
15126
|
+
status: "pending",
|
|
15127
|
+
context_scope: "isolated",
|
|
15128
|
+
depends_on: [],
|
|
15129
|
+
acceptance_criteria: [
|
|
15130
|
+
"User entity with email, password_hash, created_at fields",
|
|
15131
|
+
"Migration script creates users table",
|
|
15132
|
+
"Schema supports password reset token"
|
|
15133
|
+
]
|
|
15134
|
+
},
|
|
15135
|
+
{
|
|
15136
|
+
id: "auth-api",
|
|
15137
|
+
title: "Define auth API contract",
|
|
15138
|
+
type: "feature",
|
|
15139
|
+
risk: "medium",
|
|
15140
|
+
status: "pending",
|
|
15141
|
+
context_scope: "isolated",
|
|
15142
|
+
depends_on: ["auth-schema"],
|
|
15143
|
+
acceptance_criteria: [
|
|
15144
|
+
"POST /auth/register endpoint defined",
|
|
15145
|
+
"POST /auth/login endpoint defined",
|
|
15146
|
+
"POST /auth/logout endpoint defined",
|
|
15147
|
+
"OpenAPI spec updated"
|
|
15148
|
+
]
|
|
15149
|
+
},
|
|
15150
|
+
{
|
|
15151
|
+
id: "auth-impl",
|
|
15152
|
+
title: "Implement auth endpoints",
|
|
15153
|
+
type: "feature",
|
|
15154
|
+
risk: "high",
|
|
15155
|
+
status: "pending",
|
|
15156
|
+
context_scope: "isolated",
|
|
15157
|
+
depends_on: ["auth-api"],
|
|
15158
|
+
acceptance_criteria: [
|
|
15159
|
+
"Register endpoint hashes password and stores user",
|
|
15160
|
+
"Login endpoint validates credentials and returns session",
|
|
15161
|
+
"Logout endpoint invalidates session",
|
|
15162
|
+
"Input validation on all endpoints"
|
|
15163
|
+
]
|
|
15164
|
+
},
|
|
15165
|
+
{
|
|
15166
|
+
id: "auth-tests",
|
|
15167
|
+
title: "Write auth tests",
|
|
15168
|
+
type: "test",
|
|
15169
|
+
risk: "medium",
|
|
15170
|
+
status: "pending",
|
|
15171
|
+
context_scope: "isolated",
|
|
15172
|
+
depends_on: ["auth-impl"],
|
|
15173
|
+
acceptance_criteria: [
|
|
15174
|
+
"Unit tests for password hashing",
|
|
15175
|
+
"Integration tests for register/login/logout flow",
|
|
15176
|
+
"Edge cases: duplicate email, invalid password, expired token"
|
|
15177
|
+
]
|
|
15178
|
+
}
|
|
15179
|
+
]
|
|
15180
|
+
},
|
|
15181
|
+
{
|
|
15182
|
+
keywords: ["crud", "resource", "api", "endpoint", "rest"],
|
|
15183
|
+
tasks: [
|
|
15184
|
+
{
|
|
15185
|
+
id: "crud-model",
|
|
15186
|
+
title: "Define data model and schema",
|
|
15187
|
+
type: "feature",
|
|
15188
|
+
risk: "medium",
|
|
15189
|
+
status: "pending",
|
|
15190
|
+
context_scope: "isolated",
|
|
15191
|
+
depends_on: [],
|
|
15192
|
+
acceptance_criteria: [
|
|
15193
|
+
"Entity definition with required fields",
|
|
15194
|
+
"Database migration script",
|
|
15195
|
+
"Schema follows project conventions"
|
|
15196
|
+
]
|
|
15197
|
+
},
|
|
15198
|
+
{
|
|
15199
|
+
id: "crud-service",
|
|
15200
|
+
title: "Implement repository/service layer",
|
|
15201
|
+
type: "feature",
|
|
15202
|
+
risk: "medium",
|
|
15203
|
+
status: "pending",
|
|
15204
|
+
context_scope: "isolated",
|
|
15205
|
+
depends_on: ["crud-model"],
|
|
15206
|
+
acceptance_criteria: [
|
|
15207
|
+
"Create, Read (list + by id), Update, Delete operations",
|
|
15208
|
+
"Input validation",
|
|
15209
|
+
"Error handling for not-found and conflict"
|
|
15210
|
+
]
|
|
15211
|
+
},
|
|
15212
|
+
{
|
|
15213
|
+
id: "crud-api",
|
|
15214
|
+
title: "Implement API endpoints",
|
|
15215
|
+
type: "feature",
|
|
15216
|
+
risk: "medium",
|
|
15217
|
+
status: "pending",
|
|
15218
|
+
context_scope: "isolated",
|
|
15219
|
+
depends_on: ["crud-service"],
|
|
15220
|
+
acceptance_criteria: [
|
|
15221
|
+
"REST endpoints for all CRUD operations",
|
|
15222
|
+
"Proper HTTP status codes",
|
|
15223
|
+
"Request/response schemas"
|
|
15224
|
+
]
|
|
15225
|
+
},
|
|
15226
|
+
{
|
|
15227
|
+
id: "crud-tests",
|
|
15228
|
+
title: "Write tests",
|
|
15229
|
+
type: "test",
|
|
15230
|
+
risk: "low",
|
|
15231
|
+
status: "pending",
|
|
15232
|
+
context_scope: "isolated",
|
|
15233
|
+
depends_on: ["crud-api"],
|
|
15234
|
+
acceptance_criteria: [
|
|
15235
|
+
"Unit tests for service layer",
|
|
15236
|
+
"Integration tests for API endpoints",
|
|
15237
|
+
"Edge cases covered"
|
|
15238
|
+
]
|
|
15239
|
+
}
|
|
15240
|
+
]
|
|
15241
|
+
},
|
|
15242
|
+
{
|
|
15243
|
+
keywords: ["search", "filter", "query", "full-text", "fts"],
|
|
15244
|
+
tasks: [
|
|
15245
|
+
{
|
|
15246
|
+
id: "search-schema",
|
|
15247
|
+
title: "Design search schema and indexing strategy",
|
|
15248
|
+
type: "feature",
|
|
15249
|
+
risk: "medium",
|
|
15250
|
+
status: "pending",
|
|
15251
|
+
context_scope: "isolated",
|
|
15252
|
+
depends_on: [],
|
|
15253
|
+
acceptance_criteria: [
|
|
15254
|
+
"Search index definition",
|
|
15255
|
+
"Indexing strategy documented",
|
|
15256
|
+
"Performance requirements defined"
|
|
15257
|
+
]
|
|
15258
|
+
},
|
|
15259
|
+
{
|
|
15260
|
+
id: "search-service",
|
|
15261
|
+
title: "Implement search service",
|
|
15262
|
+
type: "feature",
|
|
15263
|
+
risk: "medium",
|
|
15264
|
+
status: "pending",
|
|
15265
|
+
context_scope: "isolated",
|
|
15266
|
+
depends_on: ["search-schema"],
|
|
15267
|
+
acceptance_criteria: [
|
|
15268
|
+
"Full-text search with ranking",
|
|
15269
|
+
"Filter support",
|
|
15270
|
+
"Pagination"
|
|
15271
|
+
]
|
|
15272
|
+
},
|
|
15273
|
+
{
|
|
15274
|
+
id: "search-api",
|
|
15275
|
+
title: "Implement search API",
|
|
15276
|
+
type: "feature",
|
|
15277
|
+
risk: "low",
|
|
15278
|
+
status: "pending",
|
|
15279
|
+
context_scope: "isolated",
|
|
15280
|
+
depends_on: ["search-service"],
|
|
15281
|
+
acceptance_criteria: [
|
|
15282
|
+
"GET /search endpoint with query params",
|
|
15283
|
+
"Response includes results + metadata",
|
|
15284
|
+
"Rate limiting applied"
|
|
15285
|
+
]
|
|
15286
|
+
},
|
|
15287
|
+
{
|
|
15288
|
+
id: "search-tests",
|
|
15289
|
+
title: "Write search tests",
|
|
15290
|
+
type: "test",
|
|
15291
|
+
risk: "low",
|
|
15292
|
+
status: "pending",
|
|
15293
|
+
context_scope: "isolated",
|
|
15294
|
+
depends_on: ["search-api"],
|
|
15295
|
+
acceptance_criteria: [
|
|
15296
|
+
"Unit tests for search logic",
|
|
15297
|
+
"Integration tests with sample data",
|
|
15298
|
+
"Performance test for large datasets"
|
|
15299
|
+
]
|
|
15300
|
+
}
|
|
15301
|
+
]
|
|
15302
|
+
},
|
|
15303
|
+
{
|
|
15304
|
+
keywords: ["notification", "email", "alert", "push", "notify"],
|
|
15305
|
+
tasks: [
|
|
15306
|
+
{
|
|
15307
|
+
id: "notif-model",
|
|
15308
|
+
title: "Design notification data model",
|
|
15309
|
+
type: "feature",
|
|
15310
|
+
risk: "medium",
|
|
15311
|
+
status: "pending",
|
|
15312
|
+
context_scope: "isolated",
|
|
15313
|
+
depends_on: [],
|
|
15314
|
+
acceptance_criteria: [
|
|
15315
|
+
"Notification entity with type, payload, status, user_id",
|
|
15316
|
+
"Database migration",
|
|
15317
|
+
"Enum for notification types"
|
|
15318
|
+
]
|
|
15319
|
+
},
|
|
15320
|
+
{
|
|
15321
|
+
id: "notif-service",
|
|
15322
|
+
title: "Implement notification service",
|
|
15323
|
+
type: "feature",
|
|
15324
|
+
risk: "medium",
|
|
15325
|
+
status: "pending",
|
|
15326
|
+
context_scope: "isolated",
|
|
15327
|
+
depends_on: ["notif-model"],
|
|
15328
|
+
acceptance_criteria: [
|
|
15329
|
+
"Send notification by type",
|
|
15330
|
+
"Queue-based delivery",
|
|
15331
|
+
"Retry logic for failed deliveries"
|
|
15332
|
+
]
|
|
15333
|
+
},
|
|
15334
|
+
{
|
|
15335
|
+
id: "notif-api",
|
|
15336
|
+
title: "Implement notification API",
|
|
15337
|
+
type: "feature",
|
|
15338
|
+
risk: "low",
|
|
15339
|
+
status: "pending",
|
|
15340
|
+
context_scope: "isolated",
|
|
15341
|
+
depends_on: ["notif-service"],
|
|
15342
|
+
acceptance_criteria: [
|
|
15343
|
+
"POST /notifications endpoint",
|
|
15344
|
+
"GET /notifications endpoint with read/unread filter",
|
|
15345
|
+
"PATCH /notifications/:id/read endpoint"
|
|
15346
|
+
]
|
|
15347
|
+
},
|
|
15348
|
+
{
|
|
15349
|
+
id: "notif-tests",
|
|
15350
|
+
title: "Write notification tests",
|
|
15351
|
+
type: "test",
|
|
15352
|
+
risk: "low",
|
|
15353
|
+
status: "pending",
|
|
15354
|
+
context_scope: "isolated",
|
|
15355
|
+
depends_on: ["notif-api"],
|
|
15356
|
+
acceptance_criteria: [
|
|
15357
|
+
"Unit tests for notification logic",
|
|
15358
|
+
"Integration tests for API",
|
|
15359
|
+
"Edge cases: invalid type, missing user"
|
|
15360
|
+
]
|
|
15361
|
+
}
|
|
15362
|
+
]
|
|
15363
|
+
},
|
|
15364
|
+
{
|
|
15365
|
+
keywords: ["migration", "migrate", "schema change", "database change", "column"],
|
|
15366
|
+
tasks: [
|
|
15367
|
+
{
|
|
15368
|
+
id: "migrate-script",
|
|
15369
|
+
title: "Write migration script",
|
|
15370
|
+
type: "feature",
|
|
15371
|
+
risk: "high",
|
|
15372
|
+
status: "pending",
|
|
15373
|
+
context_scope: "isolated",
|
|
15374
|
+
depends_on: [],
|
|
15375
|
+
acceptance_criteria: [
|
|
15376
|
+
"Migration is reversible",
|
|
15377
|
+
"Handles existing data gracefully",
|
|
15378
|
+
"Rollback script included"
|
|
15379
|
+
]
|
|
15380
|
+
},
|
|
15381
|
+
{
|
|
15382
|
+
id: "migrate-model",
|
|
15383
|
+
title: "Update domain model",
|
|
15384
|
+
type: "refactor",
|
|
15385
|
+
risk: "medium",
|
|
15386
|
+
status: "pending",
|
|
15387
|
+
context_scope: "isolated",
|
|
15388
|
+
depends_on: ["migrate-script"],
|
|
15389
|
+
acceptance_criteria: [
|
|
15390
|
+
"Domain model reflects new schema",
|
|
15391
|
+
"Existing code paths updated",
|
|
15392
|
+
"Backward compatibility maintained"
|
|
15393
|
+
]
|
|
15394
|
+
},
|
|
15395
|
+
{
|
|
15396
|
+
id: "migrate-dal",
|
|
15397
|
+
title: "Update data access layer",
|
|
15398
|
+
type: "refactor",
|
|
15399
|
+
risk: "medium",
|
|
15400
|
+
status: "pending",
|
|
15401
|
+
context_scope: "isolated",
|
|
15402
|
+
depends_on: ["migrate-model"],
|
|
15403
|
+
acceptance_criteria: [
|
|
15404
|
+
"Repository/service reads/writes new schema",
|
|
15405
|
+
"No broken queries",
|
|
15406
|
+
"Performance not degraded"
|
|
15407
|
+
]
|
|
15408
|
+
},
|
|
15409
|
+
{
|
|
15410
|
+
id: "migrate-tests",
|
|
15411
|
+
title: "Write migration tests",
|
|
15412
|
+
type: "test",
|
|
15413
|
+
risk: "high",
|
|
15414
|
+
status: "pending",
|
|
15415
|
+
context_scope: "isolated",
|
|
15416
|
+
depends_on: ["migrate-dal"],
|
|
15417
|
+
acceptance_criteria: [
|
|
15418
|
+
"Migration up/down test",
|
|
15419
|
+
"Data integrity test",
|
|
15420
|
+
"Integration tests with new schema"
|
|
15421
|
+
]
|
|
15422
|
+
}
|
|
15423
|
+
]
|
|
15424
|
+
}
|
|
15425
|
+
];
|
|
15426
|
+
var GENERIC_TEMPLATE = [
|
|
15427
|
+
{
|
|
15428
|
+
id: "plan-scope",
|
|
15429
|
+
title: "Clarify requirements and scope",
|
|
15430
|
+
type: "feature",
|
|
15431
|
+
risk: "low",
|
|
15432
|
+
status: "pending",
|
|
15433
|
+
context_scope: "isolated",
|
|
15434
|
+
depends_on: [],
|
|
15435
|
+
acceptance_criteria: ["Objective is well-defined", "Scope boundaries identified"]
|
|
15436
|
+
},
|
|
15437
|
+
{
|
|
15438
|
+
id: "plan-design",
|
|
15439
|
+
title: "Design technical approach",
|
|
15440
|
+
type: "feature",
|
|
15441
|
+
risk: "medium",
|
|
15442
|
+
status: "pending",
|
|
15443
|
+
context_scope: "isolated",
|
|
15444
|
+
depends_on: ["plan-scope"],
|
|
15445
|
+
acceptance_criteria: ["Architecture decisions documented", "API contracts defined"]
|
|
15446
|
+
},
|
|
15447
|
+
{
|
|
15448
|
+
id: "plan-impl",
|
|
15449
|
+
title: "Implement solution",
|
|
15450
|
+
type: "feature",
|
|
15451
|
+
risk: "medium",
|
|
15452
|
+
status: "pending",
|
|
15453
|
+
context_scope: "isolated",
|
|
15454
|
+
depends_on: ["plan-design"],
|
|
15455
|
+
acceptance_criteria: ["Core functionality implemented", "Follows project conventions"]
|
|
15456
|
+
},
|
|
15457
|
+
{
|
|
15458
|
+
id: "plan-tests",
|
|
15459
|
+
title: "Write tests and verify",
|
|
15460
|
+
type: "test",
|
|
15461
|
+
risk: "low",
|
|
15462
|
+
status: "pending",
|
|
15463
|
+
context_scope: "isolated",
|
|
15464
|
+
depends_on: ["plan-impl"],
|
|
15465
|
+
acceptance_criteria: ["Unit tests pass", "Integration tests pass", "No regressions"]
|
|
15466
|
+
}
|
|
15467
|
+
];
|
|
15468
|
+
function matchTemplate(objective) {
|
|
15469
|
+
const lower = objective.toLowerCase();
|
|
15470
|
+
for (const template of TEMPLATES) {
|
|
15471
|
+
const matched = template.keywords.some((kw) => lower.includes(kw));
|
|
15472
|
+
if (matched)
|
|
15473
|
+
return template.tasks;
|
|
15474
|
+
}
|
|
15475
|
+
return GENERIC_TEMPLATE;
|
|
15476
|
+
}
|
|
15477
|
+
function planGoal(objective) {
|
|
15478
|
+
const tasks = matchTemplate(objective);
|
|
15479
|
+
return {
|
|
15480
|
+
objective,
|
|
15481
|
+
tasks: tasks.map((t) => ({ ...t, status: "pending" })),
|
|
15482
|
+
created_at: new Date().toISOString()
|
|
15483
|
+
};
|
|
15484
|
+
}
|
|
15485
|
+
|
|
15486
|
+
// src/core/goal/goal-state.ts
|
|
15487
|
+
init_dist();
|
|
15488
|
+
init_schemas();
|
|
15489
|
+
import { mkdir as mkdir7, readFile as readFile10, writeFile as writeFile6 } from "node:fs/promises";
|
|
15490
|
+
import { resolve as resolve10 } from "node:path";
|
|
15491
|
+
function validateGoalGraph(graph) {
|
|
15492
|
+
const ids = new Set(graph.tasks.map((t) => t.id));
|
|
15493
|
+
if (ids.size !== graph.tasks.length) {
|
|
15494
|
+
return err(new Error("Duplicate task IDs in goal graph"));
|
|
15495
|
+
}
|
|
15496
|
+
for (const task of graph.tasks) {
|
|
15497
|
+
for (const dep of task.depends_on ?? []) {
|
|
15498
|
+
if (!ids.has(dep)) {
|
|
15499
|
+
return err(new Error(`Task "${task.id}" depends on unknown task "${dep}"`));
|
|
15500
|
+
}
|
|
15501
|
+
}
|
|
15502
|
+
}
|
|
15503
|
+
const visited = new Set;
|
|
15504
|
+
const inStack = new Set;
|
|
15505
|
+
function dfs(taskId) {
|
|
15506
|
+
if (inStack.has(taskId))
|
|
15507
|
+
return true;
|
|
15508
|
+
if (visited.has(taskId))
|
|
15509
|
+
return false;
|
|
15510
|
+
visited.add(taskId);
|
|
15511
|
+
inStack.add(taskId);
|
|
15512
|
+
const task = graph.tasks.find((t) => t.id === taskId);
|
|
15513
|
+
if (task) {
|
|
15514
|
+
for (const dep of task.depends_on ?? []) {
|
|
15515
|
+
if (dfs(dep))
|
|
15516
|
+
return true;
|
|
15517
|
+
}
|
|
15518
|
+
}
|
|
15519
|
+
inStack.delete(taskId);
|
|
15520
|
+
return false;
|
|
15521
|
+
}
|
|
15522
|
+
for (const task of graph.tasks) {
|
|
15523
|
+
if (dfs(task.id)) {
|
|
15524
|
+
return err(new Error(`Cycle detected involving task "${task.id}"`));
|
|
15525
|
+
}
|
|
15526
|
+
}
|
|
15527
|
+
return ok(graph);
|
|
15528
|
+
}
|
|
15529
|
+
async function writeGoal(projectRoot, graph) {
|
|
15530
|
+
const validation = validateGoalGraph(graph);
|
|
15531
|
+
if (!validation.success)
|
|
15532
|
+
return validation;
|
|
15533
|
+
const dir = resolve10(projectRoot, ".codeconductor");
|
|
15534
|
+
await mkdir7(dir, { recursive: true });
|
|
15535
|
+
const yaml = $stringify(graph);
|
|
15536
|
+
await writeFile6(resolve10(dir, "current-goal.yml"), yaml, "utf-8");
|
|
15537
|
+
return ok(undefined);
|
|
15538
|
+
}
|
|
15539
|
+
|
|
15540
|
+
// src/commands/goal.command.ts
|
|
15541
|
+
function renderDependencyTree(tasks) {
|
|
15542
|
+
const lines = [];
|
|
15543
|
+
const taskMap = new Map(tasks.map((t) => [t.id, t]));
|
|
15544
|
+
const roots = tasks.filter((t) => !t.depends_on || t.depends_on.length === 0);
|
|
15545
|
+
function render(taskId, prefix, isLast) {
|
|
15546
|
+
const task = taskMap.get(taskId);
|
|
15547
|
+
if (!task)
|
|
15548
|
+
return;
|
|
15549
|
+
const connector = isLast ? "└── " : "├── ";
|
|
15550
|
+
const label = `${task.id}: ${task.title}`;
|
|
15551
|
+
lines.push(`${prefix}${connector}${label}`);
|
|
15552
|
+
const children = tasks.filter((t) => t.depends_on && t.depends_on.includes(taskId));
|
|
15553
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
15554
|
+
children.forEach((child, i) => {
|
|
15555
|
+
render(child.id, childPrefix, i === children.length - 1);
|
|
15556
|
+
});
|
|
15557
|
+
}
|
|
15558
|
+
roots.forEach((root, i) => {
|
|
15559
|
+
render(root.id, "", i === roots.length - 1);
|
|
15560
|
+
});
|
|
15561
|
+
return lines.join(`
|
|
15562
|
+
`);
|
|
15563
|
+
}
|
|
15564
|
+
async function goalCommand(options) {
|
|
15565
|
+
const { objective, projectRoot, output } = options;
|
|
15566
|
+
if (!objective || objective.trim().length === 0) {
|
|
15567
|
+
return {
|
|
15568
|
+
code: 1,
|
|
15569
|
+
data: {
|
|
15570
|
+
success: false,
|
|
15571
|
+
command: "goal",
|
|
15572
|
+
errors: ['Objective is required. Usage: codeconductor goal "<objective>"']
|
|
15573
|
+
}
|
|
15574
|
+
};
|
|
15575
|
+
}
|
|
15576
|
+
try {
|
|
15577
|
+
const graph = planGoal(objective);
|
|
15578
|
+
const writeResult = await writeGoal(projectRoot, graph);
|
|
15579
|
+
if (!writeResult.success) {
|
|
15580
|
+
return {
|
|
15581
|
+
code: 1,
|
|
15582
|
+
data: {
|
|
15583
|
+
success: false,
|
|
15584
|
+
command: "goal",
|
|
15585
|
+
errors: [`Failed to write goal: ${writeResult.error.message}`]
|
|
15586
|
+
}
|
|
15587
|
+
};
|
|
15588
|
+
}
|
|
15589
|
+
if (output === "json") {
|
|
15590
|
+
return {
|
|
15591
|
+
code: 0,
|
|
15592
|
+
data: {
|
|
15593
|
+
success: true,
|
|
15594
|
+
command: "goal",
|
|
15595
|
+
objective: graph.objective,
|
|
15596
|
+
tasks: graph.tasks,
|
|
15597
|
+
file: ".codeconductor/current-goal.yml"
|
|
15598
|
+
}
|
|
15599
|
+
};
|
|
15600
|
+
}
|
|
15601
|
+
const tree = renderDependencyTree(graph.tasks);
|
|
15602
|
+
const lines = [
|
|
15603
|
+
`Objective: ${graph.objective}`,
|
|
15604
|
+
"",
|
|
15605
|
+
"Task dependency graph:",
|
|
15606
|
+
tree,
|
|
15607
|
+
"",
|
|
15608
|
+
`Tasks: ${graph.tasks.length} total`,
|
|
15609
|
+
`File: .codeconductor/current-goal.yml`
|
|
15610
|
+
];
|
|
15611
|
+
return {
|
|
15612
|
+
code: 0,
|
|
15613
|
+
data: {
|
|
15614
|
+
success: true,
|
|
15615
|
+
command: "goal",
|
|
15616
|
+
output: lines.join(`
|
|
15617
|
+
`)
|
|
15618
|
+
}
|
|
15619
|
+
};
|
|
15620
|
+
} catch (e) {
|
|
15621
|
+
return {
|
|
15622
|
+
code: 1,
|
|
15623
|
+
data: {
|
|
15624
|
+
success: false,
|
|
15625
|
+
command: "goal",
|
|
15626
|
+
errors: [e instanceof Error ? e.message : String(e)]
|
|
15627
|
+
}
|
|
15628
|
+
};
|
|
15629
|
+
}
|
|
15630
|
+
}
|
|
15631
|
+
|
|
15084
15632
|
// src/commands/help.command.ts
|
|
15085
15633
|
import { readdir as readdir3 } from "node:fs/promises";
|
|
15086
15634
|
import { join as join8 } from "node:path";
|
|
@@ -15208,7 +15756,7 @@ async function helpCommand(options) {
|
|
|
15208
15756
|
}
|
|
15209
15757
|
|
|
15210
15758
|
// src/commands/seo-audit.command.ts
|
|
15211
|
-
import { writeFile as
|
|
15759
|
+
import { writeFile as writeFile7, mkdir as mkdir8 } from "node:fs/promises";
|
|
15212
15760
|
import { dirname as dirname4, resolve as resolve11 } from "node:path";
|
|
15213
15761
|
|
|
15214
15762
|
// src/infrastructure/http/safe-fetch.ts
|
|
@@ -16501,13 +17049,13 @@ async function seoAuditCommand(options) {
|
|
|
16501
17049
|
}
|
|
16502
17050
|
if (output) {
|
|
16503
17051
|
const outputPath = resolve11(options.projectRoot, output);
|
|
16504
|
-
await
|
|
16505
|
-
await
|
|
17052
|
+
await mkdir8(dirname4(outputPath), { recursive: true });
|
|
17053
|
+
await writeFile7(outputPath, formattedOutput, "utf-8");
|
|
16506
17054
|
} else if (format === "markdown") {
|
|
16507
17055
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16508
17056
|
const defaultPath = resolve11(options.projectRoot, "seo-reports", `audit-report-${timestamp}.md`);
|
|
16509
|
-
await
|
|
16510
|
-
await
|
|
17057
|
+
await mkdir8(dirname4(defaultPath), { recursive: true });
|
|
17058
|
+
await writeFile7(defaultPath, formattedOutput, "utf-8");
|
|
16511
17059
|
process.stderr.write(`Report saved to: ${defaultPath}
|
|
16512
17060
|
`);
|
|
16513
17061
|
}
|
|
@@ -16535,7 +17083,7 @@ async function seoAuditCommand(options) {
|
|
|
16535
17083
|
}
|
|
16536
17084
|
|
|
16537
17085
|
// src/commands/seo-llms.command.ts
|
|
16538
|
-
import { writeFile as
|
|
17086
|
+
import { writeFile as writeFile8, mkdir as mkdir9 } from "node:fs/promises";
|
|
16539
17087
|
import { dirname as dirname5, resolve as resolve12 } from "node:path";
|
|
16540
17088
|
|
|
16541
17089
|
// src/domain/seo/llms-generator.ts
|
|
@@ -16680,8 +17228,8 @@ async function seoLlmsCommand(options) {
|
|
|
16680
17228
|
}) : await generateLlmsTxtFromUrl(url);
|
|
16681
17229
|
process.stderr.write("\r" + " ".repeat(80) + "\r");
|
|
16682
17230
|
const outputPath = output ? resolve12(options.projectRoot, output) : resolve12(options.projectRoot, "llms.txt");
|
|
16683
|
-
await
|
|
16684
|
-
await
|
|
17231
|
+
await mkdir9(dirname5(outputPath), { recursive: true });
|
|
17232
|
+
await writeFile8(outputPath, result.content, "utf-8");
|
|
16685
17233
|
process.stderr.write(`Generated: ${outputPath} (${result.entries.length} entries)
|
|
16686
17234
|
`);
|
|
16687
17235
|
return {
|
|
@@ -16709,7 +17257,7 @@ async function seoLlmsCommand(options) {
|
|
|
16709
17257
|
// src/commands/update.command.ts
|
|
16710
17258
|
import { homedir as homedir9 } from "node:os";
|
|
16711
17259
|
import { resolve as resolve13, dirname as dirname6 } from "node:path";
|
|
16712
|
-
import { mkdir as
|
|
17260
|
+
import { mkdir as mkdir10, readFile as readFile11, writeFile as writeFile9, stat as stat3 } from "node:fs/promises";
|
|
16713
17261
|
init_package_paths();
|
|
16714
17262
|
async function updateCommand(options) {
|
|
16715
17263
|
const { dryRun, force, global: isGlobal, output, projectRoot } = options;
|
|
@@ -16778,9 +17326,9 @@ async function updateCommand(options) {
|
|
|
16778
17326
|
const localCouncil = resolve13(basePath, ".codeconductor", "presets", "council.yml");
|
|
16779
17327
|
const bundledCouncil = resolve13(SRC_PRESETS_DIR, "council", "council.yml");
|
|
16780
17328
|
try {
|
|
16781
|
-
const content = await
|
|
16782
|
-
await
|
|
16783
|
-
await
|
|
17329
|
+
const content = await readFile11(bundledCouncil, "utf-8");
|
|
17330
|
+
await mkdir10(dirname6(localCouncil), { recursive: true });
|
|
17331
|
+
await writeFile9(localCouncil, content, "utf-8");
|
|
16784
17332
|
updated.push(localCouncil);
|
|
16785
17333
|
} catch (e) {
|
|
16786
17334
|
throw new Error(`Failed to update council.yml: ${e}`);
|
|
@@ -16789,9 +17337,9 @@ async function updateCommand(options) {
|
|
|
16789
17337
|
if (updateResults.policy) {
|
|
16790
17338
|
const localPolicy = resolve13(basePath, ".codeconductor", "presets", "policy.yml");
|
|
16791
17339
|
try {
|
|
16792
|
-
const content = await
|
|
16793
|
-
await
|
|
16794
|
-
await
|
|
17340
|
+
const content = await readFile11(POLICY_PATH, "utf-8");
|
|
17341
|
+
await mkdir10(dirname6(localPolicy), { recursive: true });
|
|
17342
|
+
await writeFile9(localPolicy, content, "utf-8");
|
|
16795
17343
|
updated.push(localPolicy);
|
|
16796
17344
|
} catch (e) {
|
|
16797
17345
|
throw new Error(`Failed to update policy.yml: ${e}`);
|
|
@@ -16887,8 +17435,8 @@ async function updateCommand(options) {
|
|
|
16887
17435
|
}
|
|
16888
17436
|
} catch {}
|
|
16889
17437
|
try {
|
|
16890
|
-
await
|
|
16891
|
-
await
|
|
17438
|
+
await mkdir10(dirname6(lockDest), { recursive: true });
|
|
17439
|
+
await writeFile9(lockDest, JSON.stringify(newSkillsLock, null, 2), "utf-8");
|
|
16892
17440
|
updated.push(lockDest);
|
|
16893
17441
|
} catch (e) {
|
|
16894
17442
|
throw new Error(`Failed to write skills-lock.json: ${e}`);
|
|
@@ -16999,6 +17547,7 @@ Commands:
|
|
|
16999
17547
|
update Update installed presets
|
|
17000
17548
|
help / cc-help Show preset inventory (skills, subagents, commands)
|
|
17001
17549
|
debt-harvest / harvest Scan source files for deferred debt items
|
|
17550
|
+
goal / cc-goal Plan goal into task graph with dependencies
|
|
17002
17551
|
|
|
17003
17552
|
Options:
|
|
17004
17553
|
--help, -h Show this help message
|
|
@@ -17124,6 +17673,13 @@ async function routeCommand(args, projectRoot) {
|
|
|
17124
17673
|
dir: options.dir,
|
|
17125
17674
|
output: flags.output
|
|
17126
17675
|
});
|
|
17676
|
+
case "goal":
|
|
17677
|
+
case "cc-goal":
|
|
17678
|
+
return goalCommand({
|
|
17679
|
+
objective: subcommand || options.objective || "",
|
|
17680
|
+
projectRoot,
|
|
17681
|
+
output: flags.output
|
|
17682
|
+
});
|
|
17127
17683
|
case "seo": {
|
|
17128
17684
|
if (subcommand === "audit") {
|
|
17129
17685
|
return seoAuditCommand({
|
package/package.json
CHANGED
package/presets/agy/AGENTS.md
CHANGED
|
@@ -248,6 +248,30 @@ High-risk checkpoint: [yes | no — if yes, describe what triggers a stop]
|
|
|
248
248
|
|
|
249
249
|
---
|
|
250
250
|
|
|
251
|
+
### goal-planner
|
|
252
|
+
|
|
253
|
+
**Role:** Transforms an objective string into a YAML task graph with dependencies. Pure function: objective → GoalGraph. No side effects.
|
|
254
|
+
|
|
255
|
+
**Use when:** User runs `codeconductor goal "<objective>"` or the orchestrator needs a multi-step plan before delegation.
|
|
256
|
+
|
|
257
|
+
**Permissions:**
|
|
258
|
+
- read: `allow`
|
|
259
|
+
- edit: `deny`
|
|
260
|
+
- bash: `deny`
|
|
261
|
+
- network: `deny`
|
|
262
|
+
|
|
263
|
+
**Model:** `{{MODEL_GEMINI}}`
|
|
264
|
+
|
|
265
|
+
**Does not:** Write files. Execute commands. Make routing decisions.
|
|
266
|
+
|
|
267
|
+
**Template matching:**
|
|
268
|
+
The planner matches objective keywords against built-in templates (auth, crud, search, notification, migration) and falls back to a generic 4-task chain: task-coach → architect → implementer → tester.
|
|
269
|
+
|
|
270
|
+
**Dependency order delegation (orchestrator):**
|
|
271
|
+
When the orchestrator receives a GoalGraph, it delegates tasks in dependency order. A task is only routed after all its `depends_on` targets complete with status `done`. If a dependency is `blocked`, the dependent task remains `pending`. The orchestrator tracks the graph state in `.codeconductor/current-goal.yml`.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
251
275
|
### architect
|
|
252
276
|
|
|
253
277
|
**Role:** Designs the technical approach. Produces ADRs, module boundaries, and API contracts.
|
package/presets/codex/AGENTS.md
CHANGED
|
@@ -790,6 +790,40 @@ module, or identifying the impact radius of a change.
|
|
|
790
790
|
|
|
791
791
|
---
|
|
792
792
|
|
|
793
|
+
### goal-planner
|
|
794
|
+
|
|
795
|
+
**Role:** Transforms an objective string into a YAML task graph with
|
|
796
|
+
dependencies. Pure function: objective → GoalGraph. No side effects.
|
|
797
|
+
|
|
798
|
+
**Use when:** User runs `codeconductor goal "<objective>"` or the orchestrator
|
|
799
|
+
needs a multi-step plan before delegation.
|
|
800
|
+
|
|
801
|
+
**Permissions:**
|
|
802
|
+
|
|
803
|
+
- read: `allow`
|
|
804
|
+
- edit: `deny`
|
|
805
|
+
- bash: `deny`
|
|
806
|
+
- network: `deny`
|
|
807
|
+
|
|
808
|
+
**Does not:** Write files. Execute commands. Make routing decisions.
|
|
809
|
+
|
|
810
|
+
**Template matching:**
|
|
811
|
+
|
|
812
|
+
The planner matches objective keywords against built-in templates (auth, crud,
|
|
813
|
+
search, notification, migration) and falls back to a generic 4-task chain:
|
|
814
|
+
`task-coach → architect → implementer → tester`.
|
|
815
|
+
|
|
816
|
+
**Dependency order delegation (orchestrator):**
|
|
817
|
+
|
|
818
|
+
When the orchestrator receives a GoalGraph, it delegates tasks in dependency
|
|
819
|
+
order. A task is only routed after all its `depends_on` targets complete with
|
|
820
|
+
status `done`. If a dependency is `blocked`, the dependent task remains `pending`.
|
|
821
|
+
The orchestrator tracks the graph state in `.codeconductor/current-goal.yml`.
|
|
822
|
+
|
|
823
|
+
**Model:** `{{MODEL_CODEX}}`
|
|
824
|
+
|
|
825
|
+
---
|
|
826
|
+
|
|
793
827
|
## Hard Rules (all agents)
|
|
794
828
|
|
|
795
829
|
These apply regardless of agent or task.
|
|
@@ -57,6 +57,13 @@ agents:
|
|
|
57
57
|
gemini: gemini-2.5-flash
|
|
58
58
|
cursor: gpt-5.4-mini
|
|
59
59
|
agy: gemini-2.5-flash
|
|
60
|
+
goal-planner:
|
|
61
|
+
claude: claude-haiku-4-5-20251001
|
|
62
|
+
opencode: opencode-go/qwen3.6-plus
|
|
63
|
+
codex: gpt-5.4-mini
|
|
64
|
+
gemini: gemini-2.5-flash
|
|
65
|
+
cursor: gpt-5.4-mini
|
|
66
|
+
agy: gemini-2.5-flash
|
|
60
67
|
tools:
|
|
61
68
|
Read:
|
|
62
69
|
agy: view_file
|
|
@@ -51,6 +51,12 @@ agents:
|
|
|
51
51
|
codex: gpt-5.4-mini
|
|
52
52
|
gemini: gemini-2.5-flash
|
|
53
53
|
cursor: gpt-5.4-mini
|
|
54
|
+
goal-planner:
|
|
55
|
+
claude: claude-haiku-4-5-20251001
|
|
56
|
+
opencode: opencode-go/qwen3.6-plus
|
|
57
|
+
codex: gpt-5.4-mini
|
|
58
|
+
gemini: gemini-2.5-flash
|
|
59
|
+
cursor: gpt-5.4-mini
|
|
54
60
|
tools:
|
|
55
61
|
Read:
|
|
56
62
|
claude: ViewCodeItem / ReadFile
|
|
@@ -52,6 +52,12 @@ agents:
|
|
|
52
52
|
codex: gpt-5.4-mini
|
|
53
53
|
gemini: gemini-2.5-flash
|
|
54
54
|
cursor: gpt-5.4-mini
|
|
55
|
+
goal-planner:
|
|
56
|
+
claude: claude-haiku-4-5-20251001
|
|
57
|
+
opencode: opencode-go/qwen3.6-plus
|
|
58
|
+
codex: gpt-5.4-mini
|
|
59
|
+
gemini: gemini-2.5-flash
|
|
60
|
+
cursor: gpt-5.4-mini
|
|
55
61
|
tools:
|
|
56
62
|
Read:
|
|
57
63
|
claude: ViewCodeItem / ReadFile
|
|
@@ -51,6 +51,12 @@ agents:
|
|
|
51
51
|
codex: gpt-5.4-mini
|
|
52
52
|
gemini: gemini-2.5-flash
|
|
53
53
|
cursor: gpt-5.4-mini
|
|
54
|
+
goal-planner:
|
|
55
|
+
claude: claude-haiku-4-5-20251001
|
|
56
|
+
opencode: opencode-go/qwen3.6-plus
|
|
57
|
+
codex: gpt-5.4-mini
|
|
58
|
+
gemini: gemini-2.5-flash
|
|
59
|
+
cursor: gpt-5.4-mini
|
|
54
60
|
tools:
|
|
55
61
|
Read:
|
|
56
62
|
claude: ViewCodeItem / ReadFile
|
|
@@ -51,6 +51,12 @@ agents:
|
|
|
51
51
|
codex: gpt-5.4-mini
|
|
52
52
|
gemini: gemini-2.5-flash
|
|
53
53
|
cursor: gpt-5.4-mini
|
|
54
|
+
goal-planner:
|
|
55
|
+
claude: claude-haiku-4-5-20251001
|
|
56
|
+
opencode: opencode-go/qwen3.6-plus
|
|
57
|
+
codex: gpt-5.4-mini
|
|
58
|
+
gemini: gemini-2.5-flash
|
|
59
|
+
cursor: gpt-5.4-mini
|
|
54
60
|
tools:
|
|
55
61
|
Read:
|
|
56
62
|
claude: ViewCodeItem / ReadFile
|
|
@@ -51,6 +51,12 @@ agents:
|
|
|
51
51
|
codex: gpt-5.4-mini
|
|
52
52
|
gemini: gemini-2.5-flash
|
|
53
53
|
cursor: gpt-5.4-mini
|
|
54
|
+
goal-planner:
|
|
55
|
+
claude: claude-haiku-4-5-20251001
|
|
56
|
+
opencode: opencode-go/deepseek-v4-flash
|
|
57
|
+
codex: gpt-5.4-mini
|
|
58
|
+
gemini: gemini-2.5-flash
|
|
59
|
+
cursor: gpt-5.4-mini
|
|
54
60
|
permissions:
|
|
55
61
|
Read: read
|
|
56
62
|
Write: edit
|