@praneeth_54/agentdoctor 2.0.1 → 3.0.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/CHANGELOG.md +123 -1
- package/README.md +510 -260
- package/dist/agent/approvals.d.ts +24 -0
- package/dist/agent/approvals.js +64 -0
- package/dist/agent/chat/deterministic.d.ts +6 -0
- package/dist/agent/chat/deterministic.js +180 -0
- package/dist/agent/chat/index.d.ts +7 -0
- package/dist/agent/chat/index.js +5 -0
- package/dist/agent/chat/memory.d.ts +44 -0
- package/dist/agent/chat/memory.js +103 -0
- package/dist/agent/chat/project-summary.d.ts +16 -0
- package/dist/agent/chat/project-summary.js +70 -0
- package/dist/agent/chat/prompts.d.ts +6 -0
- package/dist/agent/chat/prompts.js +39 -0
- package/dist/agent/chat/response.d.ts +19 -0
- package/dist/agent/chat/response.js +109 -0
- package/dist/agent/chat/service.d.ts +42 -0
- package/dist/agent/chat/service.js +246 -0
- package/dist/agent/chat/types.d.ts +48 -0
- package/dist/agent/chat/types.js +1 -0
- package/dist/agent/context/retrieve.d.ts +21 -0
- package/dist/agent/context/retrieve.js +117 -0
- package/dist/agent/context/truth.d.ts +6 -0
- package/dist/agent/context/truth.js +19 -0
- package/dist/agent/context/types.d.ts +23 -0
- package/dist/agent/context/types.js +4 -0
- package/dist/agent/index.d.ts +28 -0
- package/dist/agent/index.js +15 -0
- package/dist/agent/loop.d.ts +53 -0
- package/dist/agent/loop.js +253 -0
- package/dist/agent/modes.d.ts +18 -0
- package/dist/agent/modes.js +102 -0
- package/dist/agent/plan.d.ts +30 -0
- package/dist/agent/plan.js +121 -0
- package/dist/agent/roles.d.ts +12 -0
- package/dist/agent/roles.js +138 -0
- package/dist/agent/runtime.d.ts +83 -0
- package/dist/agent/runtime.js +293 -0
- package/dist/agent/state.d.ts +30 -0
- package/dist/agent/state.js +95 -0
- package/dist/agent/student.d.ts +56 -0
- package/dist/agent/student.js +230 -0
- package/dist/agent/tools/execute.d.ts +20 -0
- package/dist/agent/tools/execute.js +365 -0
- package/dist/agent/tools/index.d.ts +6 -0
- package/dist/agent/tools/index.js +5 -0
- package/dist/agent/tools/registry.d.ts +7 -0
- package/dist/agent/tools/registry.js +212 -0
- package/dist/agent/tools/run.d.ts +24 -0
- package/dist/agent/tools/run.js +44 -0
- package/dist/agent/tools/types.d.ts +32 -0
- package/dist/agent/tools/types.js +10 -0
- package/dist/agent/tools/write.d.ts +24 -0
- package/dist/agent/tools/write.js +121 -0
- package/dist/agent/verify.d.ts +29 -0
- package/dist/agent/verify.js +210 -0
- package/dist/ai/config.d.ts +22 -0
- package/dist/ai/config.js +69 -0
- package/dist/ai/index.d.ts +17 -0
- package/dist/ai/index.js +52 -0
- package/dist/ai/providers/mock.d.ts +20 -0
- package/dist/ai/providers/mock.js +84 -0
- package/dist/ai/providers/none.d.ts +6 -0
- package/dist/ai/providers/none.js +23 -0
- package/dist/ai/providers/openai-compatible.d.ts +21 -0
- package/dist/ai/providers/openai-compatible.js +151 -0
- package/dist/ai/redact.d.ts +9 -0
- package/dist/ai/redact.js +61 -0
- package/dist/ai/types.d.ts +71 -0
- package/dist/ai/types.js +6 -0
- package/dist/cli/commands/agent.d.ts +29 -0
- package/dist/cli/commands/agent.js +164 -0
- package/dist/cli/commands/chat.d.ts +14 -0
- package/dist/cli/commands/chat.js +153 -0
- package/dist/cli/commands/learn.d.ts +12 -0
- package/dist/cli/commands/learn.js +107 -0
- package/dist/cli/commands/product.d.ts +19 -0
- package/dist/cli/commands/product.js +147 -0
- package/dist/cli/commands/start.d.ts +15 -0
- package/dist/cli/commands/start.js +80 -0
- package/dist/cli/program.js +233 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/dashboard/server.d.ts +6 -0
- package/dist/dashboard/server.js +333 -43
- package/dist/enforcement/runner.d.ts +5 -0
- package/dist/enforcement/runner.js +51 -4
- package/dist/index.d.ts +17 -0
- package/dist/index.js +10 -0
- package/dist/intelligence/graph/build.js +36 -8
- package/dist/intelligence/resolve/imports.js +1 -1
- package/dist/languages/dart.d.ts +10 -0
- package/dist/languages/dart.js +99 -0
- package/dist/languages/go.d.ts +13 -7
- package/dist/languages/go.js +91 -26
- package/dist/languages/index.d.ts +5 -1
- package/dist/languages/index.js +13 -36
- package/dist/languages/java.d.ts +10 -0
- package/dist/languages/java.js +80 -0
- package/dist/languages/kotlin.d.ts +10 -0
- package/dist/languages/kotlin.js +85 -0
- package/dist/languages/php.d.ts +1 -0
- package/dist/languages/php.js +11 -2
- package/dist/languages/python.d.ts +6 -2
- package/dist/languages/python.js +39 -9
- package/dist/languages/rust.d.ts +10 -0
- package/dist/languages/rust.js +93 -0
- package/dist/languages/types.d.ts +4 -3
- package/dist/mcp/agent/registry.d.ts +13 -0
- package/dist/mcp/agent/registry.js +320 -0
- package/dist/mcp/agentdoctor/server.js +8 -1
- package/dist/mcp/intelligence/handlers.d.ts +3 -0
- package/dist/mcp/intelligence/handlers.js +28 -0
- package/dist/mcp/intelligence/registry.d.ts +1 -1
- package/dist/mcp/intelligence/registry.js +30 -1
- package/dist/product/api/doctor.d.ts +14 -0
- package/dist/product/api/doctor.js +185 -0
- package/dist/product/api/openapi.d.ts +7 -0
- package/dist/product/api/openapi.js +122 -0
- package/dist/product/approval/model.d.ts +30 -0
- package/dist/product/approval/model.js +64 -0
- package/dist/product/approval/session.d.ts +49 -0
- package/dist/product/approval/session.js +134 -0
- package/dist/product/database/doctor.d.ts +30 -0
- package/dist/product/database/doctor.js +184 -0
- package/dist/product/decisions/ledger.d.ts +24 -0
- package/dist/product/decisions/ledger.js +110 -0
- package/dist/product/deps/analyze.d.ts +46 -0
- package/dist/product/deps/analyze.js +137 -0
- package/dist/product/deps/lockfiles.d.ts +25 -0
- package/dist/product/deps/lockfiles.js +200 -0
- package/dist/product/discovery/roots.d.ts +42 -0
- package/dist/product/discovery/roots.js +215 -0
- package/dist/product/dna/build.d.ts +50 -0
- package/dist/product/dna/build.js +255 -0
- package/dist/product/eval/lab.d.ts +17 -0
- package/dist/product/eval/lab.js +218 -0
- package/dist/product/events/doctor.d.ts +21 -0
- package/dist/product/events/doctor.js +147 -0
- package/dist/product/evidence-scan.d.ts +12 -0
- package/dist/product/evidence-scan.js +46 -0
- package/dist/product/evolution/timeline.d.ts +29 -0
- package/dist/product/evolution/timeline.js +123 -0
- package/dist/product/features/intelligence.d.ts +23 -0
- package/dist/product/features/intelligence.js +158 -0
- package/dist/product/forensic/mode.d.ts +25 -0
- package/dist/product/forensic/mode.js +70 -0
- package/dist/product/graph/enrich-languages.d.ts +20 -0
- package/dist/product/graph/enrich-languages.js +193 -0
- package/dist/product/health/code-health.d.ts +20 -0
- package/dist/product/health/code-health.js +149 -0
- package/dist/product/index.d.ts +69 -0
- package/dist/product/index.js +35 -0
- package/dist/product/ledger/change-ledger.d.ts +23 -0
- package/dist/product/ledger/change-ledger.js +64 -0
- package/dist/product/map/software-map.d.ts +17 -0
- package/dist/product/map/software-map.js +95 -0
- package/dist/product/memory/institutional.d.ts +16 -0
- package/dist/product/memory/institutional.js +87 -0
- package/dist/product/ops/incident.d.ts +20 -0
- package/dist/product/ops/incident.js +61 -0
- package/dist/product/ops/infra.d.ts +15 -0
- package/dist/product/ops/infra.js +112 -0
- package/dist/product/org/model.d.ts +34 -0
- package/dist/product/org/model.js +195 -0
- package/dist/product/privacy/doctor.d.ts +13 -0
- package/dist/product/privacy/doctor.js +90 -0
- package/dist/product/requirements/trace.d.ts +21 -0
- package/dist/product/requirements/trace.js +166 -0
- package/dist/product/search/index.d.ts +29 -0
- package/dist/product/search/index.js +116 -0
- package/dist/product/search/software-search.d.ts +19 -0
- package/dist/product/search/software-search.js +100 -0
- package/dist/product/security/doctor.d.ts +23 -0
- package/dist/product/security/doctor.js +124 -0
- package/dist/product/self/diagnose.d.ts +15 -0
- package/dist/product/self/diagnose.js +82 -0
- package/dist/product/techdebt/roadmap.d.ts +20 -0
- package/dist/product/techdebt/roadmap.js +118 -0
- package/dist/product/testbrain/analyze.d.ts +29 -0
- package/dist/product/testbrain/analyze.js +129 -0
- package/dist/product/truth.d.ts +12 -0
- package/dist/product/truth.js +30 -0
- package/dist/product/twin/digital-twin.d.ts +23 -0
- package/dist/product/twin/digital-twin.js +52 -0
- package/dist/product/twin/store.d.ts +21 -0
- package/dist/product/twin/store.js +70 -0
- package/dist/product/whatif/engine.d.ts +28 -0
- package/dist/product/whatif/engine.js +70 -0
- package/dist/security/paths.js +43 -15
- package/dist/utils/fs.js +10 -2
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { EXIT_CODES } from "../../types/index.js";
|
|
2
|
+
import { resolveRepoRoot } from "../../utils/path.js";
|
|
3
|
+
import { resolveTargetArgument } from "./scan.js";
|
|
4
|
+
import { traceRequirements, analyzeApiSurface, analyzeDatabaseSchema, analyzeEvents, analyzeDependencies, analyzeCodeHealth, buildSoftwareMap, analyzeWhatIf, loadDecisionLedger, runForensicAnalysis, buildSoftwareDigitalTwin, runEvalLab, diagnoseAgentDoctorSelf, analyzeInfra, buildIncidentHypotheses, readChangeLedger, analyzeSecuritySurface, analyzePrivacySurface, searchSymbolsAndConcepts, buildTechnicalDebtRoadmap, analyzeFeatureIntelligence, buildSoftwareEvolutionTimeline, queryMemory, loadOrganizationModel, analyzeTestBrain, } from "../../product/index.js";
|
|
5
|
+
import { runRoleAgent } from "../../agent/roles.js";
|
|
6
|
+
function printJson(value) {
|
|
7
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
8
|
+
}
|
|
9
|
+
export async function runProductCommand(options) {
|
|
10
|
+
const root = resolveRepoRoot(options.root ?? resolveTargetArgument(undefined));
|
|
11
|
+
try {
|
|
12
|
+
let payload;
|
|
13
|
+
switch (options.action) {
|
|
14
|
+
case "requirements":
|
|
15
|
+
payload = await traceRequirements(root);
|
|
16
|
+
break;
|
|
17
|
+
case "api":
|
|
18
|
+
payload = await analyzeApiSurface(root);
|
|
19
|
+
break;
|
|
20
|
+
case "database":
|
|
21
|
+
payload = await analyzeDatabaseSchema(root);
|
|
22
|
+
break;
|
|
23
|
+
case "events":
|
|
24
|
+
payload = await analyzeEvents(root);
|
|
25
|
+
break;
|
|
26
|
+
case "dependency":
|
|
27
|
+
payload = await analyzeDependencies(root);
|
|
28
|
+
break;
|
|
29
|
+
case "health-code":
|
|
30
|
+
payload = await analyzeCodeHealth(root);
|
|
31
|
+
break;
|
|
32
|
+
case "map":
|
|
33
|
+
payload = await buildSoftwareMap(root);
|
|
34
|
+
break;
|
|
35
|
+
case "what-if":
|
|
36
|
+
if (!options.target) {
|
|
37
|
+
console.error("Error: what-if requires a file path or symbol target (--target or argument)");
|
|
38
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
39
|
+
}
|
|
40
|
+
payload = await analyzeWhatIf(root, options.target);
|
|
41
|
+
break;
|
|
42
|
+
case "decisions":
|
|
43
|
+
payload = await loadDecisionLedger(root);
|
|
44
|
+
break;
|
|
45
|
+
case "forensic":
|
|
46
|
+
payload = await runForensicAnalysis(root);
|
|
47
|
+
break;
|
|
48
|
+
case "twin":
|
|
49
|
+
payload = await buildSoftwareDigitalTwin(root);
|
|
50
|
+
break;
|
|
51
|
+
case "eval-lab":
|
|
52
|
+
payload = await runEvalLab(root);
|
|
53
|
+
break;
|
|
54
|
+
case "self-check":
|
|
55
|
+
payload = await diagnoseAgentDoctorSelf(root);
|
|
56
|
+
break;
|
|
57
|
+
case "infra":
|
|
58
|
+
payload = await analyzeInfra(root);
|
|
59
|
+
break;
|
|
60
|
+
case "incident":
|
|
61
|
+
payload = await buildIncidentHypotheses(root, options.changedFiles ? { changedFiles: options.changedFiles } : undefined);
|
|
62
|
+
break;
|
|
63
|
+
case "security-doctor":
|
|
64
|
+
payload = await analyzeSecuritySurface(root);
|
|
65
|
+
break;
|
|
66
|
+
case "privacy-doctor":
|
|
67
|
+
payload = await analyzePrivacySurface(root);
|
|
68
|
+
break;
|
|
69
|
+
case "search":
|
|
70
|
+
if (!options.query?.trim()) {
|
|
71
|
+
console.error("Error: search requires a query (--query or argument)");
|
|
72
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
73
|
+
}
|
|
74
|
+
payload = await searchSymbolsAndConcepts(root, options.query);
|
|
75
|
+
break;
|
|
76
|
+
case "tech-debt":
|
|
77
|
+
payload = await buildTechnicalDebtRoadmap(root);
|
|
78
|
+
break;
|
|
79
|
+
case "features":
|
|
80
|
+
payload = await analyzeFeatureIntelligence(root);
|
|
81
|
+
break;
|
|
82
|
+
case "evolution":
|
|
83
|
+
payload = await buildSoftwareEvolutionTimeline(root);
|
|
84
|
+
break;
|
|
85
|
+
case "memory":
|
|
86
|
+
if (!options.query?.trim()) {
|
|
87
|
+
console.error("Error: memory requires a query (--query or argument)");
|
|
88
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
89
|
+
}
|
|
90
|
+
payload = await queryMemory(root, options.query);
|
|
91
|
+
break;
|
|
92
|
+
case "org":
|
|
93
|
+
payload = await loadOrganizationModel(root);
|
|
94
|
+
break;
|
|
95
|
+
case "test-brain":
|
|
96
|
+
payload = await analyzeTestBrain({ root });
|
|
97
|
+
break;
|
|
98
|
+
case "role-agent":
|
|
99
|
+
if (!options.role || !options.goal?.trim()) {
|
|
100
|
+
console.error("Error: role-agent requires --role and --goal");
|
|
101
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
102
|
+
}
|
|
103
|
+
if (options.apply && !options.approve) {
|
|
104
|
+
console.error("Error: role-agent --apply requires --approve");
|
|
105
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
106
|
+
}
|
|
107
|
+
payload = await runRoleAgent({
|
|
108
|
+
role: options.role,
|
|
109
|
+
goal: options.goal,
|
|
110
|
+
root,
|
|
111
|
+
approvedByHuman: options.approve === true,
|
|
112
|
+
});
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
116
|
+
}
|
|
117
|
+
if (options.json) {
|
|
118
|
+
printJson(payload);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const action = options.action;
|
|
122
|
+
process.stdout.write(`AgentDoctor ${action} completed for ${root}\n`);
|
|
123
|
+
if (action === "self-check" && payload && typeof payload === "object" && "ok" in payload) {
|
|
124
|
+
process.stdout.write(` ok: ${payload.ok}\n`);
|
|
125
|
+
}
|
|
126
|
+
if (action === "eval-lab" && payload && typeof payload === "object" && "passed" in payload) {
|
|
127
|
+
process.stdout.write(` passed: ${payload.passed}\n`);
|
|
128
|
+
}
|
|
129
|
+
process.stdout.write(" (use --json for full report)\n");
|
|
130
|
+
}
|
|
131
|
+
return EXIT_CODES.SUCCESS;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
135
|
+
console.error(`Error: ${message}`);
|
|
136
|
+
return EXIT_CODES.INTERNAL_ERROR;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
export async function runChangeLedgerListCommand(options) {
|
|
140
|
+
const root = resolveRepoRoot(options.root ?? process.cwd());
|
|
141
|
+
const payload = await readChangeLedger(root);
|
|
142
|
+
if (options.json)
|
|
143
|
+
printJson(payload);
|
|
144
|
+
else
|
|
145
|
+
process.stdout.write(`Change ledger entries: ${payload.entries.length}\n`);
|
|
146
|
+
return EXIT_CODES.SUCCESS;
|
|
147
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ExitCode } from "../../types/index.js";
|
|
2
|
+
export declare function runStartCommand(options: {
|
|
3
|
+
root?: string;
|
|
4
|
+
json?: boolean;
|
|
5
|
+
select?: string;
|
|
6
|
+
maxEntries?: number;
|
|
7
|
+
initBrain?: boolean;
|
|
8
|
+
rebuildBrain?: boolean;
|
|
9
|
+
listOnly?: boolean;
|
|
10
|
+
}): Promise<ExitCode>;
|
|
11
|
+
export declare function runDnaCommand(options: {
|
|
12
|
+
root?: string;
|
|
13
|
+
json?: boolean;
|
|
14
|
+
persist?: boolean;
|
|
15
|
+
}): Promise<ExitCode>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { EXIT_CODES } from "../../types/index.js";
|
|
2
|
+
import { initBrainStore, rebuildBrain, getBrainStatus } from "../../core/brain-cli/service.js";
|
|
3
|
+
import { discoverProjectRoots } from "../../product/discovery/roots.js";
|
|
4
|
+
import { buildProjectDna, persistProjectDna } from "../../product/dna/build.js";
|
|
5
|
+
import { resolveRepoRoot } from "../../utils/path.js";
|
|
6
|
+
function printJson(value) {
|
|
7
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
8
|
+
}
|
|
9
|
+
export async function runStartCommand(options) {
|
|
10
|
+
const prefer = options.select ?? options.root;
|
|
11
|
+
const discovery = await discoverProjectRoots({
|
|
12
|
+
cwd: prefer ? resolveRepoRoot(prefer) : process.cwd(),
|
|
13
|
+
...(prefer ? { prefer: resolveRepoRoot(prefer) } : {}),
|
|
14
|
+
...(options.maxEntries !== undefined ? { maxEntries: options.maxEntries } : {}),
|
|
15
|
+
autoSelect: !options.listOnly,
|
|
16
|
+
});
|
|
17
|
+
if (options.listOnly || discovery.blocked || !discovery.selected) {
|
|
18
|
+
if (options.json) {
|
|
19
|
+
printJson({ discovery, dna: null, brain: null });
|
|
20
|
+
return discovery.blocked ? EXIT_CODES.USAGE_ERROR : EXIT_CODES.SUCCESS;
|
|
21
|
+
}
|
|
22
|
+
if (discovery.blocked) {
|
|
23
|
+
process.stderr.write(`Blocked: ${discovery.blockReason}\n`);
|
|
24
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
25
|
+
}
|
|
26
|
+
process.stdout.write("Project candidates:\n");
|
|
27
|
+
if (discovery.candidates.length === 0) {
|
|
28
|
+
process.stdout.write(" (none found — navigate into a project or pass a path)\n");
|
|
29
|
+
return EXIT_CODES.USAGE_ERROR;
|
|
30
|
+
}
|
|
31
|
+
for (const [i, c] of discovery.candidates.entries()) {
|
|
32
|
+
process.stdout.write(` [${i + 1}] ${c.root}\n score=${c.score} markers=${c.markers.join(", ")} (${c.reason})\n`);
|
|
33
|
+
}
|
|
34
|
+
process.stdout.write("\nRe-run with --select <path> to initialize that project.\n");
|
|
35
|
+
return EXIT_CODES.SUCCESS;
|
|
36
|
+
}
|
|
37
|
+
const root = discovery.selected.root;
|
|
38
|
+
const dna = await persistProjectDna(root);
|
|
39
|
+
let brainStatus = null;
|
|
40
|
+
if (options.initBrain !== false) {
|
|
41
|
+
brainStatus = await initBrainStore(root);
|
|
42
|
+
if (options.rebuildBrain) {
|
|
43
|
+
await rebuildBrain(root);
|
|
44
|
+
brainStatus = await getBrainStatus(root);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const payload = { discovery, dna, brain: brainStatus };
|
|
48
|
+
if (options.json) {
|
|
49
|
+
printJson(payload);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
process.stdout.write(`AgentDoctor start\n`);
|
|
53
|
+
process.stdout.write(` root: ${root}\n`);
|
|
54
|
+
process.stdout.write(` fingerprint: ${dna.fingerprint}\n`);
|
|
55
|
+
process.stdout.write(` type: ${dna.projectType}\n`);
|
|
56
|
+
process.stdout.write(` languages: ${dna.languages.join(", ") || "(none)"}\n`);
|
|
57
|
+
process.stdout.write(` frameworks: ${dna.frameworks.join(", ") || "(none)"}\n`);
|
|
58
|
+
process.stdout.write(` files: ${dna.counts.files} (source ${dna.counts.sourceFiles}, tests ${dna.counts.testFiles})\n`);
|
|
59
|
+
if (brainStatus) {
|
|
60
|
+
process.stdout.write(` brain: ${brainStatus.hasSnapshot ? `snapshot ${brainStatus.latestSnapshotId}` : "initialized (no snapshot yet — run with --rebuild-brain or brain rebuild)"}\n`);
|
|
61
|
+
}
|
|
62
|
+
process.stdout.write(` DNA written to .agentdoctor/dna/project-dna.json\n`);
|
|
63
|
+
}
|
|
64
|
+
return EXIT_CODES.SUCCESS;
|
|
65
|
+
}
|
|
66
|
+
export async function runDnaCommand(options) {
|
|
67
|
+
const root = resolveRepoRoot(options.root ?? process.cwd());
|
|
68
|
+
const dna = options.persist ? await persistProjectDna(root) : await buildProjectDna(root);
|
|
69
|
+
if (options.json) {
|
|
70
|
+
printJson(dna);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
process.stdout.write(`Project DNA: ${dna.name} (${dna.fingerprint})\n`);
|
|
74
|
+
process.stdout.write(` type: ${dna.projectType}\n`);
|
|
75
|
+
process.stdout.write(` languages: ${dna.languages.join(", ") || "(none)"}\n`);
|
|
76
|
+
process.stdout.write(` frameworks: ${dna.frameworks.join(", ") || "(none)"}\n`);
|
|
77
|
+
process.stdout.write(` monorepo: ${dna.monorepo.isMonorepo ? dna.monorepo.tool : "no"}\n`);
|
|
78
|
+
}
|
|
79
|
+
return EXIT_CODES.SUCCESS;
|
|
80
|
+
}
|
package/dist/cli/program.js
CHANGED
|
@@ -17,6 +17,11 @@ import { runChangeAnalyzeCommand, runChangeDiffCommand, runChangeExplainCommand,
|
|
|
17
17
|
import { runGraphSurfaceCommand, runPolicyCheckCommand, runPolicyEnforceCommand, runPolicyExplainCommand, runRunCommand, runRunExplainCommand, } from "./commands/policy-graph-run.js";
|
|
18
18
|
import { runArchitectureCommand } from "./commands/architecture.js";
|
|
19
19
|
import { runWorkspaceCommand } from "./commands/workspace.js";
|
|
20
|
+
import { runAskCommand, runChatCommand } from "./commands/chat.js";
|
|
21
|
+
import { runAgentCommand, runPlanCommand } from "./commands/agent.js";
|
|
22
|
+
import { runLearnCommand } from "./commands/learn.js";
|
|
23
|
+
import { runProductCommand } from "./commands/product.js";
|
|
24
|
+
import { runStartCommand, runDnaCommand } from "./commands/start.js";
|
|
20
25
|
import { collectOpsHealth } from "../ops/health.js";
|
|
21
26
|
import { listSessions, loadSession } from "../platform/sessions/store.js";
|
|
22
27
|
import { exportReports } from "../platform/reports/export.js";
|
|
@@ -1235,6 +1240,97 @@ export function createProgram() {
|
|
|
1235
1240
|
json: Boolean(options.json),
|
|
1236
1241
|
});
|
|
1237
1242
|
});
|
|
1243
|
+
program
|
|
1244
|
+
.command("chat")
|
|
1245
|
+
.description("Project Chat (2.1): evidence-backed conversation about this repository (requires AI provider)")
|
|
1246
|
+
.argument("[path]", "Repository path (default: current directory)")
|
|
1247
|
+
.action(async (pathArg) => {
|
|
1248
|
+
process.exitCode = await runChatCommand({
|
|
1249
|
+
root: resolveTargetArgument(pathArg),
|
|
1250
|
+
});
|
|
1251
|
+
});
|
|
1252
|
+
program
|
|
1253
|
+
.command("ask")
|
|
1254
|
+
.description("One-shot Project Chat question (same engine as chat)")
|
|
1255
|
+
.argument("<question>", "Question about the project")
|
|
1256
|
+
.argument("[path]", "Repository path (default: current directory)")
|
|
1257
|
+
.option("--json", "Emit JSON response", false)
|
|
1258
|
+
.action(async (question, pathArg, options) => {
|
|
1259
|
+
process.exitCode = await runAskCommand({
|
|
1260
|
+
question,
|
|
1261
|
+
root: resolveTargetArgument(pathArg),
|
|
1262
|
+
json: Boolean(options.json),
|
|
1263
|
+
});
|
|
1264
|
+
});
|
|
1265
|
+
program
|
|
1266
|
+
.command("plan")
|
|
1267
|
+
.description("Project Agent plan (2.1 M3): understand goal, list likely files, request approval — no file edits")
|
|
1268
|
+
.argument("<goal>", "What you want to build or change")
|
|
1269
|
+
.argument("[path]", "Repository path (default: current directory)")
|
|
1270
|
+
.option("--json", "Emit JSON plan", false)
|
|
1271
|
+
.option("--approve", "Record human approval (still no writes in M3)", false)
|
|
1272
|
+
.action(async (goal, pathArg, options) => {
|
|
1273
|
+
process.exitCode = await runPlanCommand({
|
|
1274
|
+
goal,
|
|
1275
|
+
root: resolveTargetArgument(pathArg),
|
|
1276
|
+
json: Boolean(options.json),
|
|
1277
|
+
approve: Boolean(options.approve),
|
|
1278
|
+
});
|
|
1279
|
+
});
|
|
1280
|
+
program
|
|
1281
|
+
.command("agent")
|
|
1282
|
+
.description("Project Agent (2.1): list tools, run tools, plan, or apply approved file/command changes")
|
|
1283
|
+
.argument("[path]", "Repository path (default: current directory)")
|
|
1284
|
+
.option("--list-tools", "List available agent tools", false)
|
|
1285
|
+
.option("--tool <name>", "Run a single tool by name")
|
|
1286
|
+
.option("--goal <text>", "Build a change plan for this goal")
|
|
1287
|
+
.option("--role <role>", "Specialized role for plan/apply (planner, coder, tester, reviewer, security, …)")
|
|
1288
|
+
.option("--approve", "Record explicit human approval", false)
|
|
1289
|
+
.option("--apply", "Apply approved changes (requires --approve)", false)
|
|
1290
|
+
.option("--apply-ops <json>", "JSON array of {name, arguments} tool ops for --apply")
|
|
1291
|
+
.option("--skip-verify", "Skip post-change verification after apply", false)
|
|
1292
|
+
.option("--run-tests", "Run controlled tests during verification", false)
|
|
1293
|
+
.option("--json", "Emit JSON", false)
|
|
1294
|
+
.action(async (pathArg, options) => {
|
|
1295
|
+
process.exitCode = await runAgentCommand({
|
|
1296
|
+
root: resolveTargetArgument(pathArg),
|
|
1297
|
+
listTools: Boolean(options.listTools),
|
|
1298
|
+
...(options.tool !== undefined ? { tool: options.tool } : {}),
|
|
1299
|
+
...(options.goal !== undefined ? { goal: options.goal } : {}),
|
|
1300
|
+
...(options.role !== undefined ? { role: options.role } : {}),
|
|
1301
|
+
approve: Boolean(options.approve),
|
|
1302
|
+
apply: Boolean(options.apply),
|
|
1303
|
+
...(options.applyOps !== undefined ? { applyOpsJson: options.applyOps } : {}),
|
|
1304
|
+
verify: !options.skipVerify,
|
|
1305
|
+
runTests: Boolean(options.runTests),
|
|
1306
|
+
json: Boolean(options.json),
|
|
1307
|
+
});
|
|
1308
|
+
});
|
|
1309
|
+
program
|
|
1310
|
+
.command("learn")
|
|
1311
|
+
.description("Student Learn mode (2.1 M6): explain project, viva questions, grounded documentation")
|
|
1312
|
+
.argument("[path]", "Repository path (default: current directory)")
|
|
1313
|
+
.option("--mode <mode>", "LEARN | BUILD_WITH_ME | BUILD_FOR_ME | DEVELOPER", "LEARN")
|
|
1314
|
+
.option("--viva", "Generate viva questions from detected stack", false)
|
|
1315
|
+
.option("--docs", "Generate project documentation sections", false)
|
|
1316
|
+
.option("--build <goal>", "BUILD_WITH_ME / BUILD_FOR_ME: explain, plan, then coding loop")
|
|
1317
|
+
.option("--approve", "Human approval required before BUILD writes", false)
|
|
1318
|
+
.option("--apply-ops <json>", "Deterministic tool ops JSON array for --build --approve")
|
|
1319
|
+
.option("--json", "Emit JSON", false)
|
|
1320
|
+
.option("--mock", "Use MockModelProvider", false)
|
|
1321
|
+
.action(async (pathArg, options) => {
|
|
1322
|
+
process.exitCode = await runLearnCommand({
|
|
1323
|
+
root: resolveTargetArgument(pathArg),
|
|
1324
|
+
...(options.mode !== undefined ? { mode: options.mode } : {}),
|
|
1325
|
+
viva: Boolean(options.viva),
|
|
1326
|
+
docs: Boolean(options.docs),
|
|
1327
|
+
...(options.build !== undefined ? { build: options.build } : {}),
|
|
1328
|
+
approve: Boolean(options.approve),
|
|
1329
|
+
...(options.applyOps !== undefined ? { applyOpsJson: options.applyOps } : {}),
|
|
1330
|
+
json: Boolean(options.json),
|
|
1331
|
+
useMock: Boolean(options.mock),
|
|
1332
|
+
});
|
|
1333
|
+
});
|
|
1238
1334
|
const platform = program
|
|
1239
1335
|
.command("platform")
|
|
1240
1336
|
.description("AgentDoctor 2.0 local platform (intelligence, Action Policy Evaluator, sessions, reports)");
|
|
@@ -1451,6 +1547,143 @@ export function createProgram() {
|
|
|
1451
1547
|
const code = await runExplainCommand(rule);
|
|
1452
1548
|
process.exitCode = code;
|
|
1453
1549
|
});
|
|
1550
|
+
function bindProductCommand(name, description, action) {
|
|
1551
|
+
program
|
|
1552
|
+
.command(name)
|
|
1553
|
+
.description(description)
|
|
1554
|
+
.argument("[path]", "Repository path")
|
|
1555
|
+
.option("--json", "Emit JSON report", false)
|
|
1556
|
+
.action(async (pathArg, _options, command) => {
|
|
1557
|
+
const options = command.optsWithGlobals();
|
|
1558
|
+
process.exitCode = await runProductCommand({
|
|
1559
|
+
action,
|
|
1560
|
+
root: resolveTargetArgument(pathArg),
|
|
1561
|
+
json: Boolean(options.json),
|
|
1562
|
+
});
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
program
|
|
1566
|
+
.command("start")
|
|
1567
|
+
.description("Safe project discovery: detect project root, build Project DNA, initialize Project Brain")
|
|
1568
|
+
.argument("[path]", "Optional project path (default: cwd)")
|
|
1569
|
+
.option("--list", "List candidates without initializing", false)
|
|
1570
|
+
.option("--select <path>", "Explicitly select a project root")
|
|
1571
|
+
.option("--max-entries <n>", "Refuse scans larger than this entry budget", "25000")
|
|
1572
|
+
.option("--no-init-brain", "Skip Project Brain store initialization")
|
|
1573
|
+
.option("--rebuild-brain", "Compile Project Brain after init", false)
|
|
1574
|
+
.option("--json", "Emit JSON", false)
|
|
1575
|
+
.action(async (pathArg, options) => {
|
|
1576
|
+
process.exitCode = await runStartCommand({
|
|
1577
|
+
...(pathArg !== undefined ? { root: resolveTargetArgument(pathArg) } : {}),
|
|
1578
|
+
listOnly: Boolean(options.list),
|
|
1579
|
+
...(options.select !== undefined ? { select: options.select } : {}),
|
|
1580
|
+
maxEntries: Number(options.maxEntries ?? 25000),
|
|
1581
|
+
initBrain: options.initBrain !== false,
|
|
1582
|
+
rebuildBrain: Boolean(options.rebuildBrain),
|
|
1583
|
+
json: Boolean(options.json),
|
|
1584
|
+
});
|
|
1585
|
+
});
|
|
1586
|
+
program
|
|
1587
|
+
.command("dna")
|
|
1588
|
+
.description("Build deterministic Project DNA fingerprint")
|
|
1589
|
+
.argument("[path]", "Repository path")
|
|
1590
|
+
.option("--persist", "Write .agentdoctor/dna/project-dna.json", false)
|
|
1591
|
+
.option("--json", "Emit JSON", false)
|
|
1592
|
+
.action(async (pathArg, options) => {
|
|
1593
|
+
process.exitCode = await runDnaCommand({
|
|
1594
|
+
root: resolveTargetArgument(pathArg),
|
|
1595
|
+
persist: Boolean(options.persist),
|
|
1596
|
+
json: Boolean(options.json),
|
|
1597
|
+
});
|
|
1598
|
+
});
|
|
1599
|
+
bindProductCommand("requirements", "Trace requirements from markdown docs (evidence-backed)", "requirements");
|
|
1600
|
+
bindProductCommand("api", "Discover HTTP route patterns (regex evidence)", "api");
|
|
1601
|
+
bindProductCommand("database", "Discover schema objects from migrations/SQL/Prisma", "database");
|
|
1602
|
+
bindProductCommand("events", "Detect queues, workers, cron, and event markers", "events");
|
|
1603
|
+
bindProductCommand("dependency", "Analyze direct dependencies and workspace duplicates", "dependency");
|
|
1604
|
+
bindProductCommand("deps", "Alias for dependency", "dependency");
|
|
1605
|
+
bindProductCommand("health-code", "Aggregate code health indicators with evidence", "health-code");
|
|
1606
|
+
bindProductCommand("code-health", "Alias for health-code", "health-code");
|
|
1607
|
+
bindProductCommand("map", "Build navigable software map from project layout", "map");
|
|
1608
|
+
bindProductCommand("decisions", "Load ADR files and decision ledger", "decisions");
|
|
1609
|
+
bindProductCommand("forensic", "Read-only forensic analysis (git + ledgers + brain)", "forensic");
|
|
1610
|
+
bindProductCommand("twin", "Software digital twin snapshot", "twin");
|
|
1611
|
+
bindProductCommand("eval-lab", "Run evaluation lab fixture checks", "eval-lab");
|
|
1612
|
+
bindProductCommand("self-check", "Self-diagnosis of AgentDoctor installation", "self-check");
|
|
1613
|
+
bindProductCommand("infra", "Detect Docker/K8s/Terraform/CI artifacts", "infra");
|
|
1614
|
+
bindProductCommand("incident", "Build incident timeline hypotheses", "incident");
|
|
1615
|
+
bindProductCommand("security-doctor", "Security heuristics: secrets, auth markers, dangerous patterns", "security-doctor");
|
|
1616
|
+
bindProductCommand("test-brain", "Test Brain: test-impact plus graph file↔test mapping", "test-brain");
|
|
1617
|
+
bindProductCommand("privacy-doctor", "PII-ish pattern scan (not legal compliance)", "privacy-doctor");
|
|
1618
|
+
bindProductCommand("tech-debt", "Technical debt roadmap (TODO/FIXME, architecture, tests)", "tech-debt");
|
|
1619
|
+
bindProductCommand("features", "Feature intelligence (flows + API links)", "features");
|
|
1620
|
+
bindProductCommand("evolution", "Software evolution timeline from git + ledger", "evolution");
|
|
1621
|
+
bindProductCommand("org", "Load organization model (.agentdoctor/org)", "org");
|
|
1622
|
+
program
|
|
1623
|
+
.command("memory")
|
|
1624
|
+
.description("Query institutional memory (brain + ledgers)")
|
|
1625
|
+
.argument("<query>", "Memory query")
|
|
1626
|
+
.argument("[path]", "Repository path")
|
|
1627
|
+
.option("--json", "Emit JSON report", false)
|
|
1628
|
+
.action(async (query, pathArg, _options, command) => {
|
|
1629
|
+
const options = command.optsWithGlobals();
|
|
1630
|
+
process.exitCode = await runProductCommand({
|
|
1631
|
+
action: "memory",
|
|
1632
|
+
query,
|
|
1633
|
+
root: resolveTargetArgument(pathArg),
|
|
1634
|
+
json: Boolean(options.json),
|
|
1635
|
+
});
|
|
1636
|
+
});
|
|
1637
|
+
program
|
|
1638
|
+
.command("search")
|
|
1639
|
+
.description("Search symbols and concepts (brain + bounded file scan)")
|
|
1640
|
+
.argument("<query>", "Search query")
|
|
1641
|
+
.argument("[path]", "Repository path")
|
|
1642
|
+
.option("--json", "Emit JSON report", false)
|
|
1643
|
+
.action(async (query, pathArg, _options, command) => {
|
|
1644
|
+
const options = command.optsWithGlobals();
|
|
1645
|
+
process.exitCode = await runProductCommand({
|
|
1646
|
+
action: "search",
|
|
1647
|
+
query,
|
|
1648
|
+
root: resolveTargetArgument(pathArg),
|
|
1649
|
+
json: Boolean(options.json),
|
|
1650
|
+
});
|
|
1651
|
+
});
|
|
1652
|
+
program
|
|
1653
|
+
.command("role-agent")
|
|
1654
|
+
.description("Run the coding loop with a specialized agent role")
|
|
1655
|
+
.argument("[path]", "Repository path")
|
|
1656
|
+
.requiredOption("--role <role>", "Agent role (planner, coder, tester, reviewer, security, …)")
|
|
1657
|
+
.requiredOption("--goal <text>", "Goal for the role agent")
|
|
1658
|
+
.option("--approve", "Record human approval for writes", false)
|
|
1659
|
+
.option("--apply", "Apply changes (requires --approve)", false)
|
|
1660
|
+
.option("--json", "Emit JSON", false)
|
|
1661
|
+
.action(async (pathArg, options) => {
|
|
1662
|
+
process.exitCode = await runProductCommand({
|
|
1663
|
+
action: "role-agent",
|
|
1664
|
+
root: resolveTargetArgument(pathArg),
|
|
1665
|
+
role: options.role,
|
|
1666
|
+
goal: options.goal,
|
|
1667
|
+
approve: Boolean(options.approve),
|
|
1668
|
+
apply: Boolean(options.apply),
|
|
1669
|
+
json: Boolean(options.json),
|
|
1670
|
+
});
|
|
1671
|
+
});
|
|
1672
|
+
program
|
|
1673
|
+
.command("what-if")
|
|
1674
|
+
.description("Graph-backed change impact for a file or symbol")
|
|
1675
|
+
.argument("<target>", "File path or symbol")
|
|
1676
|
+
.argument("[path]", "Repository path")
|
|
1677
|
+
.option("--json", "Emit JSON report", false)
|
|
1678
|
+
.action(async (target, pathArg, _options, command) => {
|
|
1679
|
+
const options = command.optsWithGlobals();
|
|
1680
|
+
process.exitCode = await runProductCommand({
|
|
1681
|
+
action: "what-if",
|
|
1682
|
+
root: resolveTargetArgument(pathArg),
|
|
1683
|
+
target,
|
|
1684
|
+
json: Boolean(options.json),
|
|
1685
|
+
});
|
|
1686
|
+
});
|
|
1454
1687
|
program
|
|
1455
1688
|
.command("doctor")
|
|
1456
1689
|
.description("Check AgentDoctor installation health")
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentId } from "./types/index.js";
|
|
2
|
-
export declare const PACKAGE_VERSION = "
|
|
2
|
+
export declare const PACKAGE_VERSION = "3.0.0";
|
|
3
3
|
export declare const DEFAULT_MAX_FILE_SIZE_BYTES: number;
|
|
4
4
|
/** Directories skipped during normal discovery (unless a rule needs them later). */
|
|
5
5
|
export declare const DEFAULT_IGNORE_DIRECTORIES: Set<string>;
|
package/dist/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = "
|
|
1
|
+
export const PACKAGE_VERSION = "3.0.0";
|
|
2
2
|
export const DEFAULT_MAX_FILE_SIZE_BYTES = 2 * 1024 * 1024; // 2 MiB
|
|
3
3
|
/** Directories skipped during normal discovery (unless a rule needs them later). */
|
|
4
4
|
export const DEFAULT_IGNORE_DIRECTORIES = new Set([
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ModelProvider } from "../ai/types.js";
|
|
1
2
|
export interface DashboardServerOptions {
|
|
2
3
|
root: string;
|
|
3
4
|
host?: string;
|
|
@@ -9,6 +10,11 @@ export interface DashboardServerOptions {
|
|
|
9
10
|
* Query ?user= is a localDevIdentityHint only; role elevation requires AGENTDOCTOR_ALLOW_LOCAL_IDENTITY_HINT=1.
|
|
10
11
|
*/
|
|
11
12
|
allowNonLoopback?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Optional provider override (tests). Production uses loadAiConfig().
|
|
15
|
+
* When unset and provider resolves to none, /api/chat fails closed.
|
|
16
|
+
*/
|
|
17
|
+
chatProvider?: ModelProvider;
|
|
12
18
|
}
|
|
13
19
|
export declare function isLoopbackHost(host: string): boolean;
|
|
14
20
|
/**
|