cc-codeconductor 0.3.3 → 0.4.0
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 +36 -2
- package/dist/index.js +552 -60
- package/package.json +1 -1
- package/policy.yml +12 -0
- package/presets/agy/AGENTS.md +42 -0
- package/presets/agy/skills/cc-review/SKILL.md +25 -1
- package/presets/claude/CLAUDE.md +69 -5
- package/presets/codex/AGENTS.md +52 -0
- package/presets/opencode/README.md +15 -0
- package/presets/opencode/agents/complexity-auditor.md +89 -0
package/dist/index.js
CHANGED
|
@@ -36,14 +36,15 @@ function getExitCode(error) {
|
|
|
36
36
|
}
|
|
37
37
|
return ExitCode.VALIDATION_ERROR;
|
|
38
38
|
}
|
|
39
|
-
var ExitCode, CliError, ValidationError, UnsafeOperationError;
|
|
39
|
+
var ExitCode, CliError, ValidationError, UnsafeOperationError, CredentialGuardError;
|
|
40
40
|
var init_errors = __esm(() => {
|
|
41
41
|
ExitCode = {
|
|
42
42
|
SUCCESS: 0,
|
|
43
43
|
VALIDATION_ERROR: 1,
|
|
44
44
|
UNSAFE_OPERATION: 2,
|
|
45
45
|
UNSUPPORTED_PROJECT: 3,
|
|
46
|
-
CONFIG_CONFLICT: 4
|
|
46
|
+
CONFIG_CONFLICT: 4,
|
|
47
|
+
CREDENTIAL_LEAK: 5
|
|
47
48
|
};
|
|
48
49
|
CliError = class CliError extends Error {
|
|
49
50
|
code;
|
|
@@ -67,14 +68,24 @@ var init_errors = __esm(() => {
|
|
|
67
68
|
this.name = "UnsafeOperationError";
|
|
68
69
|
}
|
|
69
70
|
};
|
|
71
|
+
CredentialGuardError = class CredentialGuardError extends CliError {
|
|
72
|
+
matches;
|
|
73
|
+
constructor(message, matches, details) {
|
|
74
|
+
super(message, ExitCode.CREDENTIAL_LEAK, details);
|
|
75
|
+
this.matches = matches;
|
|
76
|
+
this.name = "CredentialGuardError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
70
79
|
});
|
|
71
80
|
|
|
72
81
|
// src/core/filesystem/safety.ts
|
|
73
82
|
var exports_safety = {};
|
|
74
83
|
__export(exports_safety, {
|
|
75
84
|
validateWritePath: () => validateWritePath,
|
|
85
|
+
scanForCredentials: () => scanForCredentials,
|
|
76
86
|
isWritable: () => isWritable,
|
|
77
87
|
isProtectedPath: () => isProtectedPath,
|
|
88
|
+
isCredentialContent: () => isCredentialContent,
|
|
78
89
|
fileExists: () => fileExists
|
|
79
90
|
});
|
|
80
91
|
import { constants } from "node:fs";
|
|
@@ -103,6 +114,42 @@ async function isWritable(dir) {
|
|
|
103
114
|
return false;
|
|
104
115
|
}
|
|
105
116
|
}
|
|
117
|
+
function buildCredentialRegexes(patterns) {
|
|
118
|
+
return patterns.map((keyword) => new RegExp(`(?:${keyword})\\s*[:=]\\s*[^\\s]{8,}`, "i"));
|
|
119
|
+
}
|
|
120
|
+
function scanForCredentials(filePath, content, secretPatterns) {
|
|
121
|
+
const regexes = buildCredentialRegexes(secretPatterns);
|
|
122
|
+
const lines = content.split(`
|
|
123
|
+
`);
|
|
124
|
+
const matches = [];
|
|
125
|
+
for (let i = 0;i < lines.length; i++) {
|
|
126
|
+
const line = lines[i];
|
|
127
|
+
for (const regex of regexes) {
|
|
128
|
+
const m = regex.exec(line);
|
|
129
|
+
if (m) {
|
|
130
|
+
matches.push({
|
|
131
|
+
filePath,
|
|
132
|
+
line: i + 1,
|
|
133
|
+
pattern: regex.source,
|
|
134
|
+
matched: m[0]
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return matches;
|
|
140
|
+
}
|
|
141
|
+
function isCredentialContent(content, secretPatterns) {
|
|
142
|
+
const regexes = buildCredentialRegexes(secretPatterns);
|
|
143
|
+
const lines = content.split(`
|
|
144
|
+
`);
|
|
145
|
+
for (const line of lines) {
|
|
146
|
+
for (const regex of regexes) {
|
|
147
|
+
if (regex.test(line))
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
106
153
|
var PROTECTED_PATHS;
|
|
107
154
|
var init_safety = __esm(() => {
|
|
108
155
|
PROTECTED_PATHS = [".git", ".env", ".env.local", ".env.production", "secrets", "credentials"];
|
|
@@ -11079,7 +11126,7 @@ function validateCouncilSpec(data) {
|
|
|
11079
11126
|
function validateConfig(data) {
|
|
11080
11127
|
return CodeConductorConfigSchema.parse(data);
|
|
11081
11128
|
}
|
|
11082
|
-
var CouncilAgentSpecSchema, CouncilSpecSchema, ProjectProfileSchema, CodeConductorConfigSchema, RunnerTargetSchema, InstallStrategySchema, ManifestEntrySchema, InstallManifestSchema, ToolProviderNamesSchema, PermissionProviderNamesSchema, ModelConfigSchema;
|
|
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;
|
|
11083
11130
|
var init_schemas = __esm(() => {
|
|
11084
11131
|
init_zod();
|
|
11085
11132
|
CouncilAgentSpecSchema = exports_external.object({
|
|
@@ -11112,6 +11159,16 @@ var init_schemas = __esm(() => {
|
|
|
11112
11159
|
signals: exports_external.array(exports_external.string()),
|
|
11113
11160
|
confidence: exports_external.enum(["low", "medium", "high"])
|
|
11114
11161
|
});
|
|
11162
|
+
CompileCheckConfigSchema = exports_external.object({
|
|
11163
|
+
enabled: exports_external.boolean(),
|
|
11164
|
+
command: exports_external.string().optional(),
|
|
11165
|
+
timeoutMs: exports_external.number().positive().optional()
|
|
11166
|
+
});
|
|
11167
|
+
LoopConfigSchema = exports_external.object({
|
|
11168
|
+
enabled: exports_external.boolean().optional().default(true),
|
|
11169
|
+
maxIterations: exports_external.number().int().positive().optional().default(3),
|
|
11170
|
+
maxTokenBudget: exports_external.number().nonnegative().optional().default(0)
|
|
11171
|
+
});
|
|
11115
11172
|
CodeConductorConfigSchema = exports_external.object({
|
|
11116
11173
|
version: exports_external.string(),
|
|
11117
11174
|
project: exports_external.object({
|
|
@@ -11131,8 +11188,10 @@ var init_schemas = __esm(() => {
|
|
|
11131
11188
|
}),
|
|
11132
11189
|
safety: exports_external.object({
|
|
11133
11190
|
destructiveCommands: exports_external.array(exports_external.string()),
|
|
11134
|
-
secretPatterns: exports_external.array(exports_external.string())
|
|
11135
|
-
|
|
11191
|
+
secretPatterns: exports_external.array(exports_external.string()),
|
|
11192
|
+
compileCheck: CompileCheckConfigSchema.optional()
|
|
11193
|
+
}),
|
|
11194
|
+
loop: LoopConfigSchema.optional()
|
|
11136
11195
|
});
|
|
11137
11196
|
RunnerTargetSchema = exports_external.enum([
|
|
11138
11197
|
"opencode",
|
|
@@ -11176,6 +11235,80 @@ var init_schemas = __esm(() => {
|
|
|
11176
11235
|
tools: exports_external.record(exports_external.string(), ToolProviderNamesSchema).optional(),
|
|
11177
11236
|
permissions: PermissionProviderNamesSchema.optional()
|
|
11178
11237
|
});
|
|
11238
|
+
ContractTargetSchema = exports_external.enum([
|
|
11239
|
+
"claude",
|
|
11240
|
+
"opencode",
|
|
11241
|
+
"codex",
|
|
11242
|
+
"gemini",
|
|
11243
|
+
"cursor",
|
|
11244
|
+
"agy"
|
|
11245
|
+
]);
|
|
11246
|
+
ContractFormatSchema = exports_external.object({
|
|
11247
|
+
target: ContractTargetSchema,
|
|
11248
|
+
options: exports_external.record(exports_external.unknown()).optional()
|
|
11249
|
+
});
|
|
11250
|
+
AgentContractSchema = exports_external.object({
|
|
11251
|
+
council: CouncilSpecSchema,
|
|
11252
|
+
targets: exports_external.array(ContractFormatSchema),
|
|
11253
|
+
contractVersion: exports_external.string(),
|
|
11254
|
+
renderHints: exports_external.record(ContractTargetSchema, exports_external.record(exports_external.unknown())).optional()
|
|
11255
|
+
});
|
|
11256
|
+
CouncilFindingSchema = exports_external.object({
|
|
11257
|
+
category: exports_external.string(),
|
|
11258
|
+
severity: exports_external.enum(["info", "warning", "critical"]),
|
|
11259
|
+
message: exports_external.string(),
|
|
11260
|
+
agentId: exports_external.string()
|
|
11261
|
+
});
|
|
11262
|
+
CouncilVerdictInputSchema = exports_external.object({
|
|
11263
|
+
agentId: exports_external.string(),
|
|
11264
|
+
agentRole: exports_external.string(),
|
|
11265
|
+
status: exports_external.enum(["APPROVED", "REJECTED", "ABSTAIN"]),
|
|
11266
|
+
securityVeto: exports_external.boolean(),
|
|
11267
|
+
findings: exports_external.array(CouncilFindingSchema),
|
|
11268
|
+
summary: exports_external.string()
|
|
11269
|
+
});
|
|
11270
|
+
ConsensusConfigSchema = exports_external.object({
|
|
11271
|
+
algorithm: exports_external.enum(["majority", "unanimous"]),
|
|
11272
|
+
allowSecurityVeto: exports_external.boolean()
|
|
11273
|
+
});
|
|
11274
|
+
CouncilVerdictSchema = exports_external.object({
|
|
11275
|
+
status: exports_external.enum(["APPROVED", "REJECTED", "ESCALATED"]),
|
|
11276
|
+
totalAgents: exports_external.number(),
|
|
11277
|
+
approvedCount: exports_external.number(),
|
|
11278
|
+
rejectedCount: exports_external.number(),
|
|
11279
|
+
abstainedCount: exports_external.number(),
|
|
11280
|
+
vetoApplied: exports_external.boolean(),
|
|
11281
|
+
vetoByAgentId: exports_external.string().optional(),
|
|
11282
|
+
findings: exports_external.array(CouncilFindingSchema),
|
|
11283
|
+
summary: exports_external.string(),
|
|
11284
|
+
individualVerdicts: exports_external.array(CouncilVerdictInputSchema)
|
|
11285
|
+
});
|
|
11286
|
+
ClaudeAgentFileSchema = exports_external.object({
|
|
11287
|
+
path: exports_external.string().startsWith(".claude/"),
|
|
11288
|
+
content: exports_external.string(),
|
|
11289
|
+
overwrite: exports_external.boolean()
|
|
11290
|
+
});
|
|
11291
|
+
OpenCodeAgentFileSchema = exports_external.object({
|
|
11292
|
+
path: exports_external.string().startsWith(".opencode/"),
|
|
11293
|
+
content: exports_external.string(),
|
|
11294
|
+
overwrite: exports_external.boolean()
|
|
11295
|
+
});
|
|
11296
|
+
SentryStackFrameSchema = exports_external.object({
|
|
11297
|
+
filename: exports_external.string(),
|
|
11298
|
+
function: exports_external.string(),
|
|
11299
|
+
lineNo: exports_external.number(),
|
|
11300
|
+
colNo: exports_external.number().optional(),
|
|
11301
|
+
context: exports_external.array(exports_external.string())
|
|
11302
|
+
});
|
|
11303
|
+
SentryWebhookSchema = exports_external.object({
|
|
11304
|
+
issueId: exports_external.string(),
|
|
11305
|
+
title: exports_external.string(),
|
|
11306
|
+
culprit: exports_external.string(),
|
|
11307
|
+
filename: exports_external.string().optional(),
|
|
11308
|
+
stackTrace: exports_external.array(SentryStackFrameSchema),
|
|
11309
|
+
environment: exports_external.string().optional(),
|
|
11310
|
+
release: exports_external.string().optional()
|
|
11311
|
+
});
|
|
11179
11312
|
});
|
|
11180
11313
|
|
|
11181
11314
|
// src/core/presets/package-paths.ts
|
|
@@ -11865,6 +11998,59 @@ var init_agy_installer = __esm(() => {
|
|
|
11865
11998
|
init_agy_council_generator();
|
|
11866
11999
|
});
|
|
11867
12000
|
|
|
12001
|
+
// src/core/filesystem/credential-guard.ts
|
|
12002
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
12003
|
+
import { resolve as resolve6 } from "node:path";
|
|
12004
|
+
async function loadPolicyPatterns() {
|
|
12005
|
+
try {
|
|
12006
|
+
const content = await readFile7(POLICY_PATH2, "utf-8");
|
|
12007
|
+
const parsed = $parse(content);
|
|
12008
|
+
if (Array.isArray(parsed.secretPatterns) && parsed.secretPatterns.length > 0) {
|
|
12009
|
+
return parsed.secretPatterns;
|
|
12010
|
+
}
|
|
12011
|
+
} catch {}
|
|
12012
|
+
return [];
|
|
12013
|
+
}
|
|
12014
|
+
function mergePatterns(...arrays) {
|
|
12015
|
+
const seen = new Set;
|
|
12016
|
+
const result = [];
|
|
12017
|
+
for (const arr of arrays) {
|
|
12018
|
+
for (const p of arr) {
|
|
12019
|
+
if (!seen.has(p)) {
|
|
12020
|
+
seen.add(p);
|
|
12021
|
+
result.push(p);
|
|
12022
|
+
}
|
|
12023
|
+
}
|
|
12024
|
+
}
|
|
12025
|
+
return result;
|
|
12026
|
+
}
|
|
12027
|
+
async function loadCredentialPatterns(config) {
|
|
12028
|
+
const policyPatterns = await loadPolicyPatterns();
|
|
12029
|
+
const configPatterns = config?.safety?.secretPatterns;
|
|
12030
|
+
if (configPatterns && configPatterns.length > 0) {
|
|
12031
|
+
return mergePatterns(configPatterns, policyPatterns, DEFAULT_SECRET_PATTERNS);
|
|
12032
|
+
}
|
|
12033
|
+
if (policyPatterns.length > 0) {
|
|
12034
|
+
return mergePatterns(policyPatterns, DEFAULT_SECRET_PATTERNS);
|
|
12035
|
+
}
|
|
12036
|
+
return DEFAULT_SECRET_PATTERNS;
|
|
12037
|
+
}
|
|
12038
|
+
var DEFAULT_SECRET_PATTERNS, POLICY_PATH2;
|
|
12039
|
+
var init_credential_guard = __esm(() => {
|
|
12040
|
+
init_dist();
|
|
12041
|
+
DEFAULT_SECRET_PATTERNS = [
|
|
12042
|
+
"password",
|
|
12043
|
+
"secret",
|
|
12044
|
+
"api_key",
|
|
12045
|
+
"token",
|
|
12046
|
+
"api[_-]?key",
|
|
12047
|
+
"access[_-]?token",
|
|
12048
|
+
"auth[_-]?token",
|
|
12049
|
+
"private[_-]?key"
|
|
12050
|
+
];
|
|
12051
|
+
POLICY_PATH2 = resolve6(import.meta.dir, "..", "..", "..", "policy.yml");
|
|
12052
|
+
});
|
|
12053
|
+
|
|
11868
12054
|
// src/core/filesystem/file-writer.ts
|
|
11869
12055
|
var exports_file_writer = {};
|
|
11870
12056
|
__export(exports_file_writer, {
|
|
@@ -11875,6 +12061,13 @@ import { access as access4, mkdir as mkdir4, writeFile as writeFile4 } from "nod
|
|
|
11875
12061
|
import { dirname as dirname3 } from "node:path";
|
|
11876
12062
|
async function writeGeneratedFiles(files, options) {
|
|
11877
12063
|
const results = [];
|
|
12064
|
+
const secretPatterns = await loadCredentialPatterns(options.config);
|
|
12065
|
+
const allMatches = files.flatMap((file) => {
|
|
12066
|
+
return scanForCredentials(file.path, file.content, secretPatterns);
|
|
12067
|
+
});
|
|
12068
|
+
if (allMatches.length > 0) {
|
|
12069
|
+
throw new CredentialGuardError(`Credential leak detected in ${allMatches.length} file(s). No files written.`, allMatches);
|
|
12070
|
+
}
|
|
11878
12071
|
for (const file of files) {
|
|
11879
12072
|
if (!validateWritePath(file.path)) {
|
|
11880
12073
|
results.push({
|
|
@@ -11933,6 +12126,7 @@ async function writeSingleFile(path, content, options) {
|
|
|
11933
12126
|
}
|
|
11934
12127
|
var init_file_writer = __esm(() => {
|
|
11935
12128
|
init_errors();
|
|
12129
|
+
init_credential_guard();
|
|
11936
12130
|
init_safety();
|
|
11937
12131
|
});
|
|
11938
12132
|
|
|
@@ -11941,7 +12135,7 @@ init_errors();
|
|
|
11941
12135
|
// package.json
|
|
11942
12136
|
var package_default = {
|
|
11943
12137
|
name: "cc-codeconductor",
|
|
11944
|
-
version: "0.
|
|
12138
|
+
version: "0.4.0",
|
|
11945
12139
|
description: "A multi-agent orchestration framework for AI-assisted software engineering workflows.",
|
|
11946
12140
|
keywords: [
|
|
11947
12141
|
"ai",
|
|
@@ -13604,17 +13798,18 @@ async function doctorCommand(options) {
|
|
|
13604
13798
|
}
|
|
13605
13799
|
|
|
13606
13800
|
// src/commands/init.command.ts
|
|
13607
|
-
import { access as access3, mkdir as mkdir3, readFile as
|
|
13801
|
+
import { access as access3, mkdir as mkdir3, readFile as readFile8, writeFile as writeFile3 } from "node:fs/promises";
|
|
13608
13802
|
import { homedir as homedir5 } from "node:os";
|
|
13609
|
-
import { basename, resolve as
|
|
13803
|
+
import { basename, resolve as resolve8 } from "node:path";
|
|
13610
13804
|
|
|
13611
13805
|
// src/core/config/config-writer.ts
|
|
13612
13806
|
init_dist();
|
|
13613
13807
|
init_errors();
|
|
13614
13808
|
import { access as access2, mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
13615
|
-
import { resolve as
|
|
13809
|
+
import { resolve as resolve7 } from "node:path";
|
|
13616
13810
|
|
|
13617
13811
|
// src/core/config/codeconductor-config.ts
|
|
13812
|
+
init_credential_guard();
|
|
13618
13813
|
var DEFAULT_CONFIG = {
|
|
13619
13814
|
version: "0.2.0",
|
|
13620
13815
|
project: {
|
|
@@ -13633,7 +13828,17 @@ var DEFAULT_CONFIG = {
|
|
|
13633
13828
|
},
|
|
13634
13829
|
safety: {
|
|
13635
13830
|
destructiveCommands: ["rm -rf", "drop table", "delete from"],
|
|
13636
|
-
secretPatterns:
|
|
13831
|
+
secretPatterns: DEFAULT_SECRET_PATTERNS,
|
|
13832
|
+
compileCheck: {
|
|
13833
|
+
enabled: true,
|
|
13834
|
+
command: "tsc --noEmit",
|
|
13835
|
+
timeoutMs: 120000
|
|
13836
|
+
}
|
|
13837
|
+
},
|
|
13838
|
+
loop: {
|
|
13839
|
+
enabled: true,
|
|
13840
|
+
maxIterations: 3,
|
|
13841
|
+
maxTokenBudget: 0
|
|
13637
13842
|
}
|
|
13638
13843
|
};
|
|
13639
13844
|
|
|
@@ -13642,9 +13847,9 @@ var CONFIG_DIR = ".codeconductor";
|
|
|
13642
13847
|
var CONFIG_FILE2 = "config.yml";
|
|
13643
13848
|
async function writeConfig(projectRoot, config = {}, force = false) {
|
|
13644
13849
|
try {
|
|
13645
|
-
const configDir =
|
|
13850
|
+
const configDir = resolve7(projectRoot, CONFIG_DIR);
|
|
13646
13851
|
await mkdir2(configDir, { recursive: true });
|
|
13647
|
-
const configPath =
|
|
13852
|
+
const configPath = resolve7(configDir, CONFIG_FILE2);
|
|
13648
13853
|
if (!force) {
|
|
13649
13854
|
try {
|
|
13650
13855
|
await access2(configPath);
|
|
@@ -13870,7 +14075,7 @@ async function initCommand(options) {
|
|
|
13870
14075
|
}
|
|
13871
14076
|
async function resolvePresetsToCopy() {
|
|
13872
14077
|
const sources = [];
|
|
13873
|
-
const bundledCouncil =
|
|
14078
|
+
const bundledCouncil = resolve8(SRC_PRESETS_DIR, "council", "council.yml");
|
|
13874
14079
|
if (await fileExists2(bundledCouncil)) {
|
|
13875
14080
|
sources.push({ name: "council.yml", sourcePath: bundledCouncil });
|
|
13876
14081
|
}
|
|
@@ -13881,16 +14086,16 @@ async function resolvePresetsToCopy() {
|
|
|
13881
14086
|
return sources;
|
|
13882
14087
|
}
|
|
13883
14088
|
async function copyPresets(baseDir, presets, force) {
|
|
13884
|
-
const presetsDir =
|
|
14089
|
+
const presetsDir = resolve8(baseDir, ".codeconductor", "presets");
|
|
13885
14090
|
await mkdir3(presetsDir, { recursive: true });
|
|
13886
14091
|
const copied = [];
|
|
13887
14092
|
for (const preset of presets) {
|
|
13888
|
-
const destPath =
|
|
14093
|
+
const destPath = resolve8(presetsDir, preset.name);
|
|
13889
14094
|
if (!force && await fileExists2(destPath)) {
|
|
13890
14095
|
continue;
|
|
13891
14096
|
}
|
|
13892
14097
|
try {
|
|
13893
|
-
const content = await
|
|
14098
|
+
const content = await readFile8(preset.sourcePath, "utf-8");
|
|
13894
14099
|
await writeFile3(destPath, content, "utf-8");
|
|
13895
14100
|
copied.push(`.codeconductor/presets/${preset.name}`);
|
|
13896
14101
|
} catch (err2) {
|
|
@@ -13918,7 +14123,7 @@ init_claude_installer();
|
|
|
13918
14123
|
init_codex_installer();
|
|
13919
14124
|
init_opencode_installer();
|
|
13920
14125
|
import { homedir as homedir6 } from "node:os";
|
|
13921
|
-
import { resolve as
|
|
14126
|
+
import { resolve as resolve9 } from "node:path";
|
|
13922
14127
|
init_file_writer();
|
|
13923
14128
|
init_preset_loader();
|
|
13924
14129
|
|
|
@@ -13959,8 +14164,10 @@ async function installCommand(options) {
|
|
|
13959
14164
|
}
|
|
13960
14165
|
};
|
|
13961
14166
|
}
|
|
14167
|
+
const configResult = await loadConfig(projectRoot);
|
|
14168
|
+
const config = configResult.success ? configResult.data : undefined;
|
|
13962
14169
|
const spec = presetResult.data;
|
|
13963
|
-
const writeOptions = { dryRun, force };
|
|
14170
|
+
const writeOptions = { dryRun, force, config };
|
|
13964
14171
|
const allFiles = [];
|
|
13965
14172
|
for (const t of targets) {
|
|
13966
14173
|
let installer;
|
|
@@ -13986,12 +14193,12 @@ async function installCommand(options) {
|
|
|
13986
14193
|
let targetPath = f.path;
|
|
13987
14194
|
let targetBase = baseDir;
|
|
13988
14195
|
if ((t === "agy" || t === "gemini") && isGlobal) {
|
|
13989
|
-
targetBase =
|
|
14196
|
+
targetBase = resolve9(homedir6(), ".gemini", "config");
|
|
13990
14197
|
targetPath = targetPath.replace(/^\.agents\/?/, "");
|
|
13991
14198
|
}
|
|
13992
14199
|
return {
|
|
13993
14200
|
...f,
|
|
13994
|
-
path:
|
|
14201
|
+
path: resolve9(targetBase, targetPath)
|
|
13995
14202
|
};
|
|
13996
14203
|
});
|
|
13997
14204
|
const results = await writeGeneratedFiles(resolvedFiles, writeOptions);
|
|
@@ -14102,7 +14309,7 @@ async function installPresetCommand(options) {
|
|
|
14102
14309
|
|
|
14103
14310
|
// src/commands/install-lsp.command.ts
|
|
14104
14311
|
import { homedir as homedir8 } from "node:os";
|
|
14105
|
-
import { resolve as
|
|
14312
|
+
import { resolve as resolve10 } from "node:path";
|
|
14106
14313
|
|
|
14107
14314
|
// src/core/lsp/lsp-config-utils.ts
|
|
14108
14315
|
function getLanguageServerConfig(lspIds) {
|
|
@@ -14627,7 +14834,9 @@ async function installLspCommand(options) {
|
|
|
14627
14834
|
}
|
|
14628
14835
|
const installer = createLspInstaller();
|
|
14629
14836
|
const installReport = await installer.installAll(lsps, { dryRun });
|
|
14630
|
-
const
|
|
14837
|
+
const configResult = await loadConfig(projectRoot);
|
|
14838
|
+
const config = configResult.success ? configResult.data : undefined;
|
|
14839
|
+
const writeOptions = { dryRun, force, config };
|
|
14631
14840
|
const allConfigResults = [];
|
|
14632
14841
|
for (const t of targets) {
|
|
14633
14842
|
const generator = getLspConfigGenerator(t);
|
|
@@ -14637,7 +14846,7 @@ async function installLspCommand(options) {
|
|
|
14637
14846
|
const generatedFiles = generator.generate(installReport.results);
|
|
14638
14847
|
const resolvedFiles = generatedFiles.map((f) => ({
|
|
14639
14848
|
...f,
|
|
14640
|
-
path:
|
|
14849
|
+
path: resolve10(baseDir, f.path)
|
|
14641
14850
|
}));
|
|
14642
14851
|
const results = await writeGeneratedFiles(resolvedFiles, writeOptions);
|
|
14643
14852
|
for (const result of results) {
|
|
@@ -14729,9 +14938,278 @@ function getLspConfigGenerator(target) {
|
|
|
14729
14938
|
}
|
|
14730
14939
|
}
|
|
14731
14940
|
|
|
14941
|
+
// src/commands/debt-harvest.command.ts
|
|
14942
|
+
import { readdir as readdir2, readFile as readFile9, writeFile as writeFile5, mkdir as mkdir6 } from "node:fs/promises";
|
|
14943
|
+
import { join as join7, relative as relative2, extname } from "node:path";
|
|
14944
|
+
var DEFER_REGEX = /\/\/\s*defer\s*[-:]\s*(.+?)(?:\s*--(\w+))?\s*$/gm;
|
|
14945
|
+
var SOURCE_EXTENSIONS = new Set([
|
|
14946
|
+
".ts",
|
|
14947
|
+
".tsx",
|
|
14948
|
+
".js",
|
|
14949
|
+
".jsx",
|
|
14950
|
+
".mjs",
|
|
14951
|
+
".cjs",
|
|
14952
|
+
".go",
|
|
14953
|
+
".rs",
|
|
14954
|
+
".java",
|
|
14955
|
+
".kt",
|
|
14956
|
+
".swift",
|
|
14957
|
+
".cs",
|
|
14958
|
+
".php",
|
|
14959
|
+
".scala",
|
|
14960
|
+
".dart",
|
|
14961
|
+
".c",
|
|
14962
|
+
".cpp",
|
|
14963
|
+
".h",
|
|
14964
|
+
".hpp"
|
|
14965
|
+
]);
|
|
14966
|
+
async function walkDir(dir, extensions) {
|
|
14967
|
+
const results = [];
|
|
14968
|
+
try {
|
|
14969
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
14970
|
+
for (const entry of entries) {
|
|
14971
|
+
const fullPath = join7(dir, entry.name);
|
|
14972
|
+
if (entry.isDirectory()) {
|
|
14973
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
14974
|
+
continue;
|
|
14975
|
+
results.push(...await walkDir(fullPath, extensions));
|
|
14976
|
+
} else if (extensions.has(extname(entry.name))) {
|
|
14977
|
+
results.push(fullPath);
|
|
14978
|
+
}
|
|
14979
|
+
}
|
|
14980
|
+
} catch {}
|
|
14981
|
+
return results;
|
|
14982
|
+
}
|
|
14983
|
+
function extractDefers(content, filePath) {
|
|
14984
|
+
const entries = [];
|
|
14985
|
+
const lines = content.split(`
|
|
14986
|
+
`);
|
|
14987
|
+
for (let i = 0;i < lines.length; i++) {
|
|
14988
|
+
const line = lines[i];
|
|
14989
|
+
DEFER_REGEX.lastIndex = 0;
|
|
14990
|
+
const match = DEFER_REGEX.exec(line);
|
|
14991
|
+
if (match) {
|
|
14992
|
+
entries.push({
|
|
14993
|
+
file: filePath,
|
|
14994
|
+
line: i + 1,
|
|
14995
|
+
reason: match[1].trim(),
|
|
14996
|
+
tag: match[2]
|
|
14997
|
+
});
|
|
14998
|
+
}
|
|
14999
|
+
}
|
|
15000
|
+
return entries;
|
|
15001
|
+
}
|
|
15002
|
+
function renderLedger(entries) {
|
|
15003
|
+
const grouped = new Map;
|
|
15004
|
+
for (const entry of entries) {
|
|
15005
|
+
const tag = entry.tag ?? "unclassified";
|
|
15006
|
+
const group = grouped.get(tag) ?? [];
|
|
15007
|
+
group.push(entry);
|
|
15008
|
+
grouped.set(tag, group);
|
|
15009
|
+
}
|
|
15010
|
+
const lines = [
|
|
15011
|
+
"<!-- CODECONDUCTOR:BEGIN managed -->",
|
|
15012
|
+
"",
|
|
15013
|
+
"# Debt Ledger",
|
|
15014
|
+
"",
|
|
15015
|
+
"> Auto-generated by `codeconductor debt-harvest`. Do not edit manually.",
|
|
15016
|
+
""
|
|
15017
|
+
];
|
|
15018
|
+
const sortedTags = [...grouped.keys()].sort();
|
|
15019
|
+
for (const tag of sortedTags) {
|
|
15020
|
+
const tagEntries = grouped.get(tag);
|
|
15021
|
+
lines.push(`## ${tag}`);
|
|
15022
|
+
lines.push("");
|
|
15023
|
+
lines.push("| File | Line | Reason |");
|
|
15024
|
+
lines.push("| ---- | ---- | ------ |");
|
|
15025
|
+
for (const entry of tagEntries) {
|
|
15026
|
+
lines.push(`| ${entry.file} | ${entry.line} | ${entry.reason} |`);
|
|
15027
|
+
}
|
|
15028
|
+
lines.push("");
|
|
15029
|
+
}
|
|
15030
|
+
lines.push("<!-- CODECONDUCTOR:END managed -->");
|
|
15031
|
+
lines.push("");
|
|
15032
|
+
return lines.join(`
|
|
15033
|
+
`);
|
|
15034
|
+
}
|
|
15035
|
+
async function debtHarvestCommand(options) {
|
|
15036
|
+
const { projectRoot, dir = "src", output } = options;
|
|
15037
|
+
try {
|
|
15038
|
+
const targetDir = join7(projectRoot, dir);
|
|
15039
|
+
const files = await walkDir(targetDir, SOURCE_EXTENSIONS);
|
|
15040
|
+
const allEntries = [];
|
|
15041
|
+
for (const file of files) {
|
|
15042
|
+
const content = await readFile9(file, "utf-8");
|
|
15043
|
+
const entries = extractDefers(content, relative2(projectRoot, file));
|
|
15044
|
+
allEntries.push(...entries);
|
|
15045
|
+
}
|
|
15046
|
+
const ledgerDir = join7(projectRoot, ".codeconductor");
|
|
15047
|
+
await mkdir6(ledgerDir, { recursive: true });
|
|
15048
|
+
const ledgerPath = join7(ledgerDir, "debt-ledger.md");
|
|
15049
|
+
const ledgerContent = renderLedger(allEntries);
|
|
15050
|
+
await writeFile5(ledgerPath, ledgerContent, "utf-8");
|
|
15051
|
+
if (output === "json") {
|
|
15052
|
+
return {
|
|
15053
|
+
code: 0,
|
|
15054
|
+
data: {
|
|
15055
|
+
success: true,
|
|
15056
|
+
command: "debt-harvest",
|
|
15057
|
+
entries: allEntries,
|
|
15058
|
+
entryCount: allEntries.length,
|
|
15059
|
+
ledger: ledgerPath
|
|
15060
|
+
}
|
|
15061
|
+
};
|
|
15062
|
+
}
|
|
15063
|
+
return {
|
|
15064
|
+
code: 0,
|
|
15065
|
+
data: {
|
|
15066
|
+
success: true,
|
|
15067
|
+
command: "debt-harvest",
|
|
15068
|
+
message: `Found ${allEntries.length} deferred item(s) across ${files.length} file(s). Ledger written to ${ledgerPath}`,
|
|
15069
|
+
entries: allEntries
|
|
15070
|
+
}
|
|
15071
|
+
};
|
|
15072
|
+
} catch (error) {
|
|
15073
|
+
return {
|
|
15074
|
+
code: 1,
|
|
15075
|
+
data: {
|
|
15076
|
+
success: false,
|
|
15077
|
+
command: "debt-harvest",
|
|
15078
|
+
errors: [String(error)]
|
|
15079
|
+
}
|
|
15080
|
+
};
|
|
15081
|
+
}
|
|
15082
|
+
}
|
|
15083
|
+
|
|
15084
|
+
// src/commands/help.command.ts
|
|
15085
|
+
import { readdir as readdir3 } from "node:fs/promises";
|
|
15086
|
+
import { join as join8 } from "node:path";
|
|
15087
|
+
async function scanPresetDir(projectRoot, target) {
|
|
15088
|
+
const inventory = {
|
|
15089
|
+
target,
|
|
15090
|
+
skills: [],
|
|
15091
|
+
commands: [],
|
|
15092
|
+
agents: [],
|
|
15093
|
+
workflows: []
|
|
15094
|
+
};
|
|
15095
|
+
const presetDir = join8(projectRoot, "presets", target);
|
|
15096
|
+
try {
|
|
15097
|
+
const entries = await readdir3(presetDir, { withFileTypes: true });
|
|
15098
|
+
for (const entry of entries) {
|
|
15099
|
+
if (entry.isDirectory()) {
|
|
15100
|
+
const subDir = join8(presetDir, entry.name);
|
|
15101
|
+
const subEntries = await readdir3(subDir, { withFileTypes: true });
|
|
15102
|
+
for (const sub of subEntries) {
|
|
15103
|
+
if (sub.isFile()) {
|
|
15104
|
+
const itemName = sub.name.replace(/\.[^.]+$/, "");
|
|
15105
|
+
if (entry.name === "skills")
|
|
15106
|
+
inventory.skills.push(itemName);
|
|
15107
|
+
else if (entry.name === "commands")
|
|
15108
|
+
inventory.commands.push(itemName);
|
|
15109
|
+
else if (entry.name === "agents")
|
|
15110
|
+
inventory.agents.push(itemName);
|
|
15111
|
+
else if (entry.name === "workflows")
|
|
15112
|
+
inventory.workflows.push(itemName);
|
|
15113
|
+
} else if (sub.isDirectory()) {
|
|
15114
|
+
if (entry.name === "skills")
|
|
15115
|
+
inventory.skills.push(sub.name);
|
|
15116
|
+
else if (entry.name === "agents")
|
|
15117
|
+
inventory.agents.push(sub.name);
|
|
15118
|
+
}
|
|
15119
|
+
}
|
|
15120
|
+
}
|
|
15121
|
+
}
|
|
15122
|
+
} catch {}
|
|
15123
|
+
return inventory;
|
|
15124
|
+
}
|
|
15125
|
+
function renderHuman(inventory, defaultTarget) {
|
|
15126
|
+
const lines = [
|
|
15127
|
+
`CodeConductor Help — ${inventory.target}${inventory.target === defaultTarget ? " (active)" : ""}`,
|
|
15128
|
+
""
|
|
15129
|
+
];
|
|
15130
|
+
lines.push(`Skills (${inventory.skills.length}):`);
|
|
15131
|
+
if (inventory.skills.length === 0) {
|
|
15132
|
+
lines.push(" (none)");
|
|
15133
|
+
} else {
|
|
15134
|
+
for (const skill of inventory.skills.sort()) {
|
|
15135
|
+
lines.push(` - ${skill}`);
|
|
15136
|
+
}
|
|
15137
|
+
}
|
|
15138
|
+
lines.push("");
|
|
15139
|
+
lines.push(`Subagents (${inventory.agents.length}):`);
|
|
15140
|
+
if (inventory.agents.length === 0) {
|
|
15141
|
+
lines.push(" (none)");
|
|
15142
|
+
} else {
|
|
15143
|
+
for (const agent of inventory.agents.sort()) {
|
|
15144
|
+
lines.push(` - ${agent}`);
|
|
15145
|
+
}
|
|
15146
|
+
}
|
|
15147
|
+
lines.push("");
|
|
15148
|
+
lines.push(`Commands (${inventory.commands.length}):`);
|
|
15149
|
+
if (inventory.commands.length === 0) {
|
|
15150
|
+
lines.push(" (none)");
|
|
15151
|
+
} else {
|
|
15152
|
+
for (const cmd of inventory.commands.sort()) {
|
|
15153
|
+
lines.push(` - ${cmd}`);
|
|
15154
|
+
}
|
|
15155
|
+
}
|
|
15156
|
+
if (inventory.workflows.length > 0) {
|
|
15157
|
+
lines.push("");
|
|
15158
|
+
lines.push(`Workflows (${inventory.workflows.length}):`);
|
|
15159
|
+
for (const wf of inventory.workflows.sort()) {
|
|
15160
|
+
lines.push(` - ${wf}`);
|
|
15161
|
+
}
|
|
15162
|
+
}
|
|
15163
|
+
return lines.join(`
|
|
15164
|
+
`);
|
|
15165
|
+
}
|
|
15166
|
+
async function helpCommand(options) {
|
|
15167
|
+
const { projectRoot, target: overrideTarget, output } = options;
|
|
15168
|
+
try {
|
|
15169
|
+
let defaultTarget = "opencode";
|
|
15170
|
+
try {
|
|
15171
|
+
const configResult = await loadConfig(projectRoot);
|
|
15172
|
+
if (configResult.success) {
|
|
15173
|
+
defaultTarget = configResult.data.defaults.target;
|
|
15174
|
+
}
|
|
15175
|
+
} catch {}
|
|
15176
|
+
const target = overrideTarget ?? defaultTarget;
|
|
15177
|
+
const inventory = await scanPresetDir(projectRoot, target);
|
|
15178
|
+
if (output === "json") {
|
|
15179
|
+
return {
|
|
15180
|
+
code: 0,
|
|
15181
|
+
data: {
|
|
15182
|
+
success: true,
|
|
15183
|
+
command: "help",
|
|
15184
|
+
inventory,
|
|
15185
|
+
defaultTarget
|
|
15186
|
+
}
|
|
15187
|
+
};
|
|
15188
|
+
}
|
|
15189
|
+
return {
|
|
15190
|
+
code: 0,
|
|
15191
|
+
data: {
|
|
15192
|
+
success: true,
|
|
15193
|
+
command: "help",
|
|
15194
|
+
message: renderHuman(inventory, defaultTarget),
|
|
15195
|
+
inventory
|
|
15196
|
+
}
|
|
15197
|
+
};
|
|
15198
|
+
} catch (error) {
|
|
15199
|
+
return {
|
|
15200
|
+
code: 1,
|
|
15201
|
+
data: {
|
|
15202
|
+
success: false,
|
|
15203
|
+
command: "help",
|
|
15204
|
+
errors: [String(error)]
|
|
15205
|
+
}
|
|
15206
|
+
};
|
|
15207
|
+
}
|
|
15208
|
+
}
|
|
15209
|
+
|
|
14732
15210
|
// src/commands/seo-audit.command.ts
|
|
14733
|
-
import { writeFile as
|
|
14734
|
-
import { dirname as dirname4, resolve as
|
|
15211
|
+
import { writeFile as writeFile6, mkdir as mkdir7 } from "node:fs/promises";
|
|
15212
|
+
import { dirname as dirname4, resolve as resolve11 } from "node:path";
|
|
14735
15213
|
|
|
14736
15214
|
// src/infrastructure/http/safe-fetch.ts
|
|
14737
15215
|
import { lookup } from "node:dns/promises";
|
|
@@ -14818,7 +15296,7 @@ async function safeFetch(urlString, options = {}) {
|
|
|
14818
15296
|
}
|
|
14819
15297
|
}
|
|
14820
15298
|
async function delay(ms) {
|
|
14821
|
-
return new Promise((
|
|
15299
|
+
return new Promise((resolve11) => setTimeout(resolve11, ms));
|
|
14822
15300
|
}
|
|
14823
15301
|
|
|
14824
15302
|
// src/infrastructure/parsers/sitemap-parser.ts
|
|
@@ -16022,14 +16500,14 @@ async function seoAuditCommand(options) {
|
|
|
16022
16500
|
formattedOutput = formatCli(report);
|
|
16023
16501
|
}
|
|
16024
16502
|
if (output) {
|
|
16025
|
-
const outputPath =
|
|
16026
|
-
await
|
|
16027
|
-
await
|
|
16503
|
+
const outputPath = resolve11(options.projectRoot, output);
|
|
16504
|
+
await mkdir7(dirname4(outputPath), { recursive: true });
|
|
16505
|
+
await writeFile6(outputPath, formattedOutput, "utf-8");
|
|
16028
16506
|
} else if (format === "markdown") {
|
|
16029
16507
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16030
|
-
const defaultPath =
|
|
16031
|
-
await
|
|
16032
|
-
await
|
|
16508
|
+
const defaultPath = resolve11(options.projectRoot, "seo-reports", `audit-report-${timestamp}.md`);
|
|
16509
|
+
await mkdir7(dirname4(defaultPath), { recursive: true });
|
|
16510
|
+
await writeFile6(defaultPath, formattedOutput, "utf-8");
|
|
16033
16511
|
process.stderr.write(`Report saved to: ${defaultPath}
|
|
16034
16512
|
`);
|
|
16035
16513
|
}
|
|
@@ -16041,7 +16519,7 @@ async function seoAuditCommand(options) {
|
|
|
16041
16519
|
command: "seo audit",
|
|
16042
16520
|
report,
|
|
16043
16521
|
output: formattedOutput,
|
|
16044
|
-
outputFile: output ?
|
|
16522
|
+
outputFile: output ? resolve11(options.projectRoot, output) : format === "markdown" ? resolve11(options.projectRoot, "seo-reports") : undefined
|
|
16045
16523
|
}
|
|
16046
16524
|
};
|
|
16047
16525
|
} catch (error) {
|
|
@@ -16057,8 +16535,8 @@ async function seoAuditCommand(options) {
|
|
|
16057
16535
|
}
|
|
16058
16536
|
|
|
16059
16537
|
// src/commands/seo-llms.command.ts
|
|
16060
|
-
import { writeFile as
|
|
16061
|
-
import { dirname as dirname5, resolve as
|
|
16538
|
+
import { writeFile as writeFile7, mkdir as mkdir8 } from "node:fs/promises";
|
|
16539
|
+
import { dirname as dirname5, resolve as resolve12 } from "node:path";
|
|
16062
16540
|
|
|
16063
16541
|
// src/domain/seo/llms-generator.ts
|
|
16064
16542
|
function extractTitle2(html) {
|
|
@@ -16201,9 +16679,9 @@ async function seoLlmsCommand(options) {
|
|
|
16201
16679
|
}
|
|
16202
16680
|
}) : await generateLlmsTxtFromUrl(url);
|
|
16203
16681
|
process.stderr.write("\r" + " ".repeat(80) + "\r");
|
|
16204
|
-
const outputPath = output ?
|
|
16205
|
-
await
|
|
16206
|
-
await
|
|
16682
|
+
const outputPath = output ? resolve12(options.projectRoot, output) : resolve12(options.projectRoot, "llms.txt");
|
|
16683
|
+
await mkdir8(dirname5(outputPath), { recursive: true });
|
|
16684
|
+
await writeFile7(outputPath, result.content, "utf-8");
|
|
16207
16685
|
process.stderr.write(`Generated: ${outputPath} (${result.entries.length} entries)
|
|
16208
16686
|
`);
|
|
16209
16687
|
return {
|
|
@@ -16230,8 +16708,8 @@ async function seoLlmsCommand(options) {
|
|
|
16230
16708
|
|
|
16231
16709
|
// src/commands/update.command.ts
|
|
16232
16710
|
import { homedir as homedir9 } from "node:os";
|
|
16233
|
-
import { resolve as
|
|
16234
|
-
import { mkdir as
|
|
16711
|
+
import { resolve as resolve13, dirname as dirname6 } from "node:path";
|
|
16712
|
+
import { mkdir as mkdir9, readFile as readFile10, writeFile as writeFile8, stat as stat3 } from "node:fs/promises";
|
|
16235
16713
|
init_package_paths();
|
|
16236
16714
|
async function updateCommand(options) {
|
|
16237
16715
|
const { dryRun, force, global: isGlobal, output, projectRoot } = options;
|
|
@@ -16297,23 +16775,23 @@ async function updateCommand(options) {
|
|
|
16297
16775
|
}
|
|
16298
16776
|
const updated = [];
|
|
16299
16777
|
if (updateResults.council) {
|
|
16300
|
-
const localCouncil =
|
|
16301
|
-
const bundledCouncil =
|
|
16778
|
+
const localCouncil = resolve13(basePath, ".codeconductor", "presets", "council.yml");
|
|
16779
|
+
const bundledCouncil = resolve13(SRC_PRESETS_DIR, "council", "council.yml");
|
|
16302
16780
|
try {
|
|
16303
|
-
const content = await
|
|
16304
|
-
await
|
|
16305
|
-
await
|
|
16781
|
+
const content = await readFile10(bundledCouncil, "utf-8");
|
|
16782
|
+
await mkdir9(dirname6(localCouncil), { recursive: true });
|
|
16783
|
+
await writeFile8(localCouncil, content, "utf-8");
|
|
16306
16784
|
updated.push(localCouncil);
|
|
16307
16785
|
} catch (e) {
|
|
16308
16786
|
throw new Error(`Failed to update council.yml: ${e}`);
|
|
16309
16787
|
}
|
|
16310
16788
|
}
|
|
16311
16789
|
if (updateResults.policy) {
|
|
16312
|
-
const localPolicy =
|
|
16790
|
+
const localPolicy = resolve13(basePath, ".codeconductor", "presets", "policy.yml");
|
|
16313
16791
|
try {
|
|
16314
|
-
const content = await
|
|
16315
|
-
await
|
|
16316
|
-
await
|
|
16792
|
+
const content = await readFile10(POLICY_PATH, "utf-8");
|
|
16793
|
+
await mkdir9(dirname6(localPolicy), { recursive: true });
|
|
16794
|
+
await writeFile8(localPolicy, content, "utf-8");
|
|
16317
16795
|
updated.push(localPolicy);
|
|
16318
16796
|
} catch (e) {
|
|
16319
16797
|
throw new Error(`Failed to update policy.yml: ${e}`);
|
|
@@ -16365,17 +16843,17 @@ async function updateCommand(options) {
|
|
|
16365
16843
|
let targetPath = f.path;
|
|
16366
16844
|
let targetBase = basePath;
|
|
16367
16845
|
if ((targetName === "agy" || targetName === "gemini") && isGlobal) {
|
|
16368
|
-
targetBase =
|
|
16846
|
+
targetBase = resolve13(homedir9(), ".gemini", "config");
|
|
16369
16847
|
targetPath = targetPath.replace(/^\.agents\/?/, "");
|
|
16370
16848
|
}
|
|
16371
16849
|
return {
|
|
16372
16850
|
...f,
|
|
16373
|
-
path:
|
|
16851
|
+
path: resolve13(targetBase, targetPath)
|
|
16374
16852
|
};
|
|
16375
16853
|
});
|
|
16376
16854
|
const filesToWrite = resolvedFiles.filter((f) => t.files.includes(f.path));
|
|
16377
16855
|
if (filesToWrite.length > 0) {
|
|
16378
|
-
const writeResults = await writeGeneratedFiles2(filesToWrite, { dryRun: false, force: true });
|
|
16856
|
+
const writeResults = await writeGeneratedFiles2(filesToWrite, { dryRun: false, force: true, config });
|
|
16379
16857
|
for (const wr of writeResults) {
|
|
16380
16858
|
if (wr.success) {
|
|
16381
16859
|
updated.push(wr.path);
|
|
@@ -16398,19 +16876,19 @@ async function updateCommand(options) {
|
|
|
16398
16876
|
for (const s of updateResults.skills) {
|
|
16399
16877
|
newSkillsLock[s.id] = s.latestVersion;
|
|
16400
16878
|
}
|
|
16401
|
-
let lockDest =
|
|
16879
|
+
let lockDest = resolve13(basePath, ".codeconductor", "skills-lock.json");
|
|
16402
16880
|
try {
|
|
16403
|
-
const statAgents = await stat3(
|
|
16881
|
+
const statAgents = await stat3(resolve13(basePath, ".agents"));
|
|
16404
16882
|
if (statAgents.isDirectory()) {
|
|
16405
|
-
const statCodeConductor = await stat3(
|
|
16883
|
+
const statCodeConductor = await stat3(resolve13(basePath, ".codeconductor")).catch(() => null);
|
|
16406
16884
|
if (!statCodeConductor) {
|
|
16407
|
-
lockDest =
|
|
16885
|
+
lockDest = resolve13(basePath, ".agents", "skills-lock.json");
|
|
16408
16886
|
}
|
|
16409
16887
|
}
|
|
16410
16888
|
} catch {}
|
|
16411
16889
|
try {
|
|
16412
|
-
await
|
|
16413
|
-
await
|
|
16890
|
+
await mkdir9(dirname6(lockDest), { recursive: true });
|
|
16891
|
+
await writeFile8(lockDest, JSON.stringify(newSkillsLock, null, 2), "utf-8");
|
|
16414
16892
|
updated.push(lockDest);
|
|
16415
16893
|
} catch (e) {
|
|
16416
16894
|
throw new Error(`Failed to write skills-lock.json: ${e}`);
|
|
@@ -16519,6 +16997,8 @@ Commands:
|
|
|
16519
16997
|
seo llms Generate llms.txt from a URL or sitemap
|
|
16520
16998
|
doctor Validate configuration and generated files
|
|
16521
16999
|
update Update installed presets
|
|
17000
|
+
help / cc-help Show preset inventory (skills, subagents, commands)
|
|
17001
|
+
debt-harvest / harvest Scan source files for deferred debt items
|
|
16522
17002
|
|
|
16523
17003
|
Options:
|
|
16524
17004
|
--help, -h Show this help message
|
|
@@ -16562,8 +17042,6 @@ Examples:
|
|
|
16562
17042
|
async function routeCommand(args, projectRoot) {
|
|
16563
17043
|
const { command, subcommand, options, flags } = args;
|
|
16564
17044
|
switch (command) {
|
|
16565
|
-
case "help":
|
|
16566
|
-
return { code: 0, data: { help: getHelp() } };
|
|
16567
17045
|
case "init":
|
|
16568
17046
|
return initCommand({
|
|
16569
17047
|
projectRoot,
|
|
@@ -16632,6 +17110,20 @@ async function routeCommand(args, projectRoot) {
|
|
|
16632
17110
|
global: options.global === true || options.global === "true",
|
|
16633
17111
|
output: flags.output
|
|
16634
17112
|
});
|
|
17113
|
+
case "help":
|
|
17114
|
+
case "cc-help":
|
|
17115
|
+
return helpCommand({
|
|
17116
|
+
projectRoot,
|
|
17117
|
+
target: options.target,
|
|
17118
|
+
output: flags.output
|
|
17119
|
+
});
|
|
17120
|
+
case "debt-harvest":
|
|
17121
|
+
case "harvest":
|
|
17122
|
+
return debtHarvestCommand({
|
|
17123
|
+
projectRoot,
|
|
17124
|
+
dir: options.dir,
|
|
17125
|
+
output: flags.output
|
|
17126
|
+
});
|
|
16635
17127
|
case "seo": {
|
|
16636
17128
|
if (subcommand === "audit") {
|
|
16637
17129
|
return seoAuditCommand({
|