cc-codeconductor 1.4.2 → 1.5.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 +37 -12
- package/dist/index.js +291 -109
- package/docs/generated/cli.md +8 -0
- package/package.json +1 -1
- package/presets/agy/README.md +1 -1
- package/presets/agy/hooks.json +1 -1
- package/presets/agy/scripts/invoke-hook.cjs +20 -5
- package/presets/agy/settings.json +1 -1
- package/presets/agy/skills/api-versioning/SKILL.md +394 -0
- package/presets/agy/skills/astro/SKILL.md +318 -0
- package/presets/agy/skills/auth-token-inspector/SKILL.md +30 -0
- package/presets/agy/skills/cc-pagespeed/SKILL.md +2 -3
- package/presets/agy/skills/code-review/SKILL.md +207 -0
- package/presets/agy/skills/django-orm/SKILL.md +460 -0
- package/presets/agy/skills/django-uv/SKILL.md +405 -0
- package/presets/agy/skills/drizzle-schema-architect/SKILL.md +50 -0
- package/presets/agy/skills/fastapi-pydantic-strict/SKILL.md +43 -0
- package/presets/agy/skills/jpa-nplusone-detector/SKILL.md +45 -0
- package/presets/agy/skills/jpa-postgres/SKILL.md +623 -0
- package/presets/agy/skills/livewire-alpine-bridge/SKILL.md +35 -0
- package/presets/agy/skills/nextjs-typescript/SKILL.md +390 -0
- package/presets/agy/skills/python/SKILL.md +611 -0
- package/presets/agy/skills/seo-analytics-injector/SKILL.md +43 -0
- package/presets/agy/skills/spring-auth-auditor/SKILL.md +29 -0
- package/presets/agy/skills/spring-boot-feature/SKILL.md +563 -0
- package/presets/agy/skills/spring-boot-testing-strategy/SKILL.md +475 -0
- package/presets/agy/skills/tailwind-responsive-auditor/SKILL.md +29 -0
- package/presets/agy/skills/tdd-mutation-tester/SKILL.md +27 -0
- package/presets/agy/workflows/cc-pagespeed.md +2 -3
- package/presets/agy/workflows/cc-review.md +31 -0
- package/presets/agy/workflows/cc-security.md +1 -1
- package/presets/claude/commands/cc/review.md +33 -0
- package/presets/claude/settings.json +2 -2
- package/presets/claude/skills/android/SKILL.md +1 -1
- package/presets/claude/skills/api-versioning/SKILL.md +1 -1
- package/presets/claude/skills/astro/SKILL.md +318 -0
- package/presets/claude/skills/auth-token-inspector/SKILL.md +30 -0
- package/presets/claude/skills/code-review/SKILL.md +207 -0
- package/presets/claude/skills/django-orm/SKILL.md +1 -1
- package/presets/claude/skills/django-testing/SKILL.md +1 -1
- package/presets/claude/skills/django-uv/SKILL.md +405 -0
- package/presets/claude/skills/drizzle-schema-architect/SKILL.md +50 -0
- package/presets/claude/skills/fastapi-pydantic-strict/SKILL.md +43 -0
- package/presets/claude/skills/jpa-nplusone-detector/SKILL.md +45 -0
- package/presets/claude/skills/jpa-postgres/SKILL.md +1 -1
- package/presets/claude/skills/livewire-alpine-bridge/SKILL.md +35 -0
- package/presets/claude/skills/nextjs-typescript/SKILL.md +390 -0
- package/presets/claude/skills/pagespeed-perf/SKILL.md +1 -1
- package/presets/claude/skills/python/SKILL.md +1 -1
- package/presets/claude/skills/python-django-stack/SKILL.md +1 -1
- package/presets/claude/skills/python-fastapi-stack/SKILL.md +1 -1
- package/presets/claude/skills/security/SKILL.md +1 -1
- package/presets/claude/skills/seo-analytics-injector/SKILL.md +43 -0
- package/presets/claude/skills/spring-auth-auditor/SKILL.md +29 -0
- package/presets/claude/skills/spring-boot-feature/SKILL.md +1 -1
- package/presets/claude/skills/spring-boot-kotlin/SKILL.md +1 -1
- package/presets/claude/skills/spring-boot-testing-strategy/SKILL.md +475 -0
- package/presets/claude/skills/sqlalchemy/SKILL.md +1 -1
- package/presets/claude/skills/tailwind-responsive-auditor/SKILL.md +29 -0
- package/presets/claude/skills/tdd-mutation-tester/SKILL.md +27 -0
- package/presets/claude/skills/testing-strategy/SKILL.md +1 -1
- package/presets/codex/skills/android/SKILL.md +1 -1
- package/presets/codex/skills/api-versioning/SKILL.md +1 -1
- package/presets/codex/skills/astro/SKILL.md +318 -0
- package/presets/codex/skills/auth-token-inspector/SKILL.md +30 -0
- package/presets/codex/skills/cc-openspec/SKILL.md +1 -1
- package/presets/codex/skills/cc-pagespeed/SKILL.md +2 -3
- package/presets/codex/skills/cc-review/SKILL.md +31 -0
- package/presets/codex/skills/cc-security/SKILL.md +1 -1
- package/presets/codex/skills/code-review/SKILL.md +207 -0
- package/presets/codex/skills/django-orm/SKILL.md +1 -1
- package/presets/codex/skills/django-testing/SKILL.md +1 -1
- package/presets/codex/skills/django-uv/SKILL.md +405 -0
- package/presets/codex/skills/drizzle-schema-architect/SKILL.md +50 -0
- package/presets/codex/skills/fastapi-pydantic-strict/SKILL.md +43 -0
- package/presets/codex/skills/jpa-nplusone-detector/SKILL.md +45 -0
- package/presets/codex/skills/jpa-postgres/SKILL.md +1 -1
- package/presets/codex/skills/livewire-alpine-bridge/SKILL.md +35 -0
- package/presets/codex/skills/nextjs-typescript/SKILL.md +390 -0
- package/presets/codex/skills/pagespeed-perf/SKILL.md +1 -1
- package/presets/codex/skills/python/SKILL.md +1 -1
- package/presets/codex/skills/python-django-stack/SKILL.md +1 -1
- package/presets/codex/skills/python-fastapi-stack/SKILL.md +1 -1
- package/presets/codex/skills/security-ai-llm/SKILL.md +43 -0
- package/presets/codex/skills/security-blue-team/SKILL.md +43 -0
- package/presets/codex/skills/security-cloud/SKILL.md +43 -0
- package/presets/codex/skills/security-crypto/SKILL.md +43 -0
- package/presets/codex/skills/security-exploit-dev/SKILL.md +45 -0
- package/presets/codex/skills/security-grc/SKILL.md +43 -0
- package/presets/codex/skills/security-incident-response/SKILL.md +45 -0
- package/presets/codex/skills/security-log-analysis/SKILL.md +43 -0
- package/presets/codex/skills/security-malware-analysis/SKILL.md +44 -0
- package/presets/codex/skills/security-mobile/SKILL.md +43 -0
- package/presets/codex/skills/security-network/SKILL.md +43 -0
- package/presets/codex/skills/security-ot-ics/SKILL.md +43 -0
- package/presets/codex/skills/security-recon/SKILL.md +45 -0
- package/presets/codex/skills/security-red-team/SKILL.md +44 -0
- package/presets/codex/skills/security-reverse-engineering/SKILL.md +44 -0
- package/presets/codex/skills/security-soc-automation/SKILL.md +43 -0
- package/presets/codex/skills/security-threat-hunting/SKILL.md +43 -0
- package/presets/codex/skills/security-vuln-assessment/SKILL.md +45 -0
- package/presets/codex/skills/security-web/SKILL.md +44 -0
- package/presets/codex/skills/seo-analytics-injector/SKILL.md +43 -0
- package/presets/codex/skills/spring-auth-auditor/SKILL.md +29 -0
- package/presets/codex/skills/spring-boot-feature/SKILL.md +2 -2
- package/presets/codex/skills/spring-boot-kotlin/SKILL.md +1 -1
- package/presets/codex/skills/spring-boot-testing-strategy/SKILL.md +475 -0
- package/presets/codex/skills/sqlalchemy/SKILL.md +1 -1
- package/presets/codex/skills/tailwind-responsive-auditor/SKILL.md +29 -0
- package/presets/codex/skills/tdd-mutation-tester/SKILL.md +27 -0
- package/presets/codex/skills/testing-strategy/SKILL.md +1 -1
- package/presets/cursor/commands/cc/openspec.md +1 -1
- package/presets/cursor/commands/cc/pagespeed.md +2 -3
- package/presets/cursor/commands/cc/review.md +31 -0
- package/presets/cursor/commands/cc/security.md +1 -1
- package/presets/cursor/skills/android/SKILL.md +1 -1
- package/presets/cursor/skills/api-versioning/SKILL.md +2 -1
- package/presets/cursor/skills/astro/SKILL.md +1 -1
- package/presets/cursor/skills/auth-token-inspector/SKILL.md +1 -1
- package/presets/cursor/skills/code-review/SKILL.md +1 -1
- package/presets/cursor/skills/django-orm/SKILL.md +3 -5
- package/presets/cursor/skills/django-testing/SKILL.md +1 -1
- package/presets/cursor/skills/django-uv/SKILL.md +1 -1
- package/presets/cursor/skills/drizzle-schema-architect/SKILL.md +1 -1
- package/presets/cursor/skills/fastapi-pydantic-strict/SKILL.md +1 -1
- package/presets/cursor/skills/jpa-nplusone-detector/SKILL.md +1 -1
- package/presets/cursor/skills/jpa-postgres/SKILL.md +2 -4
- package/presets/cursor/skills/livewire-alpine-bridge/SKILL.md +1 -1
- package/presets/cursor/skills/nextjs-typescript/SKILL.md +1 -1
- package/presets/cursor/skills/pagespeed-perf/SKILL.md +1 -1
- package/presets/cursor/skills/python/SKILL.md +6 -7
- package/presets/cursor/skills/python-django-stack/SKILL.md +1 -1
- package/presets/cursor/skills/python-fastapi-stack/SKILL.md +1 -1
- package/presets/cursor/skills/security/SKILL.md +1 -1
- package/presets/cursor/skills/seo-analytics-injector/SKILL.md +1 -1
- package/presets/cursor/skills/spring-auth-auditor/SKILL.md +1 -1
- package/presets/cursor/skills/spring-boot-feature/SKILL.md +2 -4
- package/presets/cursor/skills/spring-boot-kotlin/SKILL.md +1 -1
- package/presets/cursor/skills/spring-boot-testing-strategy/SKILL.md +1 -1
- package/presets/cursor/skills/sqlalchemy/SKILL.md +1 -1
- package/presets/cursor/skills/tailwind-responsive-auditor/SKILL.md +1 -1
- package/presets/cursor/skills/tdd-mutation-tester/SKILL.md +1 -1
- package/presets/gemini/commands/cc/openspec.toml +1 -1
- package/presets/gemini/commands/cc/pagespeed.toml +2 -3
- package/presets/gemini/commands/cc/review.toml +31 -0
- package/presets/gemini/commands/cc/security.toml +1 -1
- package/presets/opencode/README.md +45 -52
- package/presets/opencode/commands/cc-pagespeed.md +2 -3
- package/presets/opencode/commands/cc-review.md +31 -0
- package/presets/opencode/commands/cc-security.md +1 -1
- package/presets/opencode/opencode.jsonc +1 -1
- package/presets/opencode/skills/android/SKILL.md +1 -1
- package/presets/opencode/skills/api-versioning/SKILL.md +2 -1
- package/presets/opencode/skills/astro/SKILL.md +1 -1
- package/presets/opencode/skills/auth-token-inspector/SKILL.md +1 -1
- package/presets/opencode/skills/code-review/SKILL.md +1 -1
- package/presets/opencode/skills/django-orm/SKILL.md +3 -3
- package/presets/opencode/skills/django-testing/SKILL.md +1 -1
- package/presets/opencode/skills/django-uv/SKILL.md +1 -1
- package/presets/opencode/skills/drizzle-schema-architect/SKILL.md +1 -1
- package/presets/opencode/skills/fastapi-pydantic-strict/SKILL.md +1 -1
- package/presets/opencode/skills/jpa-nplusone-detector/SKILL.md +1 -1
- package/presets/opencode/skills/jpa-postgres/SKILL.md +2 -1
- package/presets/opencode/skills/livewire-alpine-bridge/SKILL.md +1 -1
- package/presets/opencode/skills/nextjs-typescript/SKILL.md +1 -1
- package/presets/opencode/skills/pagespeed-perf/SKILL.md +1 -1
- package/presets/opencode/skills/python/SKILL.md +6 -5
- package/presets/opencode/skills/python-django-stack/SKILL.md +1 -1
- package/presets/opencode/skills/python-fastapi-stack/SKILL.md +1 -1
- package/presets/opencode/skills/security/SKILL.md +1 -1
- package/presets/opencode/skills/seo-analytics-injector/SKILL.md +1 -1
- package/presets/opencode/skills/spring-auth-auditor/SKILL.md +1 -1
- package/presets/opencode/skills/spring-boot-feature/SKILL.md +2 -1
- package/presets/opencode/skills/spring-boot-kotlin/SKILL.md +1 -1
- package/presets/opencode/skills/spring-boot-testing-strategy/SKILL.md +1 -1
- package/presets/opencode/skills/sqlalchemy/SKILL.md +1 -1
- package/presets/opencode/skills/tailwind-responsive-auditor/SKILL.md +1 -1
- package/presets/opencode/skills/tdd-mutation-tester/SKILL.md +1 -1
- package/presets/seo-hotel/skills/astro-seo/SKILL.md +1 -1
- package/presets/seo-hotel/skills/geo-readiness/SKILL.md +1 -1
- package/presets/seo-hotel/skills/off-page/SKILL.md +1 -1
- package/presets/seo-hotel/skills/schema-validator/SKILL.md +1 -1
- package/presets/seo-hotel/skills/seo-audit/SKILL.md +1 -1
- package/presets/shared/invoke-hook.cjs +20 -5
- package/src/presets/models/roles.yml +28 -28
- package/src/presets/shared-skills.yml +58 -22
package/dist/index.js
CHANGED
|
@@ -72,7 +72,7 @@ var package_default;
|
|
|
72
72
|
var init_package = __esm(() => {
|
|
73
73
|
package_default = {
|
|
74
74
|
name: "cc-codeconductor",
|
|
75
|
-
version: "1.
|
|
75
|
+
version: "1.5.0",
|
|
76
76
|
description: "A multi-agent orchestration framework for AI-assisted software engineering workflows.",
|
|
77
77
|
keywords: [
|
|
78
78
|
"ai",
|
|
@@ -12989,18 +12989,19 @@ var init_path_containment = __esm(() => {
|
|
|
12989
12989
|
});
|
|
12990
12990
|
|
|
12991
12991
|
// src/core/presets/complementary-detector.ts
|
|
12992
|
-
import {
|
|
12992
|
+
import { execFile } from "node:child_process";
|
|
12993
12993
|
import { existsSync, readFileSync } from "node:fs";
|
|
12994
12994
|
import { join as join3 } from "node:path";
|
|
12995
12995
|
import { homedir } from "node:os";
|
|
12996
|
-
|
|
12996
|
+
import { promisify } from "node:util";
|
|
12997
|
+
async function detectComplementaryTools() {
|
|
12997
12998
|
if (cachedStatus) {
|
|
12998
12999
|
return cachedStatus;
|
|
12999
13000
|
}
|
|
13000
|
-
const isCmdAvailable = (cmd) => {
|
|
13001
|
+
const isCmdAvailable = async (cmd) => {
|
|
13001
13002
|
try {
|
|
13002
13003
|
const binary = process.platform === "win32" ? "where" : "which";
|
|
13003
|
-
|
|
13004
|
+
await execFileAsync(binary, [cmd], { timeout: 1000 });
|
|
13004
13005
|
return true;
|
|
13005
13006
|
} catch {
|
|
13006
13007
|
return false;
|
|
@@ -13029,18 +13030,28 @@ function detectComplementaryTools() {
|
|
|
13029
13030
|
} catch {}
|
|
13030
13031
|
return false;
|
|
13031
13032
|
};
|
|
13033
|
+
const [rtk, codeReviewGraph, tokenSavior, tokenSaviorRecall, engram, gentleAi] = await Promise.all([
|
|
13034
|
+
isCmdAvailable("rtk"),
|
|
13035
|
+
isCmdAvailable("code-review-graph"),
|
|
13036
|
+
isCmdAvailable("token-savior"),
|
|
13037
|
+
isCmdAvailable("token-savior-recall"),
|
|
13038
|
+
isCmdAvailable("engram"),
|
|
13039
|
+
isCmdAvailable("gentle-ai")
|
|
13040
|
+
]);
|
|
13032
13041
|
cachedStatus = {
|
|
13033
|
-
rtk
|
|
13034
|
-
codeReviewGraph
|
|
13035
|
-
tokenSavior:
|
|
13042
|
+
rtk,
|
|
13043
|
+
codeReviewGraph,
|
|
13044
|
+
tokenSavior: tokenSavior || tokenSaviorRecall,
|
|
13036
13045
|
caveman: hasCaveman(),
|
|
13037
|
-
engram
|
|
13038
|
-
gentleAi
|
|
13046
|
+
engram,
|
|
13047
|
+
gentleAi
|
|
13039
13048
|
};
|
|
13040
13049
|
return cachedStatus;
|
|
13041
13050
|
}
|
|
13042
|
-
var cachedStatus = null;
|
|
13043
|
-
var init_complementary_detector = () => {
|
|
13051
|
+
var execFileAsync, cachedStatus = null;
|
|
13052
|
+
var init_complementary_detector = __esm(() => {
|
|
13053
|
+
execFileAsync = promisify(execFile);
|
|
13054
|
+
});
|
|
13044
13055
|
|
|
13045
13056
|
// src/core/presets/file-copier.ts
|
|
13046
13057
|
import { lstat as lstat2, readdir, readFile as readFile4, stat } from "node:fs/promises";
|
|
@@ -13133,9 +13144,9 @@ function extractAgentRole(filePath) {
|
|
|
13133
13144
|
];
|
|
13134
13145
|
return knownRoles.includes(name) ? name : null;
|
|
13135
13146
|
}
|
|
13136
|
-
function renderTemplate(content, modelConfig, filePath, locale = "en") {
|
|
13147
|
+
async function renderTemplate(content, modelConfig, filePath, locale = "en") {
|
|
13137
13148
|
const cleanLocale = locale === "es" || locale === "en" ? locale : "en";
|
|
13138
|
-
const tools = detectComplementaryTools();
|
|
13149
|
+
const tools = await detectComplementaryTools();
|
|
13139
13150
|
let complementaryRules = "";
|
|
13140
13151
|
if (cleanLocale === "es") {
|
|
13141
13152
|
if (tools.rtk) {
|
|
@@ -13258,7 +13269,7 @@ function substituteToolNames(content, modelConfig) {
|
|
|
13258
13269
|
const eol = fmMatch[1];
|
|
13259
13270
|
const frontmatter = fmMatch[2];
|
|
13260
13271
|
if (target === "opencode" && modelConfig.permissions) {
|
|
13261
|
-
const updatedFrontmatter2 = frontmatter.replace(/^tools:\s*(.+)\r?\n?/m, "");
|
|
13272
|
+
const updatedFrontmatter2 = frontmatter.replace(/^tools:\s*(.+)\r?\n?/m, "").replace(/^(?:temperature|effort):[^\r\n]*\r?\n?/gm, "");
|
|
13262
13273
|
return content.replace(fmMatch[0], `---${eol}${updatedFrontmatter2}${eol}---`);
|
|
13263
13274
|
}
|
|
13264
13275
|
if (!modelConfig.tools)
|
|
@@ -13276,7 +13287,7 @@ function substituteToolNames(content, modelConfig) {
|
|
|
13276
13287
|
});
|
|
13277
13288
|
return content.replace(fmMatch[0], `---${eol}${updatedFrontmatter}${eol}---`);
|
|
13278
13289
|
}
|
|
13279
|
-
function injectMcpServers(jsonString, filePath) {
|
|
13290
|
+
async function injectMcpServers(jsonString, filePath) {
|
|
13280
13291
|
const isAgyMcpConfig = filePath.endsWith("mcp_config.json");
|
|
13281
13292
|
const isClaudeSettings = filePath.endsWith("settings.json");
|
|
13282
13293
|
const isOpencodeJsonc = filePath.endsWith("opencode.jsonc") || filePath.endsWith("opencode.json");
|
|
@@ -13289,7 +13300,7 @@ function injectMcpServers(jsonString, filePath) {
|
|
|
13289
13300
|
cleanJson = jsonString.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
|
|
13290
13301
|
}
|
|
13291
13302
|
const obj = JSON.parse(cleanJson);
|
|
13292
|
-
const tools = detectComplementaryTools();
|
|
13303
|
+
const tools = await detectComplementaryTools();
|
|
13293
13304
|
const mcpServers = {};
|
|
13294
13305
|
if (tools.tokenSavior) {
|
|
13295
13306
|
mcpServers["token-savior-recall"] = {
|
|
@@ -13361,8 +13372,8 @@ async function applySingleFile(srcPath, destPath, strategy, force, dryRun, isTem
|
|
|
13361
13372
|
} catch (e) {
|
|
13362
13373
|
return { src: srcPath, dest: destPath, action: "error", error: `Cannot read source: ${e}` };
|
|
13363
13374
|
}
|
|
13364
|
-
let incomingContent = isTemplate && modelConfig ? renderTemplate(content, modelConfig, srcPath, locale) : content;
|
|
13365
|
-
incomingContent = injectMcpServers(incomingContent, destPath);
|
|
13375
|
+
let incomingContent = isTemplate && modelConfig ? await renderTemplate(content, modelConfig, srcPath, locale) : content;
|
|
13376
|
+
incomingContent = await injectMcpServers(incomingContent, destPath);
|
|
13366
13377
|
let finalContent = incomingContent;
|
|
13367
13378
|
let action = "written";
|
|
13368
13379
|
if (strategy === "append") {
|
|
@@ -14629,7 +14640,7 @@ async function checkUpdates(basePath, isGlobal, includeConflicts = false) {
|
|
|
14629
14640
|
let expectedContent;
|
|
14630
14641
|
try {
|
|
14631
14642
|
const srcContent = await readFile7(src, "utf-8");
|
|
14632
|
-
expectedContent = isTemplate && modelConfig ? renderTemplate(srcContent, modelConfig, src, locale) : srcContent;
|
|
14643
|
+
expectedContent = isTemplate && modelConfig ? await renderTemplate(srcContent, modelConfig, src, locale) : srcContent;
|
|
14633
14644
|
} catch {
|
|
14634
14645
|
continue;
|
|
14635
14646
|
}
|
|
@@ -15091,7 +15102,7 @@ async function doctorCommand(options) {
|
|
|
15091
15102
|
message: "No product graph yet. Run `codeconductor ingest` to build product memory."
|
|
15092
15103
|
});
|
|
15093
15104
|
}
|
|
15094
|
-
const compTools = detectComplementaryTools();
|
|
15105
|
+
const compTools = await detectComplementaryTools();
|
|
15095
15106
|
const toolDetails = [
|
|
15096
15107
|
{ name: "rtk", key: "rtk", label: "RTK", desc: "Run `brew install rtk` to compress command outputs" },
|
|
15097
15108
|
{ name: "code-review-graph", key: "codeReviewGraph", label: "code-review-graph", desc: "Run `pipx install code-review-graph` to navigate symbol graph" },
|
|
@@ -18373,13 +18384,13 @@ var init_binary_downloader = __esm(() => {
|
|
|
18373
18384
|
});
|
|
18374
18385
|
|
|
18375
18386
|
// src/core/lsp/lsp-installer.ts
|
|
18376
|
-
import { execFile } from "node:child_process";
|
|
18387
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
18377
18388
|
import { access as access6, mkdir as mkdir6, mkdtemp, rename as rename2, rm, writeFile as writeFile5 } from "node:fs/promises";
|
|
18378
18389
|
import { homedir as homedir8, tmpdir } from "node:os";
|
|
18379
18390
|
import { join as join9 } from "node:path";
|
|
18380
|
-
import { promisify } from "node:util";
|
|
18391
|
+
import { promisify as promisify2 } from "node:util";
|
|
18381
18392
|
async function assertTarArchiveSafe(archivePath, destRoot) {
|
|
18382
|
-
const { stdout } = await
|
|
18393
|
+
const { stdout } = await execFileAsync2("tar", ["-tzf", archivePath], {
|
|
18383
18394
|
timeout: 60000,
|
|
18384
18395
|
maxBuffer: 10 * 1024 * 1024
|
|
18385
18396
|
});
|
|
@@ -18391,7 +18402,7 @@ async function assertTarArchiveSafe(archivePath, destRoot) {
|
|
|
18391
18402
|
}
|
|
18392
18403
|
async function extractHardenedTar(archivePath, destRoot) {
|
|
18393
18404
|
await assertTarArchiveSafe(archivePath, destRoot);
|
|
18394
|
-
await
|
|
18405
|
+
await execFileAsync2("tar", ["-xzf", archivePath, "-C", destRoot, ...TAR_EXTRACT_HARDENING_FLAGS], { timeout: 120000 });
|
|
18395
18406
|
}
|
|
18396
18407
|
|
|
18397
18408
|
class LspInstaller {
|
|
@@ -18401,7 +18412,7 @@ class LspInstaller {
|
|
|
18401
18412
|
}
|
|
18402
18413
|
async checkInstalled(def) {
|
|
18403
18414
|
try {
|
|
18404
|
-
const { stdout } = await
|
|
18415
|
+
const { stdout } = await execFileAsync2("which", [def.binaryName], { timeout: 5000 });
|
|
18405
18416
|
const path = stdout.trim();
|
|
18406
18417
|
if (path) {
|
|
18407
18418
|
const version = await this.getVersion(def);
|
|
@@ -18410,7 +18421,7 @@ class LspInstaller {
|
|
|
18410
18421
|
} catch {}
|
|
18411
18422
|
if (def.packageManager === "npm" && def.npmDetect) {
|
|
18412
18423
|
try {
|
|
18413
|
-
const { stdout } = await
|
|
18424
|
+
const { stdout } = await execFileAsync2("npm", ["list", "-g", def.npmDetect, "--depth=0"], { timeout: 1e4 });
|
|
18414
18425
|
if (stdout.includes(def.npmDetect)) {
|
|
18415
18426
|
const version = this.parseVersionFromNpmList(stdout, def.npmDetect);
|
|
18416
18427
|
return { installed: true, version };
|
|
@@ -18419,7 +18430,7 @@ class LspInstaller {
|
|
|
18419
18430
|
}
|
|
18420
18431
|
if (def.packageManager === "pip" && def.pipDetect) {
|
|
18421
18432
|
try {
|
|
18422
|
-
const { stdout } = await
|
|
18433
|
+
const { stdout } = await execFileAsync2("pip", ["show", def.pipDetect], { timeout: 1e4 });
|
|
18423
18434
|
if (stdout.includes("Version:")) {
|
|
18424
18435
|
const version = this.parseVersionFromPipShow(stdout);
|
|
18425
18436
|
return { installed: true, version };
|
|
@@ -18483,7 +18494,7 @@ class LspInstaller {
|
|
|
18483
18494
|
}
|
|
18484
18495
|
async getVersion(def) {
|
|
18485
18496
|
try {
|
|
18486
|
-
const { stdout } = await
|
|
18497
|
+
const { stdout } = await execFileAsync2(def.binaryName, [def.versionFlag], { timeout: 5000 });
|
|
18487
18498
|
return stdout.trim().split(`
|
|
18488
18499
|
`)[0];
|
|
18489
18500
|
} catch {
|
|
@@ -18501,7 +18512,7 @@ class LspInstaller {
|
|
|
18501
18512
|
async installNpm(def) {
|
|
18502
18513
|
assertPinnedPackage(def);
|
|
18503
18514
|
try {
|
|
18504
|
-
await
|
|
18515
|
+
await execFileAsync2("npm", ["install", "-g", def.package], { timeout: 120000 });
|
|
18505
18516
|
} catch (error) {
|
|
18506
18517
|
throw new Error(`Failed to install ${def.serverName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
18507
18518
|
}
|
|
@@ -18509,7 +18520,7 @@ class LspInstaller {
|
|
|
18509
18520
|
async installPip(def) {
|
|
18510
18521
|
assertPinnedPackage(def);
|
|
18511
18522
|
try {
|
|
18512
|
-
await
|
|
18523
|
+
await execFileAsync2("pip", ["install", "--user", def.package], { timeout: 120000 });
|
|
18513
18524
|
} catch (error) {
|
|
18514
18525
|
throw new Error(`Failed to install ${def.serverName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
18515
18526
|
}
|
|
@@ -18551,7 +18562,7 @@ class LspInstaller {
|
|
|
18551
18562
|
await access6(candidate);
|
|
18552
18563
|
await rename2(candidate, destPath);
|
|
18553
18564
|
} catch {
|
|
18554
|
-
const { stdout: found } = await
|
|
18565
|
+
const { stdout: found } = await execFileAsync2("find", [workDir, "-type", "f", "-name", def.binaryName], { timeout: 30000 });
|
|
18555
18566
|
const first = found.split(`
|
|
18556
18567
|
`).map((l) => l.trim()).find((l) => l.length > 0);
|
|
18557
18568
|
if (!first) {
|
|
@@ -18561,7 +18572,7 @@ class LspInstaller {
|
|
|
18561
18572
|
await rename2(first, destPath);
|
|
18562
18573
|
}
|
|
18563
18574
|
if (process.platform !== "win32") {
|
|
18564
|
-
await
|
|
18575
|
+
await execFileAsync2("chmod", ["+x", destPath], { timeout: 5000 });
|
|
18565
18576
|
}
|
|
18566
18577
|
} finally {
|
|
18567
18578
|
await rm(workDir, { recursive: true, force: true });
|
|
@@ -18571,11 +18582,11 @@ class LspInstaller {
|
|
|
18571
18582
|
function createLspInstaller() {
|
|
18572
18583
|
return new LspInstaller;
|
|
18573
18584
|
}
|
|
18574
|
-
var
|
|
18585
|
+
var execFileAsync2, TAR_EXTRACT_HARDENING_FLAGS;
|
|
18575
18586
|
var init_lsp_installer = __esm(() => {
|
|
18576
18587
|
init_binary_integrity();
|
|
18577
18588
|
init_binary_downloader();
|
|
18578
|
-
|
|
18589
|
+
execFileAsync2 = promisify2(execFile2);
|
|
18579
18590
|
TAR_EXTRACT_HARDENING_FLAGS = [
|
|
18580
18591
|
"--no-same-owner",
|
|
18581
18592
|
"--no-same-permissions"
|
|
@@ -20840,13 +20851,13 @@ function slugify(text) {
|
|
|
20840
20851
|
|
|
20841
20852
|
// src/core/knowledge/source-parsers.ts
|
|
20842
20853
|
import { readFile as readFile19 } from "node:fs/promises";
|
|
20843
|
-
import { join as join15 } from "node:path";
|
|
20854
|
+
import { basename as basename6, join as join15, relative as relative7, sep as sep5 } from "node:path";
|
|
20844
20855
|
async function parseAdrFile(filePath) {
|
|
20845
20856
|
try {
|
|
20846
20857
|
const content = await readFile19(filePath, "utf-8");
|
|
20847
|
-
const
|
|
20848
|
-
const idMatch =
|
|
20849
|
-
const id = idMatch ? `adr-${idMatch[1]}` : slugify(
|
|
20858
|
+
const base = basename6(filePath);
|
|
20859
|
+
const idMatch = base.match(/adr-(\d+)/i);
|
|
20860
|
+
const id = idMatch ? `adr-${idMatch[1]}` : slugify(base);
|
|
20850
20861
|
const titleMatch = content.match(/^#\s+ADR-\d+:\s*(.+)$/m);
|
|
20851
20862
|
const statusMatch = content.match(/\*\*Status:\*\*\s*(\w+)/i);
|
|
20852
20863
|
const contextSection = extractSection(content, "Context");
|
|
@@ -20856,7 +20867,7 @@ async function parseAdrFile(filePath) {
|
|
|
20856
20867
|
`).filter((l) => l.trim().startsWith("-") || l.trim().startsWith("*")).map((l) => l.replace(/^[\s*-]+/, "").trim()).filter(Boolean);
|
|
20857
20868
|
return {
|
|
20858
20869
|
id,
|
|
20859
|
-
title: titleMatch?.[1]?.trim() ??
|
|
20870
|
+
title: titleMatch?.[1]?.trim() ?? base,
|
|
20860
20871
|
status: statusMatch?.[1]?.toLowerCase() ?? "unknown",
|
|
20861
20872
|
context: contextSection.trim(),
|
|
20862
20873
|
decision: decisionSection.trim(),
|
|
@@ -20956,7 +20967,7 @@ async function scanSrcComponents(projectRoot) {
|
|
|
20956
20967
|
source: "src/",
|
|
20957
20968
|
confidence: "medium",
|
|
20958
20969
|
relations: [],
|
|
20959
|
-
data: { path: full.
|
|
20970
|
+
data: { path: relative7(projectRoot, full).split(sep5).join("/") }
|
|
20960
20971
|
});
|
|
20961
20972
|
await walk(full, prefix ? `${prefix}-${domainSlug}` : domainSlug);
|
|
20962
20973
|
}
|
|
@@ -21017,7 +21028,7 @@ var init_episodic_store = __esm(() => {
|
|
|
21017
21028
|
// src/core/knowledge/ingest-pipeline.ts
|
|
21018
21029
|
import { createHash as createHash3 } from "node:crypto";
|
|
21019
21030
|
import { readFile as readFile21 } from "node:fs/promises";
|
|
21020
|
-
import { join as join16 } from "node:path";
|
|
21031
|
+
import { join as join16, relative as relative8, sep as sep6 } from "node:path";
|
|
21021
21032
|
import { mkdir as mkdir13, writeFile as writeFile12 } from "node:fs/promises";
|
|
21022
21033
|
async function mapLimit(items, limit, fn) {
|
|
21023
21034
|
if (items.length === 0)
|
|
@@ -21066,7 +21077,7 @@ async function collectDeferRisks(projectRoot) {
|
|
|
21066
21077
|
const perFile = await mapLimit(files, WALK_READ_CONCURRENCY, async (full) => {
|
|
21067
21078
|
const entities = [];
|
|
21068
21079
|
const content = await readFile21(full, "utf-8");
|
|
21069
|
-
const rel = full.
|
|
21080
|
+
const rel = relative8(projectRoot, full).split(sep6).join("/");
|
|
21070
21081
|
const deferRe = new RegExp(DEFER_REGEX_SOURCE, "gm");
|
|
21071
21082
|
let match;
|
|
21072
21083
|
while ((match = deferRe.exec(content)) !== null) {
|
|
@@ -22265,21 +22276,21 @@ __export(exports_rdd_receipt, {
|
|
|
22265
22276
|
});
|
|
22266
22277
|
import { createHash as createHash4 } from "node:crypto";
|
|
22267
22278
|
import { readdir as readdir7, readFile as readFile27 } from "node:fs/promises";
|
|
22268
|
-
import { join as join18, relative as
|
|
22279
|
+
import { join as join18, relative as relative9, resolve as resolve26, sep as sep7 } from "node:path";
|
|
22269
22280
|
function sha2562(content) {
|
|
22270
22281
|
return createHash4("sha256").update(content).digest("hex");
|
|
22271
22282
|
}
|
|
22272
22283
|
function canonicalPath(projectRoot, input) {
|
|
22273
22284
|
const root = resolve26(projectRoot);
|
|
22274
22285
|
const absolute = resolve26(root, input);
|
|
22275
|
-
if (absolute !== root && !absolute.startsWith(`${root}${
|
|
22286
|
+
if (absolute !== root && !absolute.startsWith(`${root}${sep7}`)) {
|
|
22276
22287
|
throw new Error(`RDD receipt path "${input}" is outside the project root`);
|
|
22277
22288
|
}
|
|
22278
|
-
const normalized =
|
|
22289
|
+
const normalized = relative9(root, absolute);
|
|
22279
22290
|
if (!normalized || normalized === ".") {
|
|
22280
22291
|
throw new Error("RDD receipts require file paths, not the project root");
|
|
22281
22292
|
}
|
|
22282
|
-
return { absolute, relative: normalized.split(
|
|
22293
|
+
return { absolute, relative: normalized.split(sep7).join("/") };
|
|
22283
22294
|
}
|
|
22284
22295
|
async function fingerprint(projectRoot, paths) {
|
|
22285
22296
|
const deduplicated = new Map;
|
|
@@ -22334,7 +22345,7 @@ async function collectReceiptPaths(projectRoot) {
|
|
|
22334
22345
|
continue;
|
|
22335
22346
|
}
|
|
22336
22347
|
if (entry.isFile())
|
|
22337
|
-
paths.push(
|
|
22348
|
+
paths.push(relative9(root, join18(current, entry.name)).split(sep7).join("/"));
|
|
22338
22349
|
}
|
|
22339
22350
|
}
|
|
22340
22351
|
await visit2(root);
|
|
@@ -23037,8 +23048,8 @@ var init_loop_state = __esm(() => {
|
|
|
23037
23048
|
});
|
|
23038
23049
|
|
|
23039
23050
|
// src/core/loop/git-stats.ts
|
|
23040
|
-
import { execFile as
|
|
23041
|
-
import { promisify as
|
|
23051
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
23052
|
+
import { promisify as promisify3 } from "node:util";
|
|
23042
23053
|
function countPorcelain(output) {
|
|
23043
23054
|
return output.split(`
|
|
23044
23055
|
`).filter((line) => line.trim().length > 0).length;
|
|
@@ -23062,12 +23073,12 @@ function countNumstat(output) {
|
|
|
23062
23073
|
async function fetchGitChangeStats(cwd) {
|
|
23063
23074
|
try {
|
|
23064
23075
|
const [status, diff] = await Promise.all([
|
|
23065
|
-
|
|
23076
|
+
execFileAsync3("git", ["status", "--porcelain"], {
|
|
23066
23077
|
cwd,
|
|
23067
23078
|
encoding: "utf-8",
|
|
23068
23079
|
timeout: 15000
|
|
23069
23080
|
}),
|
|
23070
|
-
|
|
23081
|
+
execFileAsync3("git", ["diff", "--numstat"], {
|
|
23071
23082
|
cwd,
|
|
23072
23083
|
encoding: "utf-8",
|
|
23073
23084
|
timeout: 15000
|
|
@@ -23091,9 +23102,9 @@ async function readGitChangeStats(cwd, options) {
|
|
|
23091
23102
|
cache = { cwd, at: now, stats };
|
|
23092
23103
|
return stats;
|
|
23093
23104
|
}
|
|
23094
|
-
var
|
|
23105
|
+
var execFileAsync3, GIT_STATS_CACHE_TTL_MS = 3000, cache;
|
|
23095
23106
|
var init_git_stats = __esm(() => {
|
|
23096
|
-
|
|
23107
|
+
execFileAsync3 = promisify3(execFile3);
|
|
23097
23108
|
});
|
|
23098
23109
|
|
|
23099
23110
|
// src/core/loop/loop-engine.ts
|
|
@@ -23826,11 +23837,11 @@ __export(exports_rdd_command, {
|
|
|
23826
23837
|
rddCommand: () => rddCommand,
|
|
23827
23838
|
rddStatus: () => rddStatus
|
|
23828
23839
|
});
|
|
23829
|
-
import { execFile as
|
|
23840
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
23830
23841
|
import { existsSync as existsSync4 } from "node:fs";
|
|
23831
23842
|
import { mkdir as mkdir19, readFile as readFile29, readdir as readdir9, rename as rename3, writeFile as writeFile19, chmod } from "node:fs/promises";
|
|
23832
23843
|
import { dirname as dirname11, resolve as resolve28 } from "node:path";
|
|
23833
|
-
import { promisify as
|
|
23844
|
+
import { promisify as promisify4 } from "node:util";
|
|
23834
23845
|
function receiptPath(projectRoot, id) {
|
|
23835
23846
|
const directory = resolve28(evidenceDir(projectRoot));
|
|
23836
23847
|
const path = resolve28(directory, `${id.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
|
|
@@ -23877,7 +23888,7 @@ async function rddStatus(projectRoot, taskId) {
|
|
|
23877
23888
|
return receipts.sort((left, right) => right.timestamp.localeCompare(left.timestamp));
|
|
23878
23889
|
}
|
|
23879
23890
|
async function installHooks(projectRoot) {
|
|
23880
|
-
const { stdout } = await
|
|
23891
|
+
const { stdout } = await execFileAsync4("git", ["rev-parse", "--git-path", "hooks"], {
|
|
23881
23892
|
cwd: projectRoot,
|
|
23882
23893
|
encoding: "utf8"
|
|
23883
23894
|
});
|
|
@@ -23969,12 +23980,12 @@ async function rddCommand(options) {
|
|
|
23969
23980
|
return { code: 1, data: { success: false, errors: [error instanceof Error ? error.message : String(error)] } };
|
|
23970
23981
|
}
|
|
23971
23982
|
}
|
|
23972
|
-
var
|
|
23983
|
+
var execFileAsync4;
|
|
23973
23984
|
var init_rdd_command = __esm(() => {
|
|
23974
23985
|
init_schemas();
|
|
23975
23986
|
init_paths();
|
|
23976
23987
|
init_rdd_receipt();
|
|
23977
|
-
|
|
23988
|
+
execFileAsync4 = promisify4(execFile4);
|
|
23978
23989
|
});
|
|
23979
23990
|
|
|
23980
23991
|
// src/core/ccep/confirmation-gate.ts
|
|
@@ -24283,7 +24294,7 @@ var init_output_validator = __esm(() => {
|
|
|
24283
24294
|
|
|
24284
24295
|
// src/core/ccep/command-parser.ts
|
|
24285
24296
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
24286
|
-
import { join as join20 } from "node:path";
|
|
24297
|
+
import { basename as basename7, join as join20 } from "node:path";
|
|
24287
24298
|
function readProjectId(projectRoot) {
|
|
24288
24299
|
const packageJsonPath = join20(projectRoot, "package.json");
|
|
24289
24300
|
if (existsSync5(packageJsonPath)) {
|
|
@@ -24294,7 +24305,7 @@ function readProjectId(projectRoot) {
|
|
|
24294
24305
|
}
|
|
24295
24306
|
} catch {}
|
|
24296
24307
|
}
|
|
24297
|
-
return projectRoot
|
|
24308
|
+
return basename7(projectRoot) || "unknown";
|
|
24298
24309
|
}
|
|
24299
24310
|
function parseCommand(command, userRequest, projectRoot) {
|
|
24300
24311
|
const validatedCommand = WorkflowCommandSchema.parse(command);
|
|
@@ -25969,7 +25980,7 @@ var init_backlog_validator = __esm(() => {
|
|
|
25969
25980
|
});
|
|
25970
25981
|
|
|
25971
25982
|
// src/core/openspec/backlog-scanner.ts
|
|
25972
|
-
import { execFileSync
|
|
25983
|
+
import { execFileSync } from "node:child_process";
|
|
25973
25984
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
25974
25985
|
import { resolve as resolve31 } from "node:path";
|
|
25975
25986
|
function itemSnapshot(items) {
|
|
@@ -25986,7 +25997,7 @@ async function scanBacklog(projectRoot, previousSnapshot = {}) {
|
|
|
25986
25997
|
const hash = hashContent(content);
|
|
25987
25998
|
let fileChanged = true;
|
|
25988
25999
|
try {
|
|
25989
|
-
const diff =
|
|
26000
|
+
const diff = execFileSync("git", ["diff", "--name-only", "--", BACKLOG_FILENAME], {
|
|
25990
26001
|
cwd: projectRoot,
|
|
25991
26002
|
encoding: "utf-8",
|
|
25992
26003
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -26220,7 +26231,7 @@ var init_backlog_planner = __esm(() => {
|
|
|
26220
26231
|
|
|
26221
26232
|
// src/core/openspec/openspec-generator.ts
|
|
26222
26233
|
import { mkdir as mkdir22, rename as rename5, writeFile as writeFile22 } from "node:fs/promises";
|
|
26223
|
-
import { basename as
|
|
26234
|
+
import { basename as basename8, resolve as resolve32 } from "node:path";
|
|
26224
26235
|
function pad3(n) {
|
|
26225
26236
|
return String(n).padStart(3, "0");
|
|
26226
26237
|
}
|
|
@@ -26367,7 +26378,7 @@ capabilities:
|
|
|
26367
26378
|
}
|
|
26368
26379
|
async function archiveChangeFolder(projectRoot, changePath) {
|
|
26369
26380
|
const src = resolve32(projectRoot, changePath);
|
|
26370
|
-
const slug =
|
|
26381
|
+
const slug = basename8(changePath);
|
|
26371
26382
|
const destDir = resolve32(projectRoot, "openspec", "changes", "archive");
|
|
26372
26383
|
await mkdir22(destDir, { recursive: true });
|
|
26373
26384
|
const dest = resolve32(destDir, slug);
|
|
@@ -26393,7 +26404,7 @@ var init_openspec_generator = __esm(() => {
|
|
|
26393
26404
|
|
|
26394
26405
|
// src/core/openspec/spec-quality.ts
|
|
26395
26406
|
import { readdir as readdir11, readFile as readFile34 } from "node:fs/promises";
|
|
26396
|
-
import { join as join23, relative as
|
|
26407
|
+
import { join as join23, relative as relative10, resolve as resolve33 } from "node:path";
|
|
26397
26408
|
function uniqueIds(matches) {
|
|
26398
26409
|
return [...new Set(matches ?? [])];
|
|
26399
26410
|
}
|
|
@@ -26550,7 +26561,7 @@ async function assessChangeFolder(projectRoot, changePath) {
|
|
|
26550
26561
|
const reports = [];
|
|
26551
26562
|
for (const file of specFiles) {
|
|
26552
26563
|
const content = await readFile34(file, "utf-8");
|
|
26553
|
-
reports.push(assessSpecMarkdown(content,
|
|
26564
|
+
reports.push(assessSpecMarkdown(content, relative10(root, file).replace(/\\/g, "/")));
|
|
26554
26565
|
}
|
|
26555
26566
|
for (const file of extra) {
|
|
26556
26567
|
let content;
|
|
@@ -26559,7 +26570,7 @@ async function assessChangeFolder(projectRoot, changePath) {
|
|
|
26559
26570
|
} catch {
|
|
26560
26571
|
continue;
|
|
26561
26572
|
}
|
|
26562
|
-
const rel =
|
|
26573
|
+
const rel = relative10(root, file).replace(/\\/g, "/");
|
|
26563
26574
|
if (PLACEHOLDER.test(content)) {
|
|
26564
26575
|
reports.push({
|
|
26565
26576
|
valid: false,
|
|
@@ -26756,7 +26767,7 @@ var init_spec_analyzer = __esm(() => {
|
|
|
26756
26767
|
|
|
26757
26768
|
// src/core/openspec/spec-sync.ts
|
|
26758
26769
|
import { mkdir as mkdir23, readFile as readFile36, readdir as readdir13 } from "node:fs/promises";
|
|
26759
|
-
import { join as join25, relative as
|
|
26770
|
+
import { join as join25, relative as relative11, resolve as resolve35 } from "node:path";
|
|
26760
26771
|
async function markdownFiles(dir) {
|
|
26761
26772
|
let entries;
|
|
26762
26773
|
try {
|
|
@@ -26860,17 +26871,17 @@ async function syncChangeSpecs(projectRoot, changePath) {
|
|
|
26860
26871
|
return {
|
|
26861
26872
|
success: false,
|
|
26862
26873
|
syncedPaths: [],
|
|
26863
|
-
errors: [`${
|
|
26874
|
+
errors: [`${relative11(root, file)}: no delta requirements found`]
|
|
26864
26875
|
};
|
|
26865
26876
|
}
|
|
26866
|
-
const relativeSpec =
|
|
26877
|
+
const relativeSpec = relative11(changeSpecs, file);
|
|
26867
26878
|
const target = join25(root, "openspec", "specs", relativeSpec);
|
|
26868
26879
|
let existing = `# ${relativeSpec.replace(/\\/g, "/")}
|
|
26869
26880
|
`;
|
|
26870
26881
|
try {
|
|
26871
26882
|
existing = await readFile36(target, "utf-8");
|
|
26872
26883
|
} catch {}
|
|
26873
|
-
const merged = upsertRequirements(existing, requirements,
|
|
26884
|
+
const merged = upsertRequirements(existing, requirements, relative11(root, file));
|
|
26874
26885
|
if (!merged.ok)
|
|
26875
26886
|
return { success: false, syncedPaths: [], errors: [merged.error] };
|
|
26876
26887
|
writes.push({ path: target, content: merged.content });
|
|
@@ -26881,7 +26892,7 @@ async function syncChangeSpecs(projectRoot, changePath) {
|
|
|
26881
26892
|
}
|
|
26882
26893
|
return {
|
|
26883
26894
|
success: true,
|
|
26884
|
-
syncedPaths: writes.map((write) =>
|
|
26895
|
+
syncedPaths: writes.map((write) => relative11(root, write.path).replace(/\\/g, "/")),
|
|
26885
26896
|
errors: []
|
|
26886
26897
|
};
|
|
26887
26898
|
}
|
|
@@ -27587,7 +27598,7 @@ var init_context_assembly = () => {};
|
|
|
27587
27598
|
// src/core/delivery/delivery-ledger.ts
|
|
27588
27599
|
import { createHash as createHash7 } from "node:crypto";
|
|
27589
27600
|
import { mkdir as mkdir24, readFile as readFile38, writeFile as writeFile23 } from "node:fs/promises";
|
|
27590
|
-
import { resolve as resolve37, sep as
|
|
27601
|
+
import { resolve as resolve37, sep as sep8 } from "node:path";
|
|
27591
27602
|
function ledgerPath(projectRoot, id) {
|
|
27592
27603
|
if (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(id))
|
|
27593
27604
|
throw new Error("Invalid delivery ledger id");
|
|
@@ -27598,7 +27609,7 @@ async function fingerprintWorkspace(projectRoot, paths) {
|
|
|
27598
27609
|
const fingerprints = {};
|
|
27599
27610
|
for (const path of paths) {
|
|
27600
27611
|
const candidate = resolve37(root, path);
|
|
27601
|
-
if (candidate !== root && !candidate.startsWith(`${root}${
|
|
27612
|
+
if (candidate !== root && !candidate.startsWith(`${root}${sep8}`)) {
|
|
27602
27613
|
fingerprints[path] = "outside-root";
|
|
27603
27614
|
continue;
|
|
27604
27615
|
}
|
|
@@ -27755,7 +27766,11 @@ function normalizeCommand(raw) {
|
|
|
27755
27766
|
return raw.replace(/\s+/g, " ").trim();
|
|
27756
27767
|
}
|
|
27757
27768
|
function stripGitBinary(command) {
|
|
27758
|
-
|
|
27769
|
+
const match = command.match(/^(?:&\s*)?("[^"]+"|'[^']+'|[^\s]+)([\s\S]*)$/);
|
|
27770
|
+
if (!match)
|
|
27771
|
+
return command;
|
|
27772
|
+
const binary = match[1].replace(/^["']|["']$/g, "").replace(/\\/g, "/").split("/").pop();
|
|
27773
|
+
return /^git(?:\.exe)?$/i.test(binary ?? "") ? `git${match[2]}` : command;
|
|
27759
27774
|
}
|
|
27760
27775
|
function evaluatePath(filePath) {
|
|
27761
27776
|
if (SENSITIVE_PATH.test(filePath.replace(/\//g, "\\")) || SENSITIVE_PATH.test(filePath)) {
|
|
@@ -27764,9 +27779,44 @@ function evaluatePath(filePath) {
|
|
|
27764
27779
|
return allow();
|
|
27765
27780
|
}
|
|
27766
27781
|
function evaluateCommand(rawCommand) {
|
|
27767
|
-
|
|
27782
|
+
if (/(?:curl|wget)\b.+\|\s*(sh|bash|zsh|cmd)\b/i.test(normalizeCommand(rawCommand)))
|
|
27783
|
+
return deny(MSG_POLICY);
|
|
27784
|
+
const tokens = rawCommand.match(/"[^"]*"|'[^']*'|[^"';&|\r\n]+|[;&|\r\n]+/g) ?? [];
|
|
27785
|
+
const commands = [];
|
|
27786
|
+
let current = "";
|
|
27787
|
+
for (const token of tokens) {
|
|
27788
|
+
if (/^[;&|\r\n]+$/.test(token) && !(token === "&" && !current.trim())) {
|
|
27789
|
+
commands.push(current);
|
|
27790
|
+
current = "";
|
|
27791
|
+
} else {
|
|
27792
|
+
current += token;
|
|
27793
|
+
}
|
|
27794
|
+
}
|
|
27795
|
+
commands.push(current);
|
|
27796
|
+
let verdict = allow();
|
|
27797
|
+
for (const part of commands) {
|
|
27798
|
+
const result = evaluateSingleCommand(part);
|
|
27799
|
+
if (result.action === "deny")
|
|
27800
|
+
return result;
|
|
27801
|
+
if (result.action === "ask")
|
|
27802
|
+
verdict = result;
|
|
27803
|
+
}
|
|
27804
|
+
return verdict;
|
|
27805
|
+
}
|
|
27806
|
+
function evaluateSingleCommand(rawCommand) {
|
|
27807
|
+
let command = stripGitBinary(normalizeCommand(rawCommand));
|
|
27768
27808
|
if (!command)
|
|
27769
27809
|
return allow();
|
|
27810
|
+
if (/^git\s/i.test(command)) {
|
|
27811
|
+
const words = command.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
|
|
27812
|
+
let index = 1;
|
|
27813
|
+
while (words[index]?.startsWith("-")) {
|
|
27814
|
+
const option = words[index++];
|
|
27815
|
+
if (/^(?:-C|-c|--git-dir|--work-tree|--namespace)$/.test(option))
|
|
27816
|
+
index++;
|
|
27817
|
+
}
|
|
27818
|
+
command = ["git", ...words.slice(index)].join(" ");
|
|
27819
|
+
}
|
|
27770
27820
|
if (SENSITIVE_PATH.test(command) && READ_LIKE.test(command)) {
|
|
27771
27821
|
return deny(MSG_SECRET);
|
|
27772
27822
|
}
|
|
@@ -27789,9 +27839,12 @@ function evaluateCommand(rawCommand) {
|
|
|
27789
27839
|
}
|
|
27790
27840
|
if (/^rm\s+-rf\s+(\*|[\\/])/i.test(command))
|
|
27791
27841
|
return deny(MSG_POLICY);
|
|
27792
|
-
|
|
27842
|
+
const windowsTarget = /(?:^|\s)["']?(?:[a-z]:[\\/]|\\|\*)/i.test(command);
|
|
27843
|
+
if (windowsTarget && /^Remove-Item\b/i.test(command) && /\s-(?:Recurse|r)\b/i.test(command) && /\s-(?:Force|f)\b/i.test(command))
|
|
27844
|
+
return deny(MSG_POLICY);
|
|
27845
|
+
if (windowsTarget && /^(?:rd|rmdir|del|erase)\b/i.test(command) && /\s\/s\b/i.test(command))
|
|
27793
27846
|
return deny(MSG_POLICY);
|
|
27794
|
-
if (
|
|
27847
|
+
if (/^sudo\s+/i.test(command))
|
|
27795
27848
|
return deny(MSG_POLICY);
|
|
27796
27849
|
if (/^chmod\s+777\b/i.test(command))
|
|
27797
27850
|
return deny(MSG_POLICY);
|
|
@@ -27818,13 +27871,16 @@ function evaluatePreTool(input) {
|
|
|
27818
27871
|
function formatHookOutput(verdict, format) {
|
|
27819
27872
|
if (format === "agy") {
|
|
27820
27873
|
if (verdict.action === "deny") {
|
|
27821
|
-
return JSON.stringify({ decision: "deny",
|
|
27874
|
+
return JSON.stringify({ decision: "deny", reason: verdict.message });
|
|
27822
27875
|
}
|
|
27823
27876
|
if (verdict.action === "ask") {
|
|
27824
27877
|
return JSON.stringify({ decision: "ask" });
|
|
27825
27878
|
}
|
|
27826
27879
|
return JSON.stringify({ decision: "allow" });
|
|
27827
27880
|
}
|
|
27881
|
+
if (verdict.action === "ask") {
|
|
27882
|
+
return JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "ask" } });
|
|
27883
|
+
}
|
|
27828
27884
|
return "";
|
|
27829
27885
|
}
|
|
27830
27886
|
function claudeExitCode(verdict) {
|
|
@@ -27835,11 +27891,24 @@ function parseAgyPayload(raw) {
|
|
|
27835
27891
|
return {};
|
|
27836
27892
|
try {
|
|
27837
27893
|
const parsed = JSON.parse(raw);
|
|
27838
|
-
const args = parsed.arguments ?? {};
|
|
27894
|
+
const args = parsed.toolCall?.args ?? parsed.arguments ?? {};
|
|
27839
27895
|
return {
|
|
27840
|
-
toolName: parsed.toolName,
|
|
27841
|
-
command: args.CommandLine,
|
|
27842
|
-
filePath: args.TargetFile
|
|
27896
|
+
toolName: typeof (parsed.toolCall?.name ?? parsed.toolName) === "string" ? parsed.toolCall?.name ?? parsed.toolName : undefined,
|
|
27897
|
+
command: typeof args.CommandLine === "string" ? args.CommandLine : undefined,
|
|
27898
|
+
filePath: typeof args.TargetFile === "string" ? args.TargetFile : typeof args.AbsolutePath === "string" ? args.AbsolutePath : undefined
|
|
27899
|
+
};
|
|
27900
|
+
} catch {
|
|
27901
|
+
return {};
|
|
27902
|
+
}
|
|
27903
|
+
}
|
|
27904
|
+
function parseClaudePayload(raw) {
|
|
27905
|
+
try {
|
|
27906
|
+
const parsed = JSON.parse(raw);
|
|
27907
|
+
const input = parsed.tool_input ?? {};
|
|
27908
|
+
return {
|
|
27909
|
+
toolName: typeof parsed.tool_name === "string" ? parsed.tool_name : undefined,
|
|
27910
|
+
command: typeof input.command === "string" ? input.command : undefined,
|
|
27911
|
+
filePath: typeof input.file_path === "string" ? input.file_path : undefined
|
|
27843
27912
|
};
|
|
27844
27913
|
} catch {
|
|
27845
27914
|
return {};
|
|
@@ -27901,14 +27970,17 @@ __export(exports_hook_command, {
|
|
|
27901
27970
|
readStdinText: () => readStdinText
|
|
27902
27971
|
});
|
|
27903
27972
|
import { spawnSync } from "node:child_process";
|
|
27904
|
-
import { existsSync as existsSync8 } from "node:fs";
|
|
27905
|
-
import {
|
|
27973
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
|
|
27974
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
27975
|
+
import { dirname as dirname13, resolve as resolve38 } from "node:path";
|
|
27906
27976
|
function detectFormat(explicit, stdinText) {
|
|
27907
27977
|
if (explicit)
|
|
27908
27978
|
return explicit;
|
|
27909
|
-
|
|
27910
|
-
|
|
27911
|
-
|
|
27979
|
+
try {
|
|
27980
|
+
const payload = JSON.parse(stdinText);
|
|
27981
|
+
if (payload && (("toolCall" in payload) || ("toolName" in payload) || ("workspacePaths" in payload)))
|
|
27982
|
+
return "agy";
|
|
27983
|
+
} catch {}
|
|
27912
27984
|
return "claude";
|
|
27913
27985
|
}
|
|
27914
27986
|
async function readStdinText() {
|
|
@@ -27920,11 +27992,11 @@ async function readStdinText() {
|
|
|
27920
27992
|
}
|
|
27921
27993
|
return Buffer.concat(chunks).toString("utf8");
|
|
27922
27994
|
}
|
|
27923
|
-
function resolvePreToolInput(options, stdinText) {
|
|
27924
|
-
const fromStdin = parseAgyPayload(stdinText);
|
|
27995
|
+
function resolvePreToolInput(options, stdinText, format) {
|
|
27996
|
+
const fromStdin = format === "agy" ? parseAgyPayload(stdinText) : parseClaudePayload(stdinText);
|
|
27925
27997
|
return {
|
|
27926
|
-
command: options.command ?? process.env.CLAUDE_TOOL_INPUT_COMMAND ?? fromStdin.command,
|
|
27927
|
-
filePath: options.filePath ?? process.env.CLAUDE_TOOL_INPUT_FILE_PATH ?? fromStdin.filePath,
|
|
27998
|
+
command: options.command ?? (process.env.CLAUDE_TOOL_INPUT_COMMAND || undefined) ?? fromStdin.command,
|
|
27999
|
+
filePath: options.filePath ?? (process.env.CLAUDE_TOOL_INPUT_FILE_PATH || undefined) ?? fromStdin.filePath,
|
|
27928
28000
|
toolName: fromStdin.toolName
|
|
27929
28001
|
};
|
|
27930
28002
|
}
|
|
@@ -27951,15 +28023,15 @@ async function hookCommand(options) {
|
|
|
27951
28023
|
return { code: 0, data: { success: true, command: "hook session-start" } };
|
|
27952
28024
|
}
|
|
27953
28025
|
if (event === "post-tool") {
|
|
27954
|
-
const filePath = options
|
|
27955
|
-
formatWrittenFile(filePath);
|
|
28026
|
+
const filePath = resolvePreToolInput(options, stdinText, format).filePath;
|
|
28027
|
+
formatWrittenFile(filePath, options.projectRoot);
|
|
27956
28028
|
if (format === "agy") {
|
|
27957
28029
|
process.stdout.write(`{}
|
|
27958
28030
|
`);
|
|
27959
28031
|
}
|
|
27960
28032
|
return { code: 0, data: { success: true, command: "hook post-tool" } };
|
|
27961
28033
|
}
|
|
27962
|
-
const input = resolvePreToolInput(options, stdinText);
|
|
28034
|
+
const input = resolvePreToolInput(options, stdinText, format);
|
|
27963
28035
|
const verdict = evaluatePreTool(input);
|
|
27964
28036
|
if (format === "agy") {
|
|
27965
28037
|
process.stdout.write(`${formatHookOutput(verdict, "agy")}
|
|
@@ -27973,23 +28045,40 @@ async function hookCommand(options) {
|
|
|
27973
28045
|
process.stderr.write(`${verdict.message}
|
|
27974
28046
|
`);
|
|
27975
28047
|
}
|
|
28048
|
+
const output = formatHookOutput(verdict, "claude");
|
|
28049
|
+
if (output)
|
|
28050
|
+
process.stdout.write(`${output}
|
|
28051
|
+
`);
|
|
27976
28052
|
return {
|
|
27977
28053
|
code: claudeExitCode(verdict),
|
|
27978
28054
|
data: { success: verdict.action !== "deny", command: "hook pre-tool", verdict }
|
|
27979
28055
|
};
|
|
27980
28056
|
}
|
|
27981
|
-
function formatWrittenFile(filePath) {
|
|
27982
|
-
if (!filePath
|
|
28057
|
+
function formatWrittenFile(filePath, projectRoot) {
|
|
28058
|
+
if (!filePath)
|
|
28059
|
+
return;
|
|
28060
|
+
filePath = resolve38(projectRoot, filePath);
|
|
28061
|
+
if (!existsSync8(filePath))
|
|
27983
28062
|
return;
|
|
27984
28063
|
const prettier = /\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|md|mdx|css|scss|html|astro|ya?ml)$/i;
|
|
27985
28064
|
const eslint = /\.(ts|tsx|js|jsx|mjs|cjs)$/i;
|
|
27986
28065
|
const python = /\.py$/i;
|
|
27987
|
-
const opts = { stdio: "ignore", windowsHide: true };
|
|
28066
|
+
const opts = { cwd: projectRoot, stdio: "ignore", windowsHide: true, timeout: 5000 };
|
|
28067
|
+
const require2 = createRequire2(resolve38(projectRoot, "package.json"));
|
|
28068
|
+
function runNodeTool(name, args) {
|
|
28069
|
+
try {
|
|
28070
|
+
const manifestPath = require2.resolve(`${name}/package.json`);
|
|
28071
|
+
const manifest = JSON.parse(readFileSync5(manifestPath, "utf8"));
|
|
28072
|
+
const bin = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.[name];
|
|
28073
|
+
if (typeof bin === "string")
|
|
28074
|
+
spawnSync(process.execPath, [resolve38(dirname13(manifestPath), bin), ...args], opts);
|
|
28075
|
+
} catch {}
|
|
28076
|
+
}
|
|
27988
28077
|
if (prettier.test(filePath)) {
|
|
27989
|
-
|
|
28078
|
+
runNodeTool("prettier", ["--write", filePath]);
|
|
27990
28079
|
}
|
|
27991
28080
|
if (eslint.test(filePath)) {
|
|
27992
|
-
|
|
28081
|
+
runNodeTool("eslint", ["--fix", filePath]);
|
|
27993
28082
|
}
|
|
27994
28083
|
if (python.test(filePath)) {
|
|
27995
28084
|
spawnSync("ruff", ["format", filePath], opts);
|
|
@@ -28396,7 +28485,7 @@ function ccGainToScorecardImpact(result) {
|
|
|
28396
28485
|
}
|
|
28397
28486
|
|
|
28398
28487
|
// src/core/evaluation/scorecard-signals.ts
|
|
28399
|
-
import { execFileSync as
|
|
28488
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
28400
28489
|
function parseScopeFiles(scope) {
|
|
28401
28490
|
return scope.split(/[,;]/).map((entry) => entry.trim().replace(/[.;:]$/, "").replace(/^`|`$/g, "")).filter(Boolean);
|
|
28402
28491
|
}
|
|
@@ -28426,7 +28515,7 @@ function collectScorecardSignals(projectRoot, scopeFiles, extra) {
|
|
|
28426
28515
|
}
|
|
28427
28516
|
let diff = "";
|
|
28428
28517
|
try {
|
|
28429
|
-
diff =
|
|
28518
|
+
diff = execFileSync2("git", ["diff", "HEAD"], {
|
|
28430
28519
|
cwd: projectRoot,
|
|
28431
28520
|
encoding: "utf-8",
|
|
28432
28521
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -28522,7 +28611,7 @@ var init_scorecard_signals = __esm(() => {
|
|
|
28522
28611
|
// src/core/evaluation/harness-experiment.ts
|
|
28523
28612
|
import { existsSync as existsSync9 } from "node:fs";
|
|
28524
28613
|
import { cp, mkdir as mkdir25, readFile as readFile39, readdir as readdir14, writeFile as writeFile24 } from "node:fs/promises";
|
|
28525
|
-
import { dirname as
|
|
28614
|
+
import { dirname as dirname14, join as join26, resolve as resolve39 } from "node:path";
|
|
28526
28615
|
function experimentDir(projectRoot, experimentId) {
|
|
28527
28616
|
return resolve39(projectRoot, EVAL_DIR2, EXPERIMENTS_DIR, experimentId);
|
|
28528
28617
|
}
|
|
@@ -28637,7 +28726,7 @@ function generateExperimentId(suiteId, now = new Date) {
|
|
|
28637
28726
|
return `abl-${date}-${suiteId}-${rand}`;
|
|
28638
28727
|
}
|
|
28639
28728
|
async function copyFixture(suitePath, fixtureDir, dest) {
|
|
28640
|
-
const source = fixtureDir ? resolve39(
|
|
28729
|
+
const source = fixtureDir ? resolve39(dirname14(suitePath), fixtureDir) : join26(dirname14(suitePath), "fixture");
|
|
28641
28730
|
await mkdir25(dest, { recursive: true });
|
|
28642
28731
|
if (existsSync9(source)) {
|
|
28643
28732
|
await cp(source, dest, { recursive: true });
|
|
@@ -29042,9 +29131,9 @@ var init_prompt_diff = __esm(() => {
|
|
|
29042
29131
|
});
|
|
29043
29132
|
|
|
29044
29133
|
// src/core/evaluation/regression-checklist.ts
|
|
29045
|
-
import { execFileSync as
|
|
29134
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
29046
29135
|
import { mkdir as mkdir26, readFile as readFile42, writeFile as writeFile25 } from "node:fs/promises";
|
|
29047
|
-
import { dirname as
|
|
29136
|
+
import { dirname as dirname15, resolve as resolve43 } from "node:path";
|
|
29048
29137
|
async function loadRegressionChecklist() {
|
|
29049
29138
|
try {
|
|
29050
29139
|
const path = resolve43(ROOT_PRESETS_DIR, "templates", "regression-checklist.yml");
|
|
@@ -29062,7 +29151,7 @@ function runCheckCommand(cmd, cwd) {
|
|
|
29062
29151
|
if (!file)
|
|
29063
29152
|
return { passed: false, message: "Empty command" };
|
|
29064
29153
|
try {
|
|
29065
|
-
|
|
29154
|
+
execFileSync3(file, args, {
|
|
29066
29155
|
cwd,
|
|
29067
29156
|
encoding: "utf-8",
|
|
29068
29157
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -29104,7 +29193,7 @@ async function runRegressionChecklist(projectRoot, options = {}) {
|
|
|
29104
29193
|
timestamp: new Date().toISOString()
|
|
29105
29194
|
};
|
|
29106
29195
|
const outPath = resolve43(projectRoot, ".codeconductor/evaluation/regression-last.json");
|
|
29107
|
-
await mkdir26(
|
|
29196
|
+
await mkdir26(dirname15(outPath), { recursive: true });
|
|
29108
29197
|
await writeFile25(outPath, JSON.stringify(report, null, 2), "utf-8");
|
|
29109
29198
|
return ok(report);
|
|
29110
29199
|
} catch (e) {
|
|
@@ -31516,6 +31605,7 @@ var COMMANDS = [
|
|
|
31516
31605
|
{ name: "setup", group: "getting-started", summary: "Configure and install CodeConductor.", usage: ["cc-codeconductor setup [--target <target>] [--locale en|es] [--yes] [--dry-run]"] },
|
|
31517
31606
|
{ name: "detect", group: "getting-started", summary: "Inspect the project stack and recommended presets.", usage: ["cc-codeconductor detect"] },
|
|
31518
31607
|
{ name: "init", group: "getting-started", summary: "Initialize low-level CodeConductor configuration.", usage: ["cc-codeconductor init [--locale en|es]"] },
|
|
31608
|
+
{ name: "usage", group: "getting-started", summary: "Show installation examples for presets, council, and LSP.", usage: ["cc-codeconductor usage"] },
|
|
31519
31609
|
{ name: "install", group: "getting-started", summary: "Install harness components.", usage: ["cc-codeconductor install preset --target <target>"], options: ["--target opencode|claude|codex|gemini|cursor|agy|pi|all"], subcommands: [
|
|
31520
31610
|
{ name: "preset", group: "getting-started", summary: "Install agents, prompts, skills, and commands.", usage: ["cc-codeconductor install preset --target <target> [--locale en|es]"] },
|
|
31521
31611
|
{ name: "council", group: "getting-started", summary: "Install generated council files.", usage: ["cc-codeconductor install council --target <target>"] },
|
|
@@ -31629,6 +31719,96 @@ _arguments '1:command:(${names})' '--target[target]:target:(${targets})'`;
|
|
|
31629
31719
|
return null;
|
|
31630
31720
|
}
|
|
31631
31721
|
|
|
31722
|
+
// src/cli/usage-guide.ts
|
|
31723
|
+
init_cli_bin();
|
|
31724
|
+
var RECOMMENDED_FLOW = [
|
|
31725
|
+
"cc-codeconductor setup --target claude",
|
|
31726
|
+
"cc-codeconductor setup --target claude --locale es --yes",
|
|
31727
|
+
"cc-codeconductor setup --target claude --dry-run"
|
|
31728
|
+
];
|
|
31729
|
+
var PRIMITIVES = [
|
|
31730
|
+
"cc-codeconductor detect",
|
|
31731
|
+
"cc-codeconductor init --locale es",
|
|
31732
|
+
"cc-codeconductor install preset --target claude",
|
|
31733
|
+
"cc-codeconductor install council --target claude",
|
|
31734
|
+
"cc-codeconductor install lsp --target claude"
|
|
31735
|
+
];
|
|
31736
|
+
var PRESET_EXAMPLES = [
|
|
31737
|
+
"cc-codeconductor install preset --target claude",
|
|
31738
|
+
"cc-codeconductor install preset --target claude --global",
|
|
31739
|
+
"cc-codeconductor install preset --target claude --force",
|
|
31740
|
+
"cc-codeconductor install preset --target claude --dry-run",
|
|
31741
|
+
"cc-codeconductor install preset --target all",
|
|
31742
|
+
"cc-codeconductor install preset --target claude --locale es",
|
|
31743
|
+
"cc-codeconductor install preset --target claude --global --force"
|
|
31744
|
+
];
|
|
31745
|
+
var COUNCIL_EXAMPLES = [
|
|
31746
|
+
"cc-codeconductor install council --target claude",
|
|
31747
|
+
"cc-codeconductor install council --target claude --global",
|
|
31748
|
+
"cc-codeconductor install council --target claude --force",
|
|
31749
|
+
"cc-codeconductor install council --target claude --dry-run",
|
|
31750
|
+
"cc-codeconductor install council --target all",
|
|
31751
|
+
"cc-codeconductor install council --target claude --global --force"
|
|
31752
|
+
];
|
|
31753
|
+
var LSP_EXAMPLES = [
|
|
31754
|
+
"cc-codeconductor install lsp --target claude --lang typescript,python",
|
|
31755
|
+
"cc-codeconductor install lsp --target all --lang typescript,python",
|
|
31756
|
+
"cc-codeconductor install lsp --target claude --global",
|
|
31757
|
+
"cc-codeconductor install lsp --target claude --dry-run"
|
|
31758
|
+
];
|
|
31759
|
+
var AFTER_INSTALL_EXAMPLES = [
|
|
31760
|
+
["cc-codeconductor doctor", "validates the installation"],
|
|
31761
|
+
["cc-codeconductor status", "shows what is installed"],
|
|
31762
|
+
["cc-codeconductor update --dry-run", "previews reconciliation of managed files after upgrading"],
|
|
31763
|
+
["cc-codeconductor update --force", "applies reconciliation of managed files after upgrading"],
|
|
31764
|
+
["cc-codeconductor migrate --dry-run", "previews repair of orphaned artifacts a reinstall cannot fix"]
|
|
31765
|
+
];
|
|
31766
|
+
function renderExamples(lines, bin) {
|
|
31767
|
+
return lines.map((line) => ` ${formatUsage(line, bin)}`);
|
|
31768
|
+
}
|
|
31769
|
+
function renderAnnotatedExamples(entries, bin) {
|
|
31770
|
+
return entries.map(([line, description]) => ` ${formatUsage(line, bin)} — ${description}`);
|
|
31771
|
+
}
|
|
31772
|
+
function renderUsageGuide(bin = resolveCliBin()) {
|
|
31773
|
+
return [
|
|
31774
|
+
"CodeConductor — installation usage guide",
|
|
31775
|
+
"",
|
|
31776
|
+
"Recommended flow (one command, installs and configures everything):",
|
|
31777
|
+
...renderExamples(RECOMMENDED_FLOW, bin),
|
|
31778
|
+
"",
|
|
31779
|
+
"Fine-grained primitives (for scripting or partial installs):",
|
|
31780
|
+
...renderExamples(PRIMITIVES, bin),
|
|
31781
|
+
"",
|
|
31782
|
+
"Shared flags:",
|
|
31783
|
+
" --target opencode|claude|codex|gemini|cursor|agy|pi|all (default: opencode)",
|
|
31784
|
+
" --global Install to the home directory (~/.claude, ~/.opencode, etc.) instead of the project",
|
|
31785
|
+
" --force Allow overwriting existing files",
|
|
31786
|
+
" --dry-run Show what would happen without writing files",
|
|
31787
|
+
" --locale Instruction language for agent files: en (default) | es — install preset only",
|
|
31788
|
+
" --lang Comma-separated languages to install LSP servers for — install lsp only",
|
|
31789
|
+
" --output Output mode: human (default) | json",
|
|
31790
|
+
"",
|
|
31791
|
+
"install preset — agents, prompts, skills, and commands:",
|
|
31792
|
+
...renderExamples(PRESET_EXAMPLES, bin),
|
|
31793
|
+
"",
|
|
31794
|
+
"install council — generated council spec files:",
|
|
31795
|
+
...renderExamples(COUNCIL_EXAMPLES, bin),
|
|
31796
|
+
"",
|
|
31797
|
+
"install lsp — language servers:",
|
|
31798
|
+
...renderExamples(LSP_EXAMPLES, bin),
|
|
31799
|
+
" Dedicated integration config is generated for: opencode, claude, codex, gemini, cursor, agy.",
|
|
31800
|
+
" pi installs the language servers but does not get a dedicated integration config file.",
|
|
31801
|
+
"",
|
|
31802
|
+
"After installing, verify and keep in sync:",
|
|
31803
|
+
...renderAnnotatedExamples(AFTER_INSTALL_EXAMPLES, bin),
|
|
31804
|
+
"",
|
|
31805
|
+
"More detail (GitHub only, not bundled in the npm package):",
|
|
31806
|
+
" docs/usage-cli.md Detailed CLI reference, incl. per-target generated files",
|
|
31807
|
+
" docs/getting-started/ Installation, first project, and update walkthroughs"
|
|
31808
|
+
].join(`
|
|
31809
|
+
`);
|
|
31810
|
+
}
|
|
31811
|
+
|
|
31632
31812
|
// src/cli/router.ts
|
|
31633
31813
|
var OutputModeSchema = exports_external.enum(["json", "human"]);
|
|
31634
31814
|
var SeoFormatSchema = exports_external.enum(["cli", "json", "markdown"]);
|
|
@@ -31909,6 +32089,8 @@ async function routeCommand(args, projectRoot) {
|
|
|
31909
32089
|
case "docs":
|
|
31910
32090
|
case "man":
|
|
31911
32091
|
return { code: 0, data: { success: true, command, output: renderDocs(subcommand) } };
|
|
32092
|
+
case "usage":
|
|
32093
|
+
return { code: 0, data: { success: true, command: "usage", output: renderUsageGuide() } };
|
|
31912
32094
|
case "completion": {
|
|
31913
32095
|
const output = renderCompletion(subcommand ?? "");
|
|
31914
32096
|
return output ? { code: 0, data: { success: true, command: "completion", output } } : cliContractError("completion", ["Expected shell: bash, zsh, fish, or powershell."]);
|