@mcp-graph-workflow/agent-graph-flow 0.1.4 → 0.2.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/dist/cli/index.js +1069 -259
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2863,6 +2863,33 @@ var init_migrations = __esm({
|
|
|
2863
2863
|
FROM events e
|
|
2864
2864
|
WHERE e.kind = 'tool.completed'
|
|
2865
2865
|
AND e.subjectRef_kind = 'mcp.tool';
|
|
2866
|
+
`
|
|
2867
|
+
},
|
|
2868
|
+
{
|
|
2869
|
+
version: 96,
|
|
2870
|
+
// λ_flow (transient-hypofrontality) telemetry. Records, per context call, the
|
|
2871
|
+
// flow state (Φ, λ_flow) and how much topological decay pruned vs. pinned,
|
|
2872
|
+
// tagged flow_on/flow_off for A/B. Telemetry-only — never affects graph state.
|
|
2873
|
+
// Pairs with flow-metrics-store.ts / flow-report.ts.
|
|
2874
|
+
description: "flow_metrics \u2014 \u03BB_flow (hipofrontalidade) A/B telemetry",
|
|
2875
|
+
sql: `
|
|
2876
|
+
CREATE TABLE IF NOT EXISTS flow_metrics (
|
|
2877
|
+
id TEXT PRIMARY KEY,
|
|
2878
|
+
project_id TEXT NOT NULL,
|
|
2879
|
+
node_id TEXT NOT NULL,
|
|
2880
|
+
mode TEXT NOT NULL,
|
|
2881
|
+
phi REAL NOT NULL,
|
|
2882
|
+
lambda REAL NOT NULL,
|
|
2883
|
+
tokens_baseline INTEGER NOT NULL,
|
|
2884
|
+
tokens_actual INTEGER NOT NULL,
|
|
2885
|
+
pruned_count INTEGER NOT NULL,
|
|
2886
|
+
pinned_count INTEGER NOT NULL,
|
|
2887
|
+
created_at INTEGER NOT NULL
|
|
2888
|
+
);
|
|
2889
|
+
CREATE INDEX IF NOT EXISTS idx_flow_metrics_project_created
|
|
2890
|
+
ON flow_metrics(project_id, created_at DESC);
|
|
2891
|
+
CREATE INDEX IF NOT EXISTS idx_flow_metrics_mode
|
|
2892
|
+
ON flow_metrics(mode, created_at DESC);
|
|
2866
2893
|
`
|
|
2867
2894
|
}
|
|
2868
2895
|
];
|
|
@@ -5408,6 +5435,13 @@ function getNodeAcTexts(doc, nodeId) {
|
|
|
5408
5435
|
if (inline.length > 0) return inline;
|
|
5409
5436
|
return _acByParent.get(nodeId) ?? [];
|
|
5410
5437
|
}
|
|
5438
|
+
function getNodeAcFromStore(store2, nodeId) {
|
|
5439
|
+
const node = store2.getNodeById(nodeId);
|
|
5440
|
+
if (!node) return [];
|
|
5441
|
+
const inline = node.acceptanceCriteria ?? [];
|
|
5442
|
+
if (inline.length > 0) return inline;
|
|
5443
|
+
return store2.getChildNodes(nodeId).filter((n) => n.type === "acceptance_criteria").map((n) => n.title);
|
|
5444
|
+
}
|
|
5411
5445
|
function nodeHasAc(doc, nodeId) {
|
|
5412
5446
|
return getNodeAcTexts(doc, nodeId).length > 0;
|
|
5413
5447
|
}
|
|
@@ -7044,8 +7078,8 @@ var init_implementation_executor = __esm({
|
|
|
7044
7078
|
};
|
|
7045
7079
|
defaultRunner = (command, cwd) => {
|
|
7046
7080
|
try {
|
|
7047
|
-
const
|
|
7048
|
-
return { exitCode: 0, output:
|
|
7081
|
+
const output16 = execSync(command, { cwd, encoding: "utf8", stdio: "pipe" });
|
|
7082
|
+
return { exitCode: 0, output: output16 };
|
|
7049
7083
|
} catch (err) {
|
|
7050
7084
|
const e = err;
|
|
7051
7085
|
return {
|
|
@@ -7128,8 +7162,10 @@ var init_plan_parser = __esm({
|
|
|
7128
7162
|
// src/core/autonomy/implement-attempt.ts
|
|
7129
7163
|
function buildInitialPrompt(node, opts = {}) {
|
|
7130
7164
|
const repoMapBlock = opts.repoMap && opts.repoMap.length > 0 ? [`Contexto do reposit\xF3rio (refer\xEAncia, n\xE3o reescreva o que j\xE1 existe):`, opts.repoMap, ""] : [];
|
|
7165
|
+
const flowBlock = opts.flowContext && opts.flowContext.length > 0 ? [opts.flowContext, ""] : [];
|
|
7131
7166
|
return [
|
|
7132
7167
|
...repoMapBlock,
|
|
7168
|
+
...flowBlock,
|
|
7133
7169
|
`Implemente a task "${node.title}" (id: ${node.id}) seguindo TDD.`,
|
|
7134
7170
|
"Responda APENAS com um bloco ```json. H\xE1 DOIS mecanismos:",
|
|
7135
7171
|
'- "edits" (PREFIRA \u2014 economia de token): [{ "path", "oldString", "newString", "replaceAll"? }].',
|
|
@@ -7158,7 +7194,7 @@ async function attemptImplementation(deps, options) {
|
|
|
7158
7194
|
let lastResult;
|
|
7159
7195
|
let lastError;
|
|
7160
7196
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
7161
|
-
const prompt = attempt === 1 || !lastResult ? buildInitialPrompt(options.node, { repoMap: options.repoMap }) : buildRetryPrompt(options.node, lastResult, maxFeedbackChars);
|
|
7197
|
+
const prompt = attempt === 1 || !lastResult ? buildInitialPrompt(options.node, { repoMap: options.repoMap, flowContext: options.flowContext }) : buildRetryPrompt(options.node, lastResult, maxFeedbackChars);
|
|
7162
7198
|
let plan;
|
|
7163
7199
|
try {
|
|
7164
7200
|
const text = await deps.generate(prompt);
|
|
@@ -7573,6 +7609,854 @@ var init_repo_map = __esm({
|
|
|
7573
7609
|
FOCUS_BOOST = 3;
|
|
7574
7610
|
}
|
|
7575
7611
|
});
|
|
7612
|
+
var LspConfigOverrideSchema, LspDiagnosticSchema, LspDocumentSymbolSchema, LspTextEditSchema, LspWorkspaceEditSchema;
|
|
7613
|
+
var init_lsp_types = __esm({
|
|
7614
|
+
"src/core/lsp/lsp-types.ts"() {
|
|
7615
|
+
init_esm_shims();
|
|
7616
|
+
z.object({
|
|
7617
|
+
languageId: z.string(),
|
|
7618
|
+
extensions: z.array(z.string()),
|
|
7619
|
+
command: z.string(),
|
|
7620
|
+
args: z.array(z.string()),
|
|
7621
|
+
configFiles: z.array(z.string()),
|
|
7622
|
+
probeCommand: z.string().optional(),
|
|
7623
|
+
initializationOptions: z.record(z.string(), z.unknown()).optional(),
|
|
7624
|
+
settings: z.record(z.string(), z.unknown()).optional()
|
|
7625
|
+
});
|
|
7626
|
+
LspConfigOverrideSchema = z.object({
|
|
7627
|
+
languageId: z.string(),
|
|
7628
|
+
command: z.string(),
|
|
7629
|
+
args: z.array(z.string()).default([]),
|
|
7630
|
+
extensions: z.array(z.string()).optional(),
|
|
7631
|
+
initializationOptions: z.record(z.string(), z.unknown()).optional(),
|
|
7632
|
+
settings: z.record(z.string(), z.unknown()).optional()
|
|
7633
|
+
});
|
|
7634
|
+
z.object({
|
|
7635
|
+
file: z.string(),
|
|
7636
|
+
startLine: z.int().min(0),
|
|
7637
|
+
startCharacter: z.int().min(0),
|
|
7638
|
+
endLine: z.int().min(0),
|
|
7639
|
+
endCharacter: z.int().min(0)
|
|
7640
|
+
});
|
|
7641
|
+
z.object({
|
|
7642
|
+
signature: z.string(),
|
|
7643
|
+
documentation: z.string().optional(),
|
|
7644
|
+
language: z.string().optional()
|
|
7645
|
+
});
|
|
7646
|
+
LspDiagnosticSchema = z.object({
|
|
7647
|
+
file: z.string(),
|
|
7648
|
+
startLine: z.int().min(0),
|
|
7649
|
+
startCharacter: z.int().min(0),
|
|
7650
|
+
endLine: z.int().min(0),
|
|
7651
|
+
endCharacter: z.int().min(0),
|
|
7652
|
+
severity: z.number().int().min(1).max(4),
|
|
7653
|
+
message: z.string(),
|
|
7654
|
+
code: z.string().optional(),
|
|
7655
|
+
source: z.string().optional()
|
|
7656
|
+
});
|
|
7657
|
+
z.object({
|
|
7658
|
+
name: z.string(),
|
|
7659
|
+
kind: z.string(),
|
|
7660
|
+
file: z.string(),
|
|
7661
|
+
startLine: z.int().min(0),
|
|
7662
|
+
endLine: z.int().min(0)
|
|
7663
|
+
});
|
|
7664
|
+
LspDocumentSymbolSchema = z.object({
|
|
7665
|
+
name: z.string(),
|
|
7666
|
+
kind: z.string(),
|
|
7667
|
+
file: z.string(),
|
|
7668
|
+
startLine: z.int().min(0),
|
|
7669
|
+
endLine: z.int().min(0),
|
|
7670
|
+
children: z.lazy(() => z.array(LspDocumentSymbolSchema)).optional()
|
|
7671
|
+
});
|
|
7672
|
+
LspTextEditSchema = z.object({
|
|
7673
|
+
file: z.string(),
|
|
7674
|
+
startLine: z.int().min(0),
|
|
7675
|
+
startCharacter: z.int().min(0),
|
|
7676
|
+
endLine: z.int().min(0),
|
|
7677
|
+
endCharacter: z.int().min(0),
|
|
7678
|
+
newText: z.string()
|
|
7679
|
+
});
|
|
7680
|
+
LspWorkspaceEditSchema = z.object({
|
|
7681
|
+
changes: z.array(LspTextEditSchema)
|
|
7682
|
+
});
|
|
7683
|
+
z.object({
|
|
7684
|
+
languageId: z.string(),
|
|
7685
|
+
status: z.enum(["stopped", "starting", "ready", "error"]),
|
|
7686
|
+
pid: z.number().int().optional(),
|
|
7687
|
+
error: z.string().optional()
|
|
7688
|
+
});
|
|
7689
|
+
z.object({
|
|
7690
|
+
languageId: z.string(),
|
|
7691
|
+
confidence: z.number().min(0).max(1),
|
|
7692
|
+
detectedVia: z.enum(["file_extension", "config_file", "shebang"]),
|
|
7693
|
+
fileCount: z.int().min(0),
|
|
7694
|
+
configFile: z.string().optional()
|
|
7695
|
+
});
|
|
7696
|
+
z.object({
|
|
7697
|
+
title: z.string(),
|
|
7698
|
+
kind: z.string().optional(),
|
|
7699
|
+
isPreferred: z.boolean().optional(),
|
|
7700
|
+
edit: LspWorkspaceEditSchema.optional(),
|
|
7701
|
+
diagnostics: z.array(LspDiagnosticSchema).optional()
|
|
7702
|
+
});
|
|
7703
|
+
z.object({
|
|
7704
|
+
applied: z.boolean(),
|
|
7705
|
+
filesModified: z.array(z.string()),
|
|
7706
|
+
totalEdits: z.number().int(),
|
|
7707
|
+
errors: z.array(z.string()),
|
|
7708
|
+
backups: z.map(z.string(), z.string()).optional()
|
|
7709
|
+
});
|
|
7710
|
+
}
|
|
7711
|
+
});
|
|
7712
|
+
var BROWSER_PILOT_MODELS, ContextModeSchema, ProfileFilterConfigSchema, BrowserAutomationConfigSchema, FlowConfigSchema, ConfigSchema;
|
|
7713
|
+
var init_config_schema = __esm({
|
|
7714
|
+
"src/core/config/config-schema.ts"() {
|
|
7715
|
+
init_esm_shims();
|
|
7716
|
+
init_lsp_types();
|
|
7717
|
+
BROWSER_PILOT_MODELS = ["claude-3.5-sonnet", "gpt-4o", "gpt-4o-mini", "o1", "o1-mini"];
|
|
7718
|
+
ContextModeSchema = z.enum(["ultra-lean", "lean", "full"]);
|
|
7719
|
+
ProfileFilterConfigSchema = z.enum(["core", "pro", "expert", "all"]);
|
|
7720
|
+
BrowserAutomationConfigSchema = z.object({
|
|
7721
|
+
enabled: z.boolean().default(false),
|
|
7722
|
+
bridgeUrl: z.string().regex(/^https?:\/\//, "bridgeUrl must start with http:// or https://").default("http://127.0.0.1:9876/v1"),
|
|
7723
|
+
defaultModel: z.enum(BROWSER_PILOT_MODELS).default("claude-3.5-sonnet"),
|
|
7724
|
+
defaultCdpUrl: z.string().min(1).optional(),
|
|
7725
|
+
allowedDomains: z.array(z.string().min(1)).default([]),
|
|
7726
|
+
forbiddenCdpMethods: z.array(z.string().min(1)).default(["Browser.close"]),
|
|
7727
|
+
maxStepsDefault: z.number().int().min(1).max(100).default(25),
|
|
7728
|
+
tokenBudgetPerDay: z.number().int().nonnegative().optional()
|
|
7729
|
+
}).default({
|
|
7730
|
+
enabled: false,
|
|
7731
|
+
bridgeUrl: "http://127.0.0.1:9876/v1",
|
|
7732
|
+
defaultModel: "claude-3.5-sonnet",
|
|
7733
|
+
allowedDomains: [],
|
|
7734
|
+
forbiddenCdpMethods: ["Browser.close"],
|
|
7735
|
+
maxStepsDefault: 25
|
|
7736
|
+
});
|
|
7737
|
+
FlowConfigSchema = z.object({
|
|
7738
|
+
/** Master switch. OFF = byte-identical legacy context behaviour. */
|
|
7739
|
+
enabled: z.boolean().default(false),
|
|
7740
|
+
/** λ_base — minimum architectural forgetting rate. */
|
|
7741
|
+
lambdaBase: z.number().min(0).default(0.15),
|
|
7742
|
+
/** α — hypofrontality accelerator (weight of Φ on λ_flow). */
|
|
7743
|
+
alpha: z.number().min(0).default(1.5),
|
|
7744
|
+
/** BFS depth used to pull distant pinned invariants back into scope. */
|
|
7745
|
+
maxDepth: z.number().int().min(0).max(6).default(3),
|
|
7746
|
+
/** Peripheral neighbours below this decayed weight are pruned (unless pinned). */
|
|
7747
|
+
weightThreshold: z.number().min(0).max(1).default(0.1),
|
|
7748
|
+
/** EMA gain per consecutive success when computing Φ. */
|
|
7749
|
+
emaGain: z.number().min(0).max(1).default(0.34),
|
|
7750
|
+
/** Multiplier applied to Φ on a failure (0 = hard reset → re-hydrate memory). */
|
|
7751
|
+
resetFactor: z.number().min(0).max(1).default(0),
|
|
7752
|
+
/** Damping fraction of `emaGain` applied on a `partial` outcome. */
|
|
7753
|
+
partialFactor: z.number().min(0).max(1).default(0.5),
|
|
7754
|
+
/** rag budget is never scaled below this fraction of baseline (long-range safety). */
|
|
7755
|
+
budgetFloorRatio: z.number().min(0).max(1).default(0.25),
|
|
7756
|
+
/** How many recent task outcomes feed Φ. */
|
|
7757
|
+
historyWindow: z.number().int().min(1).max(200).default(12),
|
|
7758
|
+
/** Node types that are never diluted. */
|
|
7759
|
+
pinnedTypes: z.array(z.string()).default(["constraint", "risk", "decision", "acceptance_criteria", "constitution", "requirement"]),
|
|
7760
|
+
/** A/B experiment: alternate flow_on/flow_off deterministically per node to measure impact. */
|
|
7761
|
+
experiment: z.object({ abEnabled: z.boolean().default(false) }).default({ abEnabled: false })
|
|
7762
|
+
});
|
|
7763
|
+
ConfigSchema = z.object({
|
|
7764
|
+
port: z.number().int().min(1).max(65535).default(3e3),
|
|
7765
|
+
dbPath: z.string().default("workflow-graph"),
|
|
7766
|
+
basePath: z.string().optional(),
|
|
7767
|
+
contextMode: ContextModeSchema.default("lean"),
|
|
7768
|
+
profile: ProfileFilterConfigSchema.default("all"),
|
|
7769
|
+
dashboard: z.object({
|
|
7770
|
+
autoOpen: z.boolean().default(true)
|
|
7771
|
+
}).default({ autoOpen: true }),
|
|
7772
|
+
integrations: z.object({
|
|
7773
|
+
codeGraphAutoIndex: z.boolean().default(true),
|
|
7774
|
+
codeGraphReindexIntervalSec: z.number().int().min(0).default(0),
|
|
7775
|
+
lspServers: z.array(LspConfigOverrideSchema).default([]),
|
|
7776
|
+
browserAutomation: BrowserAutomationConfigSchema
|
|
7777
|
+
}).prefault({}),
|
|
7778
|
+
flow: FlowConfigSchema.prefault({})
|
|
7779
|
+
});
|
|
7780
|
+
}
|
|
7781
|
+
});
|
|
7782
|
+
|
|
7783
|
+
// src/core/context/flow-config.ts
|
|
7784
|
+
function resolveFlowConfig(source) {
|
|
7785
|
+
const raw = source.getProjectSetting(FLOW_CONFIG_SETTING_KEY);
|
|
7786
|
+
if (!raw) return FlowConfigSchema.parse({});
|
|
7787
|
+
try {
|
|
7788
|
+
return FlowConfigSchema.parse(JSON.parse(raw));
|
|
7789
|
+
} catch {
|
|
7790
|
+
return FlowConfigSchema.parse({});
|
|
7791
|
+
}
|
|
7792
|
+
}
|
|
7793
|
+
function flowAbArm(nodeId) {
|
|
7794
|
+
let sum = 0;
|
|
7795
|
+
for (let i = 0; i < nodeId.length; i += 1) sum += nodeId.charCodeAt(i);
|
|
7796
|
+
return sum % 2 === 0 ? "flow_on" : "flow_off";
|
|
7797
|
+
}
|
|
7798
|
+
var FLOW_CONFIG_SETTING_KEY;
|
|
7799
|
+
var init_flow_config = __esm({
|
|
7800
|
+
"src/core/context/flow-config.ts"() {
|
|
7801
|
+
init_esm_shims();
|
|
7802
|
+
init_config_schema();
|
|
7803
|
+
FLOW_CONFIG_SETTING_KEY = "flow_config";
|
|
7804
|
+
}
|
|
7805
|
+
});
|
|
7806
|
+
|
|
7807
|
+
// src/core/context/flow-index.ts
|
|
7808
|
+
function computeFlowIndex(outcomesNewestFirst, tuning = {}) {
|
|
7809
|
+
const { emaGain, resetFactor, partialFactor } = { ...DEFAULT_FLOW_TUNING, ...tuning };
|
|
7810
|
+
let streak = 0;
|
|
7811
|
+
for (const outcome of outcomesNewestFirst) {
|
|
7812
|
+
if (outcome === "success") streak += 1;
|
|
7813
|
+
else break;
|
|
7814
|
+
}
|
|
7815
|
+
let phi = 0;
|
|
7816
|
+
for (let i = outcomesNewestFirst.length - 1; i >= 0; i -= 1) {
|
|
7817
|
+
const outcome = outcomesNewestFirst[i];
|
|
7818
|
+
if (outcome === "success") {
|
|
7819
|
+
phi += emaGain * (1 - phi);
|
|
7820
|
+
} else if (outcome === "failure") {
|
|
7821
|
+
phi *= resetFactor;
|
|
7822
|
+
} else {
|
|
7823
|
+
phi *= 1 - emaGain * partialFactor;
|
|
7824
|
+
}
|
|
7825
|
+
}
|
|
7826
|
+
phi = Math.min(1, Math.max(0, phi));
|
|
7827
|
+
return { phi, streak, sampleCount: outcomesNewestFirst.length };
|
|
7828
|
+
}
|
|
7829
|
+
function computeLambdaFlow(phi, lambdaBase, alpha) {
|
|
7830
|
+
return lambdaBase + alpha * phi;
|
|
7831
|
+
}
|
|
7832
|
+
function decayWeight(lambda, distance) {
|
|
7833
|
+
return Math.exp(-lambda * distance);
|
|
7834
|
+
}
|
|
7835
|
+
var DEFAULT_FLOW_TUNING;
|
|
7836
|
+
var init_flow_index = __esm({
|
|
7837
|
+
"src/core/context/flow-index.ts"() {
|
|
7838
|
+
init_esm_shims();
|
|
7839
|
+
DEFAULT_FLOW_TUNING = {
|
|
7840
|
+
emaGain: 0.34,
|
|
7841
|
+
resetFactor: 0,
|
|
7842
|
+
partialFactor: 0.5
|
|
7843
|
+
};
|
|
7844
|
+
}
|
|
7845
|
+
});
|
|
7846
|
+
|
|
7847
|
+
// src/core/context/token-estimator.ts
|
|
7848
|
+
function isAsciiLetter(code) {
|
|
7849
|
+
return code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
7850
|
+
}
|
|
7851
|
+
function isAsciiDigit(code) {
|
|
7852
|
+
return code >= 48 && code <= 57;
|
|
7853
|
+
}
|
|
7854
|
+
function isWhitespace(code) {
|
|
7855
|
+
return code === 32 || code === 9 || code === 10 || code === 13 || code === 12 || code === 11;
|
|
7856
|
+
}
|
|
7857
|
+
function estimateTokens2(text) {
|
|
7858
|
+
if (!text) return 0;
|
|
7859
|
+
let tokens = 0;
|
|
7860
|
+
const len = text.length;
|
|
7861
|
+
let i = 0;
|
|
7862
|
+
while (i < len) {
|
|
7863
|
+
const code = text.charCodeAt(i);
|
|
7864
|
+
if (isWhitespace(code)) {
|
|
7865
|
+
i++;
|
|
7866
|
+
continue;
|
|
7867
|
+
}
|
|
7868
|
+
if (isAsciiLetter(code)) {
|
|
7869
|
+
const start = i;
|
|
7870
|
+
i++;
|
|
7871
|
+
let subWords = 1;
|
|
7872
|
+
while (i < len && isAsciiLetter(text.charCodeAt(i))) {
|
|
7873
|
+
if (i > start && text.charCodeAt(i) >= 65 && text.charCodeAt(i) <= 90 && text.charCodeAt(i - 1) >= 97 && text.charCodeAt(i - 1) <= 122) {
|
|
7874
|
+
subWords++;
|
|
7875
|
+
}
|
|
7876
|
+
i++;
|
|
7877
|
+
}
|
|
7878
|
+
const wordLen = i - start;
|
|
7879
|
+
if (subWords > 1) {
|
|
7880
|
+
tokens += subWords;
|
|
7881
|
+
} else {
|
|
7882
|
+
tokens += wordLen <= 6 ? 1 : wordLen > 20 ? Math.ceil(wordLen / 4) : Math.ceil(wordLen / 5);
|
|
7883
|
+
}
|
|
7884
|
+
continue;
|
|
7885
|
+
}
|
|
7886
|
+
if (isAsciiDigit(code)) {
|
|
7887
|
+
const start = i;
|
|
7888
|
+
i++;
|
|
7889
|
+
while (i < len && isAsciiDigit(text.charCodeAt(i))) i++;
|
|
7890
|
+
const digitsLen = i - start;
|
|
7891
|
+
tokens += Math.ceil(digitsLen / 3);
|
|
7892
|
+
continue;
|
|
7893
|
+
}
|
|
7894
|
+
tokens += 1;
|
|
7895
|
+
i++;
|
|
7896
|
+
}
|
|
7897
|
+
return tokens;
|
|
7898
|
+
}
|
|
7899
|
+
var init_token_estimator = __esm({
|
|
7900
|
+
"src/core/context/token-estimator.ts"() {
|
|
7901
|
+
init_esm_shims();
|
|
7902
|
+
}
|
|
7903
|
+
});
|
|
7904
|
+
|
|
7905
|
+
// src/core/context/compact-context.ts
|
|
7906
|
+
function toTaskSummary(node) {
|
|
7907
|
+
const summary = {
|
|
7908
|
+
id: node.id,
|
|
7909
|
+
type: node.type,
|
|
7910
|
+
title: node.title,
|
|
7911
|
+
status: node.status,
|
|
7912
|
+
priority: node.priority
|
|
7913
|
+
};
|
|
7914
|
+
if (node.description) summary.description = node.description;
|
|
7915
|
+
if (node.sprint) summary.sprint = node.sprint;
|
|
7916
|
+
if (node.xpSize) summary.xpSize = node.xpSize;
|
|
7917
|
+
if (node.tags?.length) summary.tags = node.tags;
|
|
7918
|
+
return summary;
|
|
7919
|
+
}
|
|
7920
|
+
function isInferred(edge) {
|
|
7921
|
+
return edge.metadata?.inferred === true;
|
|
7922
|
+
}
|
|
7923
|
+
function buildTaskContext(store2, nodeId, snapshot) {
|
|
7924
|
+
const resolveNode = (id) => {
|
|
7925
|
+
return store2.getNodeById(id);
|
|
7926
|
+
};
|
|
7927
|
+
const node = resolveNode(nodeId);
|
|
7928
|
+
if (!node) {
|
|
7929
|
+
log26.warn(`buildTaskContext: node ${nodeId} not found`);
|
|
7930
|
+
return null;
|
|
7931
|
+
}
|
|
7932
|
+
let parent = null;
|
|
7933
|
+
if (node.parentId) {
|
|
7934
|
+
const parentNode = resolveNode(node.parentId);
|
|
7935
|
+
if (parentNode) parent = toTaskSummary(parentNode);
|
|
7936
|
+
}
|
|
7937
|
+
let childNodes;
|
|
7938
|
+
{
|
|
7939
|
+
childNodes = store2.getChildNodes(nodeId);
|
|
7940
|
+
}
|
|
7941
|
+
const children = childNodes.map(toTaskSummary);
|
|
7942
|
+
let incomingEdges;
|
|
7943
|
+
let outgoingEdges;
|
|
7944
|
+
{
|
|
7945
|
+
incomingEdges = store2.getEdgesTo(nodeId);
|
|
7946
|
+
outgoingEdges = store2.getEdgesFrom(nodeId);
|
|
7947
|
+
}
|
|
7948
|
+
const blockers = [];
|
|
7949
|
+
const dependsOn = [];
|
|
7950
|
+
const relatedIds = /* @__PURE__ */ new Set();
|
|
7951
|
+
const relatedNodes = [];
|
|
7952
|
+
const implementsNodes = [];
|
|
7953
|
+
const derivedFromNodes = [];
|
|
7954
|
+
let edgeParent = null;
|
|
7955
|
+
const edgeChildren = [];
|
|
7956
|
+
const edgeChildrenIds = /* @__PURE__ */ new Set();
|
|
7957
|
+
for (const edge of incomingEdges) {
|
|
7958
|
+
if (edge.relationType === "blocks") {
|
|
7959
|
+
const blockerNode = resolveNode(edge.from);
|
|
7960
|
+
if (blockerNode) {
|
|
7961
|
+
blockers.push({
|
|
7962
|
+
id: blockerNode.id,
|
|
7963
|
+
title: blockerNode.title,
|
|
7964
|
+
status: blockerNode.status,
|
|
7965
|
+
relationType: edge.relationType,
|
|
7966
|
+
inferred: isInferred(edge)
|
|
7967
|
+
});
|
|
7968
|
+
}
|
|
7969
|
+
} else if (edge.relationType === "related_to") {
|
|
7970
|
+
const relNode = resolveNode(edge.from);
|
|
7971
|
+
if (relNode && !relatedIds.has(relNode.id)) {
|
|
7972
|
+
relatedIds.add(relNode.id);
|
|
7973
|
+
relatedNodes.push(toTaskSummary(relNode));
|
|
7974
|
+
}
|
|
7975
|
+
} else if (edge.relationType === "parent_of" && !edgeParent) {
|
|
7976
|
+
const parentNode = resolveNode(edge.from);
|
|
7977
|
+
if (parentNode) edgeParent = toTaskSummary(parentNode);
|
|
7978
|
+
}
|
|
7979
|
+
}
|
|
7980
|
+
for (const edge of outgoingEdges) {
|
|
7981
|
+
if (edge.relationType === "depends_on") {
|
|
7982
|
+
const depNode = resolveNode(edge.to);
|
|
7983
|
+
if (depNode) {
|
|
7984
|
+
dependsOn.push({
|
|
7985
|
+
id: depNode.id,
|
|
7986
|
+
title: depNode.title,
|
|
7987
|
+
status: depNode.status,
|
|
7988
|
+
resolved: depNode.status === "done",
|
|
7989
|
+
inferred: isInferred(edge)
|
|
7990
|
+
});
|
|
7991
|
+
}
|
|
7992
|
+
} else if (edge.relationType === "related_to") {
|
|
7993
|
+
const relNode = resolveNode(edge.to);
|
|
7994
|
+
if (relNode && !relatedIds.has(relNode.id)) {
|
|
7995
|
+
relatedIds.add(relNode.id);
|
|
7996
|
+
relatedNodes.push(toTaskSummary(relNode));
|
|
7997
|
+
}
|
|
7998
|
+
} else if (edge.relationType === "implements") {
|
|
7999
|
+
const implNode = resolveNode(edge.to);
|
|
8000
|
+
if (implNode) implementsNodes.push(toTaskSummary(implNode));
|
|
8001
|
+
} else if (edge.relationType === "derived_from") {
|
|
8002
|
+
const derivedNode = resolveNode(edge.to);
|
|
8003
|
+
if (derivedNode) derivedFromNodes.push(toTaskSummary(derivedNode));
|
|
8004
|
+
} else if (edge.relationType === "parent_of") {
|
|
8005
|
+
const childNode = resolveNode(edge.to);
|
|
8006
|
+
if (childNode && !edgeChildrenIds.has(childNode.id)) {
|
|
8007
|
+
edgeChildrenIds.add(childNode.id);
|
|
8008
|
+
edgeChildren.push(toTaskSummary(childNode));
|
|
8009
|
+
}
|
|
8010
|
+
}
|
|
8011
|
+
}
|
|
8012
|
+
const acceptanceCriteria = getNodeAcFromStore(store2, node.id);
|
|
8013
|
+
const sourceRef = node.sourceRef ? { ...node.sourceRef } : null;
|
|
8014
|
+
const localNodes = [node, ...childNodes];
|
|
8015
|
+
const originalChars = localNodes.reduce(
|
|
8016
|
+
(sum, n) => sum + n.title.length + (n.description?.length ?? 0) + (n.acceptanceCriteria?.join("").length ?? 0),
|
|
8017
|
+
0
|
|
8018
|
+
) + [...incomingEdges, ...outgoingEdges].reduce((sum, e) => sum + (e.reason?.length ?? 0), 0);
|
|
8019
|
+
const summary = toTaskSummary(node);
|
|
8020
|
+
const corePayload = {
|
|
8021
|
+
task: summary,
|
|
8022
|
+
parent,
|
|
8023
|
+
children,
|
|
8024
|
+
blockers,
|
|
8025
|
+
dependsOn,
|
|
8026
|
+
relatedNodes: relatedNodes.length > 0 ? relatedNodes : void 0,
|
|
8027
|
+
implementsNodes: implementsNodes.length > 0 ? implementsNodes : void 0,
|
|
8028
|
+
derivedFromNodes: derivedFromNodes.length > 0 ? derivedFromNodes : void 0,
|
|
8029
|
+
edgeParent: edgeParent ?? void 0,
|
|
8030
|
+
edgeChildren: edgeChildren.length > 0 ? edgeChildren : void 0,
|
|
8031
|
+
acceptanceCriteria,
|
|
8032
|
+
sourceRef,
|
|
8033
|
+
metrics: { originalChars: 0, compactChars: 0, reductionPercent: 0, estimatedTokens: 0 }
|
|
8034
|
+
};
|
|
8035
|
+
const compactJson = JSON.stringify(corePayload);
|
|
8036
|
+
const compactChars = compactJson.length;
|
|
8037
|
+
const reductionPercent = originalChars > 0 ? Math.round((originalChars - compactChars) / originalChars * 100) : 0;
|
|
8038
|
+
const metrics = {
|
|
8039
|
+
originalChars,
|
|
8040
|
+
compactChars,
|
|
8041
|
+
reductionPercent,
|
|
8042
|
+
estimatedTokens: estimateTokens2(compactJson)
|
|
8043
|
+
};
|
|
8044
|
+
const contextPayload = {
|
|
8045
|
+
...corePayload,
|
|
8046
|
+
node: summary,
|
|
8047
|
+
metrics
|
|
8048
|
+
};
|
|
8049
|
+
log26.info(`Context for ${nodeId}: ${metrics.estimatedTokens} tokens, ${metrics.reductionPercent}% reduction`);
|
|
8050
|
+
return contextPayload;
|
|
8051
|
+
}
|
|
8052
|
+
var log26, KEY_MAP, KEY_LEGEND;
|
|
8053
|
+
var init_compact_context = __esm({
|
|
8054
|
+
"src/core/context/compact-context.ts"() {
|
|
8055
|
+
init_esm_shims();
|
|
8056
|
+
init_ac_helpers();
|
|
8057
|
+
init_token_estimator();
|
|
8058
|
+
init_logger();
|
|
8059
|
+
log26 = createLogger({ layer: "core", source: "compact-context.ts" });
|
|
8060
|
+
KEY_MAP = {
|
|
8061
|
+
// TaskContext top-level
|
|
8062
|
+
task: "tk",
|
|
8063
|
+
node: "n",
|
|
8064
|
+
parent: "par",
|
|
8065
|
+
children: "ch",
|
|
8066
|
+
blockers: "bl",
|
|
8067
|
+
dependsOn: "dep",
|
|
8068
|
+
acceptanceCriteria: "ac",
|
|
8069
|
+
sourceRef: "sr",
|
|
8070
|
+
relatedNodes: "rel",
|
|
8071
|
+
implementsNodes: "impl",
|
|
8072
|
+
derivedFromNodes: "drv",
|
|
8073
|
+
edgeParent: "ep",
|
|
8074
|
+
edgeChildren: "ech",
|
|
8075
|
+
metrics: "m",
|
|
8076
|
+
// TaskSummary / shared fields
|
|
8077
|
+
id: "i",
|
|
8078
|
+
type: "t",
|
|
8079
|
+
title: "n",
|
|
8080
|
+
status: "s",
|
|
8081
|
+
priority: "p",
|
|
8082
|
+
description: "d",
|
|
8083
|
+
sprint: "sp",
|
|
8084
|
+
xpSize: "xs",
|
|
8085
|
+
tags: "tg",
|
|
8086
|
+
// BlockerInfo / DependencyInfo
|
|
8087
|
+
relationType: "rt",
|
|
8088
|
+
inferred: "inf",
|
|
8089
|
+
resolved: "res",
|
|
8090
|
+
// SourceRefInfo
|
|
8091
|
+
file: "f",
|
|
8092
|
+
startLine: "sl",
|
|
8093
|
+
endLine: "el",
|
|
8094
|
+
confidence: "cf",
|
|
8095
|
+
// ContextMetrics
|
|
8096
|
+
originalChars: "oc",
|
|
8097
|
+
compactChars: "cc",
|
|
8098
|
+
reductionPercent: "rp",
|
|
8099
|
+
estimatedTokens: "et"
|
|
8100
|
+
};
|
|
8101
|
+
KEY_LEGEND = {};
|
|
8102
|
+
for (const [full, short] of Object.entries(KEY_MAP)) {
|
|
8103
|
+
KEY_LEGEND[short] = full;
|
|
8104
|
+
}
|
|
8105
|
+
}
|
|
8106
|
+
});
|
|
8107
|
+
|
|
8108
|
+
// src/core/context/topological-decay.ts
|
|
8109
|
+
function corePayloadTokens(ctx, pinned) {
|
|
8110
|
+
const { metrics: _m, node: _n, ...core } = ctx;
|
|
8111
|
+
return estimateTokens2(JSON.stringify(pinned.length > 0 ? { ...core, pinnedInvariants: pinned } : core));
|
|
8112
|
+
}
|
|
8113
|
+
function isPinnedType(type, pinnedTypes) {
|
|
8114
|
+
return pinnedTypes.has(type);
|
|
8115
|
+
}
|
|
8116
|
+
function collectDistantInvariants(store2, rootId, alreadyPresent, maxDepth, pinnedTypes) {
|
|
8117
|
+
if (maxDepth <= 0) return [];
|
|
8118
|
+
const visited = /* @__PURE__ */ new Set([rootId]);
|
|
8119
|
+
const found = /* @__PURE__ */ new Map();
|
|
8120
|
+
let frontier = [rootId];
|
|
8121
|
+
for (let depth = 1; depth <= maxDepth && frontier.length > 0; depth += 1) {
|
|
8122
|
+
const next = [];
|
|
8123
|
+
for (const id of frontier) {
|
|
8124
|
+
const edges = [...store2.getEdgesFrom(id), ...store2.getEdgesTo(id)];
|
|
8125
|
+
for (const edge of edges) {
|
|
8126
|
+
const neighborId = edge.from === id ? edge.to : edge.from;
|
|
8127
|
+
if (visited.has(neighborId)) continue;
|
|
8128
|
+
visited.add(neighborId);
|
|
8129
|
+
next.push(neighborId);
|
|
8130
|
+
if (alreadyPresent.has(neighborId) || found.has(neighborId)) continue;
|
|
8131
|
+
const neighbor = store2.getNodeById(neighborId);
|
|
8132
|
+
if (neighbor && isPinnedType(neighbor.type, pinnedTypes)) {
|
|
8133
|
+
found.set(neighborId, {
|
|
8134
|
+
id: neighbor.id,
|
|
8135
|
+
type: neighbor.type,
|
|
8136
|
+
title: neighbor.title,
|
|
8137
|
+
status: neighbor.status,
|
|
8138
|
+
distance: depth
|
|
8139
|
+
});
|
|
8140
|
+
}
|
|
8141
|
+
}
|
|
8142
|
+
}
|
|
8143
|
+
frontier = next;
|
|
8144
|
+
}
|
|
8145
|
+
return [...found.values()];
|
|
8146
|
+
}
|
|
8147
|
+
function buildDecayedTaskContext(store2, nodeId, opts) {
|
|
8148
|
+
const base = buildTaskContext(store2, nodeId);
|
|
8149
|
+
if (!base) return null;
|
|
8150
|
+
const pinnedTypes = opts.pinnedTypes ?? new Set(DEFAULT_PINNED_TYPES);
|
|
8151
|
+
const tokensBaseline = corePayloadTokens(base, []);
|
|
8152
|
+
const peripheralWeight = decayWeight(opts.lambda, PERIPHERAL_DISTANCE);
|
|
8153
|
+
const peripheralSurvives = peripheralWeight >= opts.weightThreshold;
|
|
8154
|
+
const presentIds = /* @__PURE__ */ new Set([base.task.id]);
|
|
8155
|
+
if (base.parent) presentIds.add(base.parent.id);
|
|
8156
|
+
for (const c of base.children) presentIds.add(c.id);
|
|
8157
|
+
for (const b of base.blockers) presentIds.add(b.id);
|
|
8158
|
+
for (const d of base.dependsOn) presentIds.add(d.id);
|
|
8159
|
+
const ctx = structuredClone(base);
|
|
8160
|
+
let prunedCount = 0;
|
|
8161
|
+
const prunePeripheral = (list) => {
|
|
8162
|
+
if (!list) return list;
|
|
8163
|
+
const kept = list.filter((item) => {
|
|
8164
|
+
presentIds.add(item.id);
|
|
8165
|
+
if (isPinnedType(item.type, pinnedTypes)) return true;
|
|
8166
|
+
if (peripheralSurvives) return true;
|
|
8167
|
+
prunedCount += 1;
|
|
8168
|
+
return false;
|
|
8169
|
+
});
|
|
8170
|
+
return kept.length > 0 ? kept : void 0;
|
|
8171
|
+
};
|
|
8172
|
+
ctx.relatedNodes = prunePeripheral(ctx.relatedNodes);
|
|
8173
|
+
ctx.implementsNodes = prunePeripheral(ctx.implementsNodes);
|
|
8174
|
+
ctx.derivedFromNodes = prunePeripheral(ctx.derivedFromNodes);
|
|
8175
|
+
ctx.edgeChildren = prunePeripheral(ctx.edgeChildren);
|
|
8176
|
+
if (ctx.edgeParent) {
|
|
8177
|
+
presentIds.add(ctx.edgeParent.id);
|
|
8178
|
+
if (!isPinnedType(ctx.edgeParent.type, pinnedTypes) && !peripheralSurvives) {
|
|
8179
|
+
ctx.edgeParent = null;
|
|
8180
|
+
prunedCount += 1;
|
|
8181
|
+
}
|
|
8182
|
+
}
|
|
8183
|
+
const pinnedInvariants = collectDistantInvariants(
|
|
8184
|
+
store2,
|
|
8185
|
+
nodeId,
|
|
8186
|
+
presentIds,
|
|
8187
|
+
opts.maxDepth,
|
|
8188
|
+
pinnedTypes
|
|
8189
|
+
);
|
|
8190
|
+
const tokensActual = corePayloadTokens(ctx, pinnedInvariants);
|
|
8191
|
+
ctx.metrics = {
|
|
8192
|
+
...ctx.metrics,
|
|
8193
|
+
estimatedTokens: tokensActual
|
|
8194
|
+
};
|
|
8195
|
+
ctx.node = ctx.task;
|
|
8196
|
+
const retainedCount = (ctx.children?.length ?? 0) + (ctx.blockers?.length ?? 0) + (ctx.dependsOn?.length ?? 0) + (ctx.relatedNodes?.length ?? 0) + (ctx.implementsNodes?.length ?? 0) + (ctx.derivedFromNodes?.length ?? 0) + (ctx.edgeChildren?.length ?? 0);
|
|
8197
|
+
log27.debug("flow:decay", {
|
|
8198
|
+
nodeId,
|
|
8199
|
+
lambda: opts.lambda,
|
|
8200
|
+
prunedCount,
|
|
8201
|
+
pinnedCount: pinnedInvariants.length,
|
|
8202
|
+
tokensBaseline,
|
|
8203
|
+
tokensActual
|
|
8204
|
+
});
|
|
8205
|
+
return {
|
|
8206
|
+
context: ctx,
|
|
8207
|
+
meta: {
|
|
8208
|
+
lambda: opts.lambda,
|
|
8209
|
+
prunedCount,
|
|
8210
|
+
retainedCount,
|
|
8211
|
+
pinnedCount: pinnedInvariants.length,
|
|
8212
|
+
tokensBaseline,
|
|
8213
|
+
tokensActual,
|
|
8214
|
+
tokensSaved: tokensBaseline - tokensActual,
|
|
8215
|
+
pinnedInvariants
|
|
8216
|
+
}
|
|
8217
|
+
};
|
|
8218
|
+
}
|
|
8219
|
+
var log27, DEFAULT_PINNED_TYPES, PERIPHERAL_DISTANCE;
|
|
8220
|
+
var init_topological_decay = __esm({
|
|
8221
|
+
"src/core/context/topological-decay.ts"() {
|
|
8222
|
+
init_esm_shims();
|
|
8223
|
+
init_compact_context();
|
|
8224
|
+
init_flow_index();
|
|
8225
|
+
init_token_estimator();
|
|
8226
|
+
init_logger();
|
|
8227
|
+
log27 = createLogger({ layer: "core", source: "topological-decay.ts" });
|
|
8228
|
+
DEFAULT_PINNED_TYPES = [
|
|
8229
|
+
"constraint",
|
|
8230
|
+
"risk",
|
|
8231
|
+
"decision",
|
|
8232
|
+
"acceptance_criteria",
|
|
8233
|
+
"constitution",
|
|
8234
|
+
"requirement"
|
|
8235
|
+
];
|
|
8236
|
+
PERIPHERAL_DISTANCE = 2;
|
|
8237
|
+
}
|
|
8238
|
+
});
|
|
8239
|
+
|
|
8240
|
+
// src/core/store/episodic-outcomes-store.ts
|
|
8241
|
+
function buildApproachSummary(touchedFiles, acIds) {
|
|
8242
|
+
const files = [...touchedFiles].sort().join("+");
|
|
8243
|
+
const acs = [...acIds].sort().join(",");
|
|
8244
|
+
return `${files}:${acs}`;
|
|
8245
|
+
}
|
|
8246
|
+
function insertEpisodicOutcome(db, outcome) {
|
|
8247
|
+
db.prepare(
|
|
8248
|
+
`INSERT OR IGNORE INTO episodic_outcomes
|
|
8249
|
+
(id, node_id, task_type, tags, approach_summary, outcome, cycle_time_delta, reopen_count, created_at)
|
|
8250
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
8251
|
+
).run(
|
|
8252
|
+
outcome.id,
|
|
8253
|
+
outcome.nodeId,
|
|
8254
|
+
outcome.taskType,
|
|
8255
|
+
outcome.tags,
|
|
8256
|
+
outcome.approachSummary,
|
|
8257
|
+
outcome.outcome,
|
|
8258
|
+
outcome.cycleTimeDelta,
|
|
8259
|
+
outcome.reopenCount,
|
|
8260
|
+
outcome.createdAt
|
|
8261
|
+
);
|
|
8262
|
+
}
|
|
8263
|
+
function queryEpisodicOutcomes(db, opts = {}) {
|
|
8264
|
+
const conditions = [];
|
|
8265
|
+
const params = [];
|
|
8266
|
+
if (opts.taskType) {
|
|
8267
|
+
conditions.push("task_type = ?");
|
|
8268
|
+
params.push(opts.taskType);
|
|
8269
|
+
}
|
|
8270
|
+
if (opts.maxAgeDays) {
|
|
8271
|
+
const cutoff = Date.now() - opts.maxAgeDays * 24 * 3600 * 1e3;
|
|
8272
|
+
conditions.push("created_at >= ?");
|
|
8273
|
+
params.push(cutoff);
|
|
8274
|
+
}
|
|
8275
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8276
|
+
const limit = Math.min(opts.limit ?? 100, 500);
|
|
8277
|
+
params.push(limit);
|
|
8278
|
+
const rows = db.prepare(
|
|
8279
|
+
`SELECT id, node_id, task_type, tags, approach_summary, outcome,
|
|
8280
|
+
cycle_time_delta, reopen_count, created_at
|
|
8281
|
+
FROM episodic_outcomes
|
|
8282
|
+
${where}
|
|
8283
|
+
ORDER BY created_at DESC
|
|
8284
|
+
LIMIT ?`
|
|
8285
|
+
).all(...params);
|
|
8286
|
+
return rows.map((r) => ({
|
|
8287
|
+
id: r.id,
|
|
8288
|
+
nodeId: r.node_id,
|
|
8289
|
+
taskType: r.task_type,
|
|
8290
|
+
tags: r.tags,
|
|
8291
|
+
approachSummary: r.approach_summary,
|
|
8292
|
+
outcome: r.outcome,
|
|
8293
|
+
cycleTimeDelta: r.cycle_time_delta,
|
|
8294
|
+
reopenCount: r.reopen_count,
|
|
8295
|
+
createdAt: r.created_at
|
|
8296
|
+
}));
|
|
8297
|
+
}
|
|
8298
|
+
var init_episodic_outcomes_store = __esm({
|
|
8299
|
+
"src/core/store/episodic-outcomes-store.ts"() {
|
|
8300
|
+
init_esm_shims();
|
|
8301
|
+
}
|
|
8302
|
+
});
|
|
8303
|
+
|
|
8304
|
+
// src/core/context/flow-metrics-store.ts
|
|
8305
|
+
function insertFlowMetric(db, metric) {
|
|
8306
|
+
db.prepare(
|
|
8307
|
+
`INSERT OR IGNORE INTO flow_metrics
|
|
8308
|
+
(id, project_id, node_id, mode, phi, lambda,
|
|
8309
|
+
tokens_baseline, tokens_actual, pruned_count, pinned_count, created_at)
|
|
8310
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
8311
|
+
).run(
|
|
8312
|
+
metric.id,
|
|
8313
|
+
metric.projectId,
|
|
8314
|
+
metric.nodeId,
|
|
8315
|
+
metric.mode,
|
|
8316
|
+
metric.phi,
|
|
8317
|
+
metric.lambda,
|
|
8318
|
+
metric.tokensBaseline,
|
|
8319
|
+
metric.tokensActual,
|
|
8320
|
+
metric.prunedCount,
|
|
8321
|
+
metric.pinnedCount,
|
|
8322
|
+
metric.createdAt
|
|
8323
|
+
);
|
|
8324
|
+
}
|
|
8325
|
+
var init_flow_metrics_store = __esm({
|
|
8326
|
+
"src/core/context/flow-metrics-store.ts"() {
|
|
8327
|
+
init_esm_shims();
|
|
8328
|
+
}
|
|
8329
|
+
});
|
|
8330
|
+
|
|
8331
|
+
// src/core/context/flow-compact.ts
|
|
8332
|
+
function formatFlowContext(result) {
|
|
8333
|
+
const { context: ctx, pinnedInvariants } = result;
|
|
8334
|
+
const lines = ["Contexto do grafo (dilu\xEDdo por flow \u2014 \u03A6 governando o esquecimento):"];
|
|
8335
|
+
lines.push(`- Task: ${ctx.task.title} (${ctx.task.id}) [${ctx.task.status}]`);
|
|
8336
|
+
if (ctx.task.description) lines.push(` ${ctx.task.description}`);
|
|
8337
|
+
if (ctx.acceptanceCriteria.length > 0) {
|
|
8338
|
+
lines.push("- Crit\xE9rios de aceita\xE7\xE3o:");
|
|
8339
|
+
for (const ac of ctx.acceptanceCriteria) lines.push(` \u2022 ${ac}`);
|
|
8340
|
+
}
|
|
8341
|
+
const openBlockers = ctx.blockers.filter((b) => b.status !== "done");
|
|
8342
|
+
if (openBlockers.length > 0) {
|
|
8343
|
+
lines.push(`- Bloqueadores: ${openBlockers.map((b) => `${b.title} (${b.status})`).join("; ")}`);
|
|
8344
|
+
}
|
|
8345
|
+
const openDeps = ctx.dependsOn.filter((d) => !d.resolved);
|
|
8346
|
+
if (openDeps.length > 0) {
|
|
8347
|
+
lines.push(`- Depende de: ${openDeps.map((d) => `${d.title} (${d.status})`).join("; ")}`);
|
|
8348
|
+
}
|
|
8349
|
+
if (pinnedInvariants.length > 0) {
|
|
8350
|
+
lines.push("- Invariantes pinados (nunca dilu\xEDdos):");
|
|
8351
|
+
for (const inv of pinnedInvariants) lines.push(` \u2022 [${inv.type}] ${inv.title}`);
|
|
8352
|
+
}
|
|
8353
|
+
return lines.join("\n");
|
|
8354
|
+
}
|
|
8355
|
+
function recordMetric(store2, row) {
|
|
8356
|
+
try {
|
|
8357
|
+
insertFlowMetric(store2.getDb(), {
|
|
8358
|
+
id: generateId("flowm"),
|
|
8359
|
+
createdAt: row.createdAt ?? Date.now(),
|
|
8360
|
+
...row
|
|
8361
|
+
});
|
|
8362
|
+
} catch (err) {
|
|
8363
|
+
log28.warn("flow:metric:record-failed", { error: err instanceof Error ? err.message : String(err) });
|
|
8364
|
+
}
|
|
8365
|
+
}
|
|
8366
|
+
function applyFlowToCompact(store2, nodeId) {
|
|
8367
|
+
const cfg = resolveFlowConfig(store2);
|
|
8368
|
+
if (!cfg.enabled) return null;
|
|
8369
|
+
const projectId = store2.getActiveProject()?.id ?? "unknown";
|
|
8370
|
+
const outcomes = queryEpisodicOutcomes(store2.getDb(), { limit: cfg.historyWindow }).map((o) => o.outcome);
|
|
8371
|
+
const state = computeFlowIndex(outcomes, {
|
|
8372
|
+
emaGain: cfg.emaGain,
|
|
8373
|
+
resetFactor: cfg.resetFactor,
|
|
8374
|
+
partialFactor: cfg.partialFactor
|
|
8375
|
+
});
|
|
8376
|
+
const lambda = computeLambdaFlow(state.phi, cfg.lambdaBase, cfg.alpha);
|
|
8377
|
+
const mode = cfg.experiment.abEnabled ? flowAbArm(nodeId) : "flow_on";
|
|
8378
|
+
if (mode === "flow_off") {
|
|
8379
|
+
const base = buildTaskContext(store2, nodeId);
|
|
8380
|
+
if (!base) return null;
|
|
8381
|
+
const baseline = base.metrics.estimatedTokens;
|
|
8382
|
+
recordMetric(store2, {
|
|
8383
|
+
projectId,
|
|
8384
|
+
nodeId,
|
|
8385
|
+
mode,
|
|
8386
|
+
phi: state.phi,
|
|
8387
|
+
lambda,
|
|
8388
|
+
tokensBaseline: baseline,
|
|
8389
|
+
tokensActual: baseline,
|
|
8390
|
+
prunedCount: 0,
|
|
8391
|
+
pinnedCount: 0
|
|
8392
|
+
});
|
|
8393
|
+
return {
|
|
8394
|
+
context: base,
|
|
8395
|
+
pinnedInvariants: [],
|
|
8396
|
+
flow: {
|
|
8397
|
+
enabled: true,
|
|
8398
|
+
mode,
|
|
8399
|
+
phi: state.phi,
|
|
8400
|
+
streak: state.streak,
|
|
8401
|
+
lambda,
|
|
8402
|
+
prunedCount: 0,
|
|
8403
|
+
pinnedCount: 0,
|
|
8404
|
+
tokensBaseline: baseline,
|
|
8405
|
+
tokensActual: baseline,
|
|
8406
|
+
tokensSaved: 0
|
|
8407
|
+
}
|
|
8408
|
+
};
|
|
8409
|
+
}
|
|
8410
|
+
const decayed = buildDecayedTaskContext(store2, nodeId, {
|
|
8411
|
+
lambda,
|
|
8412
|
+
maxDepth: cfg.maxDepth,
|
|
8413
|
+
weightThreshold: cfg.weightThreshold,
|
|
8414
|
+
pinnedTypes: new Set(cfg.pinnedTypes)
|
|
8415
|
+
});
|
|
8416
|
+
if (!decayed) return null;
|
|
8417
|
+
recordMetric(store2, {
|
|
8418
|
+
projectId,
|
|
8419
|
+
nodeId,
|
|
8420
|
+
mode,
|
|
8421
|
+
phi: state.phi,
|
|
8422
|
+
lambda,
|
|
8423
|
+
tokensBaseline: decayed.meta.tokensBaseline,
|
|
8424
|
+
tokensActual: decayed.meta.tokensActual,
|
|
8425
|
+
prunedCount: decayed.meta.prunedCount,
|
|
8426
|
+
pinnedCount: decayed.meta.pinnedCount
|
|
8427
|
+
});
|
|
8428
|
+
return {
|
|
8429
|
+
context: decayed.context,
|
|
8430
|
+
pinnedInvariants: decayed.meta.pinnedInvariants,
|
|
8431
|
+
flow: {
|
|
8432
|
+
enabled: true,
|
|
8433
|
+
mode,
|
|
8434
|
+
phi: state.phi,
|
|
8435
|
+
streak: state.streak,
|
|
8436
|
+
lambda,
|
|
8437
|
+
prunedCount: decayed.meta.prunedCount,
|
|
8438
|
+
pinnedCount: decayed.meta.pinnedCount,
|
|
8439
|
+
tokensBaseline: decayed.meta.tokensBaseline,
|
|
8440
|
+
tokensActual: decayed.meta.tokensActual,
|
|
8441
|
+
tokensSaved: decayed.meta.tokensSaved
|
|
8442
|
+
}
|
|
8443
|
+
};
|
|
8444
|
+
}
|
|
8445
|
+
var log28;
|
|
8446
|
+
var init_flow_compact = __esm({
|
|
8447
|
+
"src/core/context/flow-compact.ts"() {
|
|
8448
|
+
init_esm_shims();
|
|
8449
|
+
init_flow_config();
|
|
8450
|
+
init_flow_index();
|
|
8451
|
+
init_topological_decay();
|
|
8452
|
+
init_compact_context();
|
|
8453
|
+
init_episodic_outcomes_store();
|
|
8454
|
+
init_flow_metrics_store();
|
|
8455
|
+
init_id();
|
|
8456
|
+
init_logger();
|
|
8457
|
+
log28 = createLogger({ layer: "core", source: "flow-compact.ts" });
|
|
8458
|
+
}
|
|
8459
|
+
});
|
|
7576
8460
|
|
|
7577
8461
|
// src/cli/shared/live-implement.ts
|
|
7578
8462
|
function buildLiveImplement(options) {
|
|
@@ -7589,6 +8473,14 @@ function buildLiveImplement(options) {
|
|
|
7589
8473
|
const repoRelations = projectId ? codeStore.getAllRelations(projectId) : [];
|
|
7590
8474
|
const implement = async (node) => {
|
|
7591
8475
|
const repoMap = repoSymbols.length > 0 ? buildRepoMap({ symbols: repoSymbols, relations: repoRelations }, { tokenBudget: REPO_MAP_TOKEN_BUDGET, focus: node.title }).text : void 0;
|
|
8476
|
+
let flowContext;
|
|
8477
|
+
const flow = applyFlowToCompact(store2, node.id);
|
|
8478
|
+
if (flow) {
|
|
8479
|
+
flowContext = formatFlowContext(flow);
|
|
8480
|
+
onLog?.(
|
|
8481
|
+
` [flow] \u03A6=${flow.flow.phi.toFixed(2)} \u03BB=${flow.flow.lambda.toFixed(2)} podados=${flow.flow.prunedCount} pinados=${flow.flow.pinnedCount} \u2192 ${flow.flow.tokensSaved} tok economizados`
|
|
8482
|
+
);
|
|
8483
|
+
}
|
|
7592
8484
|
const outcome = await attemptImplementation(
|
|
7593
8485
|
{
|
|
7594
8486
|
generate: async (prompt) => {
|
|
@@ -7604,13 +8496,28 @@ function buildLiveImplement(options) {
|
|
|
7604
8496
|
},
|
|
7605
8497
|
execute: (plan) => executePlan(plan, { workspaceDir: dir, defaultTestCommand: testCmd })
|
|
7606
8498
|
},
|
|
7607
|
-
{ node, maxAttempts, repoMap }
|
|
8499
|
+
{ node, maxAttempts, repoMap, flowContext }
|
|
7608
8500
|
);
|
|
7609
8501
|
const files = outcome.lastResult?.applied.length ?? 0;
|
|
7610
8502
|
const task = ledger.byTask(node.id);
|
|
7611
8503
|
onLog?.(
|
|
7612
8504
|
` [live] ${client.modelFor("implement")}: ${outcome.attempts} tentativa(s), ${files} arquivo(s), ${task.total} tok \u2192 ${outcome.success ? "verde" : "escala"}`
|
|
7613
8505
|
);
|
|
8506
|
+
try {
|
|
8507
|
+
const applied = outcome.lastResult?.applied ?? [];
|
|
8508
|
+
insertEpisodicOutcome(store2.getDb(), {
|
|
8509
|
+
id: generateId("epi"),
|
|
8510
|
+
nodeId: node.id,
|
|
8511
|
+
taskType: "",
|
|
8512
|
+
tags: "",
|
|
8513
|
+
approachSummary: buildApproachSummary(applied, []),
|
|
8514
|
+
outcome: outcome.success ? "success" : "failure",
|
|
8515
|
+
cycleTimeDelta: 0,
|
|
8516
|
+
reopenCount: 0,
|
|
8517
|
+
createdAt: Date.now()
|
|
8518
|
+
});
|
|
8519
|
+
} catch {
|
|
8520
|
+
}
|
|
7614
8521
|
return outcome.success;
|
|
7615
8522
|
};
|
|
7616
8523
|
return { implement, repoSymbolCount: repoSymbols.length };
|
|
@@ -7625,6 +8532,9 @@ var init_live_implement = __esm({
|
|
|
7625
8532
|
init_implement_attempt();
|
|
7626
8533
|
init_code_store();
|
|
7627
8534
|
init_repo_map();
|
|
8535
|
+
init_flow_compact();
|
|
8536
|
+
init_episodic_outcomes_store();
|
|
8537
|
+
init_id();
|
|
7628
8538
|
REPO_MAP_TOKEN_BUDGET = 1e3;
|
|
7629
8539
|
}
|
|
7630
8540
|
});
|
|
@@ -7890,7 +8800,7 @@ function InteractiveApp({ dashboard, port, asyncPort, liveRunner, skillCommands
|
|
|
7890
8800
|
process.stdout.isTTY ? "banner" : "dashboard"
|
|
7891
8801
|
);
|
|
7892
8802
|
const [input, setInput] = useState("");
|
|
7893
|
-
const [
|
|
8803
|
+
const [log48, setLog] = useState([]);
|
|
7894
8804
|
const [running, setRunning] = useState(false);
|
|
7895
8805
|
const [showHelp, setShowHelp] = useState(false);
|
|
7896
8806
|
const append = (line) => setLog((prev) => [...prev, line].slice(-MAX_LOG_LINES));
|
|
@@ -7939,7 +8849,7 @@ ${skill.body}` : `Skill n\xE3o encontrada: ${parsed.cmd}`);
|
|
|
7939
8849
|
}
|
|
7940
8850
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
7941
8851
|
/* @__PURE__ */ jsx(App, { model: dashboard }),
|
|
7942
|
-
|
|
8852
|
+
log48.length > 0 && /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, borderStyle: "single", paddingX: 1, children: log48.map((line, i) => /* @__PURE__ */ jsx(Text, { children: line }, i)) }),
|
|
7943
8853
|
showHelp && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", paddingX: 1, children: [
|
|
7944
8854
|
/* @__PURE__ */ jsx(Text, { bold: true, children: "Comandos:" }),
|
|
7945
8855
|
COMMANDS.map((c) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
@@ -8166,22 +9076,25 @@ function parseSkillMarkdown(content) {
|
|
|
8166
9076
|
} catch (err) {
|
|
8167
9077
|
return { ok: false, error: `YAML parse error: ${err instanceof Error ? err.message : String(err)}` };
|
|
8168
9078
|
}
|
|
9079
|
+
const rawTriggers = frontmatter.triggers;
|
|
9080
|
+
const triggers = Array.isArray(rawTriggers) ? rawTriggers.map((t) => typeof t === "string" ? { event: t } : t) : rawTriggers;
|
|
9081
|
+
const phases = Array.isArray(frontmatter.phases) ? frontmatter.phases : [];
|
|
8169
9082
|
const raw = {
|
|
8170
9083
|
name: frontmatter.name,
|
|
8171
9084
|
description: frontmatter.description,
|
|
8172
9085
|
category: frontmatter.category ?? "know-me",
|
|
8173
|
-
phases
|
|
9086
|
+
phases,
|
|
8174
9087
|
// §extracta-sweep-1 — optional `platforms:` array; absent = all OSes.
|
|
8175
9088
|
platforms: frontmatter.platforms,
|
|
8176
9089
|
instructions: bodyText,
|
|
8177
9090
|
toolchain: frontmatter.toolchain,
|
|
8178
|
-
triggers
|
|
9091
|
+
triggers,
|
|
8179
9092
|
contextTemplate: frontmatter.contextTemplate
|
|
8180
9093
|
};
|
|
8181
9094
|
const parsed = CustomSkillInputSchema.safeParse(raw);
|
|
8182
9095
|
if (!parsed.success) {
|
|
8183
9096
|
const issues = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
8184
|
-
|
|
9097
|
+
log29.debug("skill-loader:validation_failed", { issues });
|
|
8185
9098
|
return { ok: false, error: `Validation failed: ${issues}` };
|
|
8186
9099
|
}
|
|
8187
9100
|
return { ok: true, skill: parsed.data };
|
|
@@ -8224,13 +9137,13 @@ function walk(dir, acc) {
|
|
|
8224
9137
|
else acc.errors.push({ file: full, error: parsed.error ?? "unknown parse error" });
|
|
8225
9138
|
}
|
|
8226
9139
|
}
|
|
8227
|
-
var
|
|
9140
|
+
var log29;
|
|
8228
9141
|
var init_skill_loader = __esm({
|
|
8229
9142
|
"src/core/skills/skill-loader.ts"() {
|
|
8230
9143
|
init_esm_shims();
|
|
8231
9144
|
init_skill_schema();
|
|
8232
9145
|
init_logger();
|
|
8233
|
-
|
|
9146
|
+
log29 = createLogger({ layer: "core", source: "skill-loader.ts" });
|
|
8234
9147
|
}
|
|
8235
9148
|
});
|
|
8236
9149
|
function summarize(skill) {
|
|
@@ -8323,7 +9236,7 @@ function mergeGraph(store2, incoming, options) {
|
|
|
8323
9236
|
}
|
|
8324
9237
|
const sourceProject = incoming.project.name;
|
|
8325
9238
|
const dryRun = options?.dryRun ?? false;
|
|
8326
|
-
|
|
9239
|
+
log30.info("merge-graph:start", {
|
|
8327
9240
|
sourceProject,
|
|
8328
9241
|
incomingNodes: incoming.nodes.length,
|
|
8329
9242
|
incomingEdges: incoming.edges.length,
|
|
@@ -8375,7 +9288,7 @@ function mergeGraph(store2, incoming, options) {
|
|
|
8375
9288
|
edgesInserted2++;
|
|
8376
9289
|
}
|
|
8377
9290
|
}
|
|
8378
|
-
|
|
9291
|
+
log30.info("merge-graph:dry-run", {
|
|
8379
9292
|
nodesInserted: nodesToInsert.length,
|
|
8380
9293
|
nodesSkipped,
|
|
8381
9294
|
edgesInserted: edgesInserted2,
|
|
@@ -8395,7 +9308,7 @@ function mergeGraph(store2, incoming, options) {
|
|
|
8395
9308
|
const { nodesInserted, edgesInserted } = store2.mergeInsert(nodesToInsert, validEdges);
|
|
8396
9309
|
const edgesSkipped = validEdges.length - edgesInserted;
|
|
8397
9310
|
store2.recordImport(`merge:${sourceProject}`, nodesInserted, edgesInserted);
|
|
8398
|
-
|
|
9311
|
+
log30.info("merge-graph:done", {
|
|
8399
9312
|
sourceProject,
|
|
8400
9313
|
nodesInserted,
|
|
8401
9314
|
nodesSkipped,
|
|
@@ -8412,14 +9325,14 @@ function mergeGraph(store2, incoming, options) {
|
|
|
8412
9325
|
sourceProject
|
|
8413
9326
|
};
|
|
8414
9327
|
}
|
|
8415
|
-
var
|
|
9328
|
+
var log30;
|
|
8416
9329
|
var init_import_graph = __esm({
|
|
8417
9330
|
"src/core/importer/import-graph.ts"() {
|
|
8418
9331
|
init_esm_shims();
|
|
8419
9332
|
init_graph_schema();
|
|
8420
9333
|
init_errors();
|
|
8421
9334
|
init_logger();
|
|
8422
|
-
|
|
9335
|
+
log30 = createLogger({ layer: "core", source: "import-graph.ts" });
|
|
8423
9336
|
}
|
|
8424
9337
|
});
|
|
8425
9338
|
|
|
@@ -8530,7 +9443,7 @@ function computeFileSha256(path22) {
|
|
|
8530
9443
|
return hash.digest("hex");
|
|
8531
9444
|
}
|
|
8532
9445
|
async function downloadFileWithVerify(url, destPath, expectedSha256) {
|
|
8533
|
-
|
|
9446
|
+
log31.info("model-downloader:start", { url, dest: destPath, hasExpectedHash: false });
|
|
8534
9447
|
const controller = new AbortController();
|
|
8535
9448
|
const timeoutId = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS);
|
|
8536
9449
|
let response;
|
|
@@ -8552,15 +9465,15 @@ async function downloadFileWithVerify(url, destPath, expectedSha256) {
|
|
|
8552
9465
|
const actualSha = computeFileSha256(destPath);
|
|
8553
9466
|
const sizeBytes = statSync(destPath).size;
|
|
8554
9467
|
const verified = expectedSha256 != null && actualSha === expectedSha256;
|
|
8555
|
-
|
|
9468
|
+
log31.info("model-downloader:ok", { dest: destPath, sizeBytes, sha256: actualSha, verified });
|
|
8556
9469
|
return { sha256: actualSha, verified, sizeBytes };
|
|
8557
9470
|
}
|
|
8558
|
-
var
|
|
9471
|
+
var log31, DOWNLOAD_TIMEOUT_MS, ChecksumMismatchError, DownloadError;
|
|
8559
9472
|
var init_model_downloader = __esm({
|
|
8560
9473
|
"src/core/rag/model-downloader.ts"() {
|
|
8561
9474
|
init_esm_shims();
|
|
8562
9475
|
init_logger();
|
|
8563
|
-
|
|
9476
|
+
log31 = createLogger({ layer: "core", source: "model-downloader.ts" });
|
|
8564
9477
|
DOWNLOAD_TIMEOUT_MS = 9e4;
|
|
8565
9478
|
ChecksumMismatchError = class extends Error {
|
|
8566
9479
|
constructor(url, expected, actual) {
|
|
@@ -8629,15 +9542,15 @@ async function isOnnxAvailable() {
|
|
|
8629
9542
|
onnxAvailableCache = true;
|
|
8630
9543
|
} catch {
|
|
8631
9544
|
onnxAvailableCache = false;
|
|
8632
|
-
|
|
9545
|
+
log32.warn("onnx:unavailable", { reason: "onnxruntime-node not installed \u2014 RAG will use hash embeddings (degraded mode)" });
|
|
8633
9546
|
}
|
|
8634
9547
|
return onnxAvailableCache;
|
|
8635
9548
|
}
|
|
8636
9549
|
async function logEmbeddingModeOnBoot(isAvailable = isOnnxAvailable, logFn = (event, fields) => {
|
|
8637
9550
|
if (fields.mode === "neural") {
|
|
8638
|
-
|
|
9551
|
+
log32.info(event, fields);
|
|
8639
9552
|
} else {
|
|
8640
|
-
|
|
9553
|
+
log32.warn(event, fields);
|
|
8641
9554
|
}
|
|
8642
9555
|
}) {
|
|
8643
9556
|
try {
|
|
@@ -8660,7 +9573,7 @@ function ensureOnnxModelDir(modelsDir) {
|
|
|
8660
9573
|
async function downloadFile(url, destPath) {
|
|
8661
9574
|
try {
|
|
8662
9575
|
const resultValue = await downloadFileWithVerify(url, destPath);
|
|
8663
|
-
|
|
9576
|
+
log32.info("onnx:download:ok", {
|
|
8664
9577
|
dest: destPath,
|
|
8665
9578
|
sizeBytes: resultValue.sizeBytes,
|
|
8666
9579
|
sha256: resultValue.sha256,
|
|
@@ -8684,7 +9597,7 @@ async function ensureModelFiles(modelsDir) {
|
|
|
8684
9597
|
if (existsSync(modelPath)) {
|
|
8685
9598
|
const size = statSync(modelPath).size;
|
|
8686
9599
|
if (size < MIN_MODEL_SIZE) {
|
|
8687
|
-
|
|
9600
|
+
log32.warn("onnx:corrupted-model", { modelPath, sizeBytes: size, minRequired: MIN_MODEL_SIZE });
|
|
8688
9601
|
unlinkSync(modelPath);
|
|
8689
9602
|
}
|
|
8690
9603
|
}
|
|
@@ -8693,12 +9606,12 @@ async function ensureModelFiles(modelsDir) {
|
|
|
8693
9606
|
const raw = readFileSync(tokenizerPath, "utf-8");
|
|
8694
9607
|
JSON.parse(raw);
|
|
8695
9608
|
} catch {
|
|
8696
|
-
|
|
9609
|
+
log32.warn("onnx:corrupted-tokenizer", { tokenizerPath });
|
|
8697
9610
|
unlinkSync(tokenizerPath);
|
|
8698
9611
|
}
|
|
8699
9612
|
}
|
|
8700
9613
|
if (existsSync(modelPath) && existsSync(tokenizerPath)) {
|
|
8701
|
-
|
|
9614
|
+
log32.debug("onnx:cache-hit", { modelDir });
|
|
8702
9615
|
return { modelPath, tokenizerPath };
|
|
8703
9616
|
}
|
|
8704
9617
|
mkdirSync(modelDir, { recursive: true });
|
|
@@ -8715,7 +9628,7 @@ function loadTokenizer(tokenizerPath) {
|
|
|
8715
9628
|
const raw = readFileSync(tokenizerPath, "utf-8");
|
|
8716
9629
|
return JSON.parse(raw);
|
|
8717
9630
|
} catch (err) {
|
|
8718
|
-
|
|
9631
|
+
log32.warn("onnx:tokenizer-load-failed", { tokenizerPath, error: err instanceof Error ? err.message : String(err) });
|
|
8719
9632
|
return null;
|
|
8720
9633
|
}
|
|
8721
9634
|
}
|
|
@@ -8767,15 +9680,15 @@ function startOnnxBackgroundDownload(modelsDir, options = {}) {
|
|
|
8767
9680
|
modelPath = join(modelDir, MODEL_FILENAME);
|
|
8768
9681
|
tokenizerPath = join(modelDir, TOKENIZER_FILENAME);
|
|
8769
9682
|
const cacheEvent = "onnx:background-ready-from-cache";
|
|
8770
|
-
|
|
9683
|
+
log32.info(cacheEvent, { modelsDir });
|
|
8771
9684
|
onLog?.(cacheEvent);
|
|
8772
9685
|
} else {
|
|
8773
9686
|
const startEvent = "onnx:background-download-start";
|
|
8774
|
-
|
|
9687
|
+
log32.info(startEvent, { message: "Downloading MiniLM-L6-v2 (23MB)...", modelsDir });
|
|
8775
9688
|
onLog?.(startEvent);
|
|
8776
9689
|
({ modelPath, tokenizerPath } = await ensureFiles(modelsDir));
|
|
8777
9690
|
const doneEvent = "onnx:background-download-complete";
|
|
8778
|
-
|
|
9691
|
+
log32.info(doneEvent, { modelsDir });
|
|
8779
9692
|
onLog?.(doneEvent);
|
|
8780
9693
|
}
|
|
8781
9694
|
const provider = makeProvider(modelPath, tokenizerPath);
|
|
@@ -8783,7 +9696,7 @@ function startOnnxBackgroundDownload(modelsDir, options = {}) {
|
|
|
8783
9696
|
onReady?.(provider);
|
|
8784
9697
|
} catch (err) {
|
|
8785
9698
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8786
|
-
|
|
9699
|
+
log32.warn("onnx:background-download-failed", { error: msg, action: "fallback-remains-tfidf" });
|
|
8787
9700
|
onWarning?.(msg);
|
|
8788
9701
|
}
|
|
8789
9702
|
};
|
|
@@ -8797,7 +9710,7 @@ function _resetBackgroundDownloadState() {
|
|
|
8797
9710
|
async function getOnnxProvider(modelsDir) {
|
|
8798
9711
|
const available = await isOnnxAvailable();
|
|
8799
9712
|
if (!available) {
|
|
8800
|
-
|
|
9713
|
+
log32.warn("onnx:provider-degraded", { available: false, impact: "RAG operates with hash embeddings instead of neural \u2014 lower search quality" });
|
|
8801
9714
|
return null;
|
|
8802
9715
|
}
|
|
8803
9716
|
const existing = providerCache.get(modelsDir);
|
|
@@ -8817,8 +9730,8 @@ async function getOnnxProvider(modelsDir) {
|
|
|
8817
9730
|
return await creation;
|
|
8818
9731
|
} catch (err) {
|
|
8819
9732
|
providerCache.delete(modelsDir);
|
|
8820
|
-
|
|
8821
|
-
|
|
9733
|
+
log32.error("onnx:provider-init-failed", { error: err instanceof Error ? err.message : String(err) });
|
|
9734
|
+
log32.warn("onnx:fallback", {
|
|
8822
9735
|
reason: err instanceof Error ? err.message : String(err),
|
|
8823
9736
|
action: "return-null-provider",
|
|
8824
9737
|
modelsDir
|
|
@@ -8826,7 +9739,7 @@ async function getOnnxProvider(modelsDir) {
|
|
|
8826
9739
|
return null;
|
|
8827
9740
|
}
|
|
8828
9741
|
}
|
|
8829
|
-
var
|
|
9742
|
+
var log32, MODEL_NAME, MODEL_FILENAME, TOKENIZER_FILENAME, EMBEDDING_DIM, MAX_SEQUENCE_LENGTH, MODEL_BASE_URL, MODEL_URL, TOKENIZER_URL, DOWNLOAD_TIMEOUT_MS2, onnxAvailableCache, OnnxEmbeddingProvider, _backgroundProvider, _backgroundStarted, providerCache;
|
|
8830
9743
|
var init_onnx_embeddings = __esm({
|
|
8831
9744
|
"src/core/rag/onnx-embeddings.ts"() {
|
|
8832
9745
|
init_esm_shims();
|
|
@@ -8834,7 +9747,7 @@ var init_onnx_embeddings = __esm({
|
|
|
8834
9747
|
init_errors();
|
|
8835
9748
|
init_tensor_buffer_pool();
|
|
8836
9749
|
init_model_downloader();
|
|
8837
|
-
|
|
9750
|
+
log32 = createLogger({ layer: "rag", source: "onnx-embeddings.ts" });
|
|
8838
9751
|
MODEL_NAME = "all-MiniLM-L6-v2-quantized";
|
|
8839
9752
|
MODEL_FILENAME = "model.onnx";
|
|
8840
9753
|
TOKENIZER_FILENAME = "tokenizer.json";
|
|
@@ -8866,7 +9779,7 @@ var init_onnx_embeddings = __esm({
|
|
|
8866
9779
|
throw new OnnxModelNotFoundError(`Failed to load tokenizer: ${this.tokenizerPath}`);
|
|
8867
9780
|
}
|
|
8868
9781
|
this.vocab = config.model?.vocab ?? {};
|
|
8869
|
-
|
|
9782
|
+
log32.info("onnx:session-created", { model: this.modelPath });
|
|
8870
9783
|
return this.session;
|
|
8871
9784
|
}
|
|
8872
9785
|
async generateEmbedding(text) {
|
|
@@ -8995,7 +9908,7 @@ async function checkSqliteDatabase(basePath) {
|
|
|
8995
9908
|
};
|
|
8996
9909
|
}
|
|
8997
9910
|
} catch (err) {
|
|
8998
|
-
|
|
9911
|
+
log33.debug("intentional-swallow", { error: String(err), reason: "statSync race with deletion; fall through to open attempt" });
|
|
8999
9912
|
}
|
|
9000
9913
|
try {
|
|
9001
9914
|
const db = new Database2(dbPath, { readonly: true });
|
|
@@ -9045,7 +9958,7 @@ async function checkDbIntegrity2(basePath) {
|
|
|
9045
9958
|
};
|
|
9046
9959
|
}
|
|
9047
9960
|
} catch (err) {
|
|
9048
|
-
|
|
9961
|
+
log33.debug("intentional-swallow", { error: String(err), reason: "fall through to open attempt" });
|
|
9049
9962
|
}
|
|
9050
9963
|
try {
|
|
9051
9964
|
const db = new Database2(dbPath, { readonly: true });
|
|
@@ -9053,7 +9966,7 @@ async function checkDbIntegrity2(basePath) {
|
|
|
9053
9966
|
try {
|
|
9054
9967
|
schemaCount = db.prepare("SELECT count(*) as n FROM sqlite_master WHERE type IN ('table','view')").get().n;
|
|
9055
9968
|
} catch (err) {
|
|
9056
|
-
|
|
9969
|
+
log33.debug("intentional-swallow", { error: String(err), reason: "reading sqlite_master itself failed \u2014 DB is unreadable, fall through" });
|
|
9057
9970
|
}
|
|
9058
9971
|
if (schemaCount === 0) {
|
|
9059
9972
|
db.close();
|
|
@@ -9213,7 +10126,7 @@ async function checkIntegrations(basePath) {
|
|
|
9213
10126
|
});
|
|
9214
10127
|
return results;
|
|
9215
10128
|
} catch (err) {
|
|
9216
|
-
|
|
10129
|
+
log33.debug("doctor:integrations:fail", {
|
|
9217
10130
|
error: err instanceof Error ? err.message : String(err)
|
|
9218
10131
|
});
|
|
9219
10132
|
return [
|
|
@@ -9264,7 +10177,7 @@ async function checkOnnxStatus() {
|
|
|
9264
10177
|
const { isOnnxAvailable: isOnnxAvailable2 } = await Promise.resolve().then(() => (init_onnx_embeddings(), onnx_embeddings_exports));
|
|
9265
10178
|
return checkOnnxStatusWith(isOnnxAvailable2);
|
|
9266
10179
|
}
|
|
9267
|
-
var
|
|
10180
|
+
var log33, MIN_NODE_VERSION;
|
|
9268
10181
|
var init_doctor_checks = __esm({
|
|
9269
10182
|
"src/core/doctor/doctor-checks.ts"() {
|
|
9270
10183
|
init_esm_shims();
|
|
@@ -9272,7 +10185,7 @@ var init_doctor_checks = __esm({
|
|
|
9272
10185
|
init_fs();
|
|
9273
10186
|
init_tool_status();
|
|
9274
10187
|
init_logger();
|
|
9275
|
-
|
|
10188
|
+
log33 = createLogger({ layer: "core", source: "doctor-checks.ts" });
|
|
9276
10189
|
MIN_NODE_VERSION = 20;
|
|
9277
10190
|
}
|
|
9278
10191
|
});
|
|
@@ -9297,7 +10210,7 @@ async function runDoctor(basePath) {
|
|
|
9297
10210
|
if (!basePath) {
|
|
9298
10211
|
throw new McpGraphError("Doctor requires a valid base path");
|
|
9299
10212
|
}
|
|
9300
|
-
|
|
10213
|
+
log34.info("Running doctor checks", { basePath });
|
|
9301
10214
|
const checks = [];
|
|
9302
10215
|
checks.push(checkNodeVersion());
|
|
9303
10216
|
checks.push(checkConfigFile(basePath));
|
|
@@ -9335,7 +10248,7 @@ async function runDoctor(basePath) {
|
|
|
9335
10248
|
}
|
|
9336
10249
|
}
|
|
9337
10250
|
for (const result of checks) {
|
|
9338
|
-
|
|
10251
|
+
log34.event(
|
|
9339
10252
|
{ action: "health.check", category: "health", outcome: result.level === "ok" ? "success" : "failure" },
|
|
9340
10253
|
`health.check.${result.name}`,
|
|
9341
10254
|
{ check: result.name }
|
|
@@ -9348,7 +10261,7 @@ async function runDoctor(basePath) {
|
|
|
9348
10261
|
passed: summary.error === 0
|
|
9349
10262
|
};
|
|
9350
10263
|
}
|
|
9351
|
-
var
|
|
10264
|
+
var log34;
|
|
9352
10265
|
var init_doctor_runner = __esm({
|
|
9353
10266
|
"src/core/doctor/doctor-runner.ts"() {
|
|
9354
10267
|
init_esm_shims();
|
|
@@ -9357,7 +10270,7 @@ var init_doctor_runner = __esm({
|
|
|
9357
10270
|
init_errors();
|
|
9358
10271
|
init_logger();
|
|
9359
10272
|
init_doctor_checks();
|
|
9360
|
-
|
|
10273
|
+
log34 = createLogger({ layer: "core", source: "doctor-runner.ts" });
|
|
9361
10274
|
}
|
|
9362
10275
|
});
|
|
9363
10276
|
|
|
@@ -10104,16 +11017,36 @@ init_token_ledger();
|
|
|
10104
11017
|
init_llm_call_ledger();
|
|
10105
11018
|
init_live_implement();
|
|
10106
11019
|
init_store_port();
|
|
11020
|
+
|
|
11021
|
+
// src/cli/shared/enable-flow.ts
|
|
11022
|
+
init_esm_shims();
|
|
11023
|
+
init_flow_config();
|
|
11024
|
+
function enableFlowConfig(store2) {
|
|
11025
|
+
const raw = store2.getProjectSetting(FLOW_CONFIG_SETTING_KEY);
|
|
11026
|
+
let current = {};
|
|
11027
|
+
if (raw) {
|
|
11028
|
+
try {
|
|
11029
|
+
current = JSON.parse(raw);
|
|
11030
|
+
} catch {
|
|
11031
|
+
current = {};
|
|
11032
|
+
}
|
|
11033
|
+
}
|
|
11034
|
+
store2.setProjectSetting(FLOW_CONFIG_SETTING_KEY, JSON.stringify({ ...current, enabled: true }));
|
|
11035
|
+
}
|
|
10107
11036
|
function output7(msg) {
|
|
10108
11037
|
process.stdout.write(msg + "\n");
|
|
10109
11038
|
}
|
|
10110
11039
|
function autopilotCommand() {
|
|
10111
|
-
return new Command("autopilot").description("Loop aut\xF4nomo com guardrails: next \u2192 in_progress \u2192 DoD \u2192 done|escalate (WIP=1)").option("-d, --dir <dir>", "Diret\xF3rio do projeto", process.cwd()).option("-m, --max <n>", "Budget: m\xE1ximo de tasks por sess\xE3o (cost-runaway guard)", "5").option("--simulate", "Simula impl bem-sucedida (deixa o DoD real decidir) \u2014 n\xE3o escreve c\xF3digo", false).option("--live", "Invoca o modelo real via SDK do Copilot: gera plano \u2192 aplica \u2192 roda testes \u2192 done|escala", false).option("--test-cmd <cmd>", "Comando de teste rodado no modo --live quando o plano n\xE3o traz um", "npm test").option("--retries <n>", "Tentativas por task no --live (retry com feedback compacto do teste)", "2").action(
|
|
11040
|
+
return new Command("autopilot").description("Loop aut\xF4nomo com guardrails: next \u2192 in_progress \u2192 DoD \u2192 done|escalate (WIP=1)").option("-d, --dir <dir>", "Diret\xF3rio do projeto", process.cwd()).option("-m, --max <n>", "Budget: m\xE1ximo de tasks por sess\xE3o (cost-runaway guard)", "5").option("--simulate", "Simula impl bem-sucedida (deixa o DoD real decidir) \u2014 n\xE3o escreve c\xF3digo", false).option("--live", "Invoca o modelo real via SDK do Copilot: gera plano \u2192 aplica \u2192 roda testes \u2192 done|escala", false).option("--test-cmd <cmd>", "Comando de teste rodado no modo --live quando o plano n\xE3o traz um", "npm test").option("--retries <n>", "Tentativas por task no --live (retry com feedback compacto do teste)", "2").option("--flow", "Ativa a dilui\xE7\xE3o de contexto por \u03BB_flow (hipofrontalidade) no --live", false).action(
|
|
10112
11041
|
async (opts) => {
|
|
10113
11042
|
const store2 = openStoreOrFail(opts.dir, { requireExisting: true });
|
|
10114
11043
|
try {
|
|
10115
11044
|
const maxIterations = Math.max(1, parseInt(opts.max, 10) || 5);
|
|
10116
11045
|
const port = makeStorePort(store2);
|
|
11046
|
+
if (opts.flow) {
|
|
11047
|
+
enableFlowConfig(store2);
|
|
11048
|
+
output7("[FLOW] \u03BB_flow ativo: contexto do grafo dilu\xEDdo por \u03A6(t) (esquecimento din\xE2mico).\n");
|
|
11049
|
+
}
|
|
10117
11050
|
if (opts.simulate) output7("[SIMULA\xC7\xC3O] impl tratada como verde \u2014 DoD real decide prontid\xE3o.\n");
|
|
10118
11051
|
if (opts.live) output7("[LIVE] modelo via SDK do Copilot: gera plano \u2192 aplica no workspace \u2192 roda testes.\n");
|
|
10119
11052
|
let implement;
|
|
@@ -10413,7 +11346,7 @@ function whichCommand() {
|
|
|
10413
11346
|
}
|
|
10414
11347
|
|
|
10415
11348
|
// src/core/lsp/lsp-deps-installer.ts
|
|
10416
|
-
var
|
|
11349
|
+
var log36 = createLogger({ layer: "core", source: "lsp-deps-installer.ts" });
|
|
10417
11350
|
var execAsync = promisify(execFile);
|
|
10418
11351
|
var LSP_NPM_PACKAGES = {
|
|
10419
11352
|
typescript: "typescript-language-server",
|
|
@@ -10464,7 +11397,7 @@ var LSP_SYSTEM_PACKAGES = {
|
|
|
10464
11397
|
async function checkLspDep(languageId, command) {
|
|
10465
11398
|
try {
|
|
10466
11399
|
await execAsync(whichCommand(), [command]);
|
|
10467
|
-
|
|
11400
|
+
log36.info("LSP server available", { languageId, command });
|
|
10468
11401
|
return {
|
|
10469
11402
|
name: command,
|
|
10470
11403
|
languageId,
|
|
@@ -10510,7 +11443,7 @@ function getServerCommand(languageId) {
|
|
|
10510
11443
|
}
|
|
10511
11444
|
async function installLspDeps(detectedLanguages) {
|
|
10512
11445
|
if (detectedLanguages.length === 0) return [];
|
|
10513
|
-
|
|
11446
|
+
log36.info("Checking LSP server dependencies", {
|
|
10514
11447
|
languages: detectedLanguages.join(", ")
|
|
10515
11448
|
});
|
|
10516
11449
|
const results = [];
|
|
@@ -10522,7 +11455,7 @@ async function installLspDeps(detectedLanguages) {
|
|
|
10522
11455
|
}
|
|
10523
11456
|
const available = results.filter((r) => r.status === "already_available").length;
|
|
10524
11457
|
const missing = results.filter((r) => r.status === "not_found").length;
|
|
10525
|
-
|
|
11458
|
+
log36.info("LSP dependency check complete", {
|
|
10526
11459
|
total: String(results.length),
|
|
10527
11460
|
available: String(available),
|
|
10528
11461
|
missing: String(missing)
|
|
@@ -10533,7 +11466,7 @@ async function installLspDeps(detectedLanguages) {
|
|
|
10533
11466
|
// src/core/lsp/language-detector.ts
|
|
10534
11467
|
init_esm_shims();
|
|
10535
11468
|
init_logger();
|
|
10536
|
-
var
|
|
11469
|
+
var log37 = createLogger({ layer: "core", source: "language-detector.ts" });
|
|
10537
11470
|
var CONFIG_FILE_MAP = {
|
|
10538
11471
|
"tsconfig.json": "typescript",
|
|
10539
11472
|
"jsconfig.json": "typescript",
|
|
@@ -10573,7 +11506,7 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
|
10573
11506
|
"__pycache__"
|
|
10574
11507
|
]);
|
|
10575
11508
|
function detectProjectLanguages(projectPath, registry) {
|
|
10576
|
-
|
|
11509
|
+
log37.debug("detecting project languages", { projectPath });
|
|
10577
11510
|
const configDetections = /* @__PURE__ */ new Map();
|
|
10578
11511
|
const fileCounts = /* @__PURE__ */ new Map();
|
|
10579
11512
|
detectConfigFiles(projectPath, configDetections);
|
|
@@ -10601,7 +11534,7 @@ function detectProjectLanguages(projectPath, registry) {
|
|
|
10601
11534
|
});
|
|
10602
11535
|
}
|
|
10603
11536
|
results.sort((a, b) => b.fileCount - a.fileCount);
|
|
10604
|
-
|
|
11537
|
+
log37.info("project languages detected", {
|
|
10605
11538
|
count: String(results.length),
|
|
10606
11539
|
languages: results.map((r) => r.languageId).join(",")
|
|
10607
11540
|
});
|
|
@@ -10612,7 +11545,7 @@ function detectConfigFiles(rootPath, configDetections) {
|
|
|
10612
11545
|
try {
|
|
10613
11546
|
entries = readdirSync(rootPath, { withFileTypes: true, encoding: "utf-8" });
|
|
10614
11547
|
} catch {
|
|
10615
|
-
|
|
11548
|
+
log37.debug("cannot read root directory for config detection", { rootPath });
|
|
10616
11549
|
return;
|
|
10617
11550
|
}
|
|
10618
11551
|
for (const entry of entries) {
|
|
@@ -10637,7 +11570,7 @@ function walkAndCountFiles(dirPath, registry, fileCounts) {
|
|
|
10637
11570
|
try {
|
|
10638
11571
|
entries = readdirSync(dirPath, { withFileTypes: true, encoding: "utf-8" });
|
|
10639
11572
|
} catch {
|
|
10640
|
-
|
|
11573
|
+
log37.debug("cannot read directory, skipping", { dirPath });
|
|
10641
11574
|
return;
|
|
10642
11575
|
}
|
|
10643
11576
|
for (const entry of entries) {
|
|
@@ -11722,176 +12655,10 @@ function applySection(existingContent, newSection) {
|
|
|
11722
12655
|
|
|
11723
12656
|
// src/core/config/config-loader.ts
|
|
11724
12657
|
init_esm_shims();
|
|
11725
|
-
|
|
11726
|
-
// src/core/config/config-schema.ts
|
|
11727
|
-
init_esm_shims();
|
|
11728
|
-
|
|
11729
|
-
// src/core/lsp/lsp-types.ts
|
|
11730
|
-
init_esm_shims();
|
|
11731
|
-
z.object({
|
|
11732
|
-
languageId: z.string(),
|
|
11733
|
-
extensions: z.array(z.string()),
|
|
11734
|
-
command: z.string(),
|
|
11735
|
-
args: z.array(z.string()),
|
|
11736
|
-
configFiles: z.array(z.string()),
|
|
11737
|
-
probeCommand: z.string().optional(),
|
|
11738
|
-
initializationOptions: z.record(z.string(), z.unknown()).optional(),
|
|
11739
|
-
settings: z.record(z.string(), z.unknown()).optional()
|
|
11740
|
-
});
|
|
11741
|
-
var LspConfigOverrideSchema = z.object({
|
|
11742
|
-
languageId: z.string(),
|
|
11743
|
-
command: z.string(),
|
|
11744
|
-
args: z.array(z.string()).default([]),
|
|
11745
|
-
extensions: z.array(z.string()).optional(),
|
|
11746
|
-
initializationOptions: z.record(z.string(), z.unknown()).optional(),
|
|
11747
|
-
settings: z.record(z.string(), z.unknown()).optional()
|
|
11748
|
-
});
|
|
11749
|
-
z.object({
|
|
11750
|
-
file: z.string(),
|
|
11751
|
-
startLine: z.int().min(0),
|
|
11752
|
-
startCharacter: z.int().min(0),
|
|
11753
|
-
endLine: z.int().min(0),
|
|
11754
|
-
endCharacter: z.int().min(0)
|
|
11755
|
-
});
|
|
11756
|
-
z.object({
|
|
11757
|
-
signature: z.string(),
|
|
11758
|
-
documentation: z.string().optional(),
|
|
11759
|
-
language: z.string().optional()
|
|
11760
|
-
});
|
|
11761
|
-
var LspDiagnosticSchema = z.object({
|
|
11762
|
-
file: z.string(),
|
|
11763
|
-
startLine: z.int().min(0),
|
|
11764
|
-
startCharacter: z.int().min(0),
|
|
11765
|
-
endLine: z.int().min(0),
|
|
11766
|
-
endCharacter: z.int().min(0),
|
|
11767
|
-
severity: z.number().int().min(1).max(4),
|
|
11768
|
-
message: z.string(),
|
|
11769
|
-
code: z.string().optional(),
|
|
11770
|
-
source: z.string().optional()
|
|
11771
|
-
});
|
|
11772
|
-
z.object({
|
|
11773
|
-
name: z.string(),
|
|
11774
|
-
kind: z.string(),
|
|
11775
|
-
file: z.string(),
|
|
11776
|
-
startLine: z.int().min(0),
|
|
11777
|
-
endLine: z.int().min(0)
|
|
11778
|
-
});
|
|
11779
|
-
var LspDocumentSymbolSchema = z.object({
|
|
11780
|
-
name: z.string(),
|
|
11781
|
-
kind: z.string(),
|
|
11782
|
-
file: z.string(),
|
|
11783
|
-
startLine: z.int().min(0),
|
|
11784
|
-
endLine: z.int().min(0),
|
|
11785
|
-
children: z.lazy(() => z.array(LspDocumentSymbolSchema)).optional()
|
|
11786
|
-
});
|
|
11787
|
-
var LspTextEditSchema = z.object({
|
|
11788
|
-
file: z.string(),
|
|
11789
|
-
startLine: z.int().min(0),
|
|
11790
|
-
startCharacter: z.int().min(0),
|
|
11791
|
-
endLine: z.int().min(0),
|
|
11792
|
-
endCharacter: z.int().min(0),
|
|
11793
|
-
newText: z.string()
|
|
11794
|
-
});
|
|
11795
|
-
var LspWorkspaceEditSchema = z.object({
|
|
11796
|
-
changes: z.array(LspTextEditSchema)
|
|
11797
|
-
});
|
|
11798
|
-
z.object({
|
|
11799
|
-
languageId: z.string(),
|
|
11800
|
-
status: z.enum(["stopped", "starting", "ready", "error"]),
|
|
11801
|
-
pid: z.number().int().optional(),
|
|
11802
|
-
error: z.string().optional()
|
|
11803
|
-
});
|
|
11804
|
-
z.object({
|
|
11805
|
-
languageId: z.string(),
|
|
11806
|
-
confidence: z.number().min(0).max(1),
|
|
11807
|
-
detectedVia: z.enum(["file_extension", "config_file", "shebang"]),
|
|
11808
|
-
fileCount: z.int().min(0),
|
|
11809
|
-
configFile: z.string().optional()
|
|
11810
|
-
});
|
|
11811
|
-
z.object({
|
|
11812
|
-
title: z.string(),
|
|
11813
|
-
kind: z.string().optional(),
|
|
11814
|
-
isPreferred: z.boolean().optional(),
|
|
11815
|
-
edit: LspWorkspaceEditSchema.optional(),
|
|
11816
|
-
diagnostics: z.array(LspDiagnosticSchema).optional()
|
|
11817
|
-
});
|
|
11818
|
-
z.object({
|
|
11819
|
-
applied: z.boolean(),
|
|
11820
|
-
filesModified: z.array(z.string()),
|
|
11821
|
-
totalEdits: z.number().int(),
|
|
11822
|
-
errors: z.array(z.string()),
|
|
11823
|
-
backups: z.map(z.string(), z.string()).optional()
|
|
11824
|
-
});
|
|
11825
|
-
|
|
11826
|
-
// src/core/config/config-schema.ts
|
|
11827
|
-
var BROWSER_PILOT_MODELS = ["claude-3.5-sonnet", "gpt-4o", "gpt-4o-mini", "o1", "o1-mini"];
|
|
11828
|
-
var ContextModeSchema = z.enum(["ultra-lean", "lean", "full"]);
|
|
11829
|
-
var ProfileFilterConfigSchema = z.enum(["core", "pro", "expert", "all"]);
|
|
11830
|
-
var BrowserAutomationConfigSchema = z.object({
|
|
11831
|
-
enabled: z.boolean().default(false),
|
|
11832
|
-
bridgeUrl: z.string().regex(/^https?:\/\//, "bridgeUrl must start with http:// or https://").default("http://127.0.0.1:9876/v1"),
|
|
11833
|
-
defaultModel: z.enum(BROWSER_PILOT_MODELS).default("claude-3.5-sonnet"),
|
|
11834
|
-
defaultCdpUrl: z.string().min(1).optional(),
|
|
11835
|
-
allowedDomains: z.array(z.string().min(1)).default([]),
|
|
11836
|
-
forbiddenCdpMethods: z.array(z.string().min(1)).default(["Browser.close"]),
|
|
11837
|
-
maxStepsDefault: z.number().int().min(1).max(100).default(25),
|
|
11838
|
-
tokenBudgetPerDay: z.number().int().nonnegative().optional()
|
|
11839
|
-
}).default({
|
|
11840
|
-
enabled: false,
|
|
11841
|
-
bridgeUrl: "http://127.0.0.1:9876/v1",
|
|
11842
|
-
defaultModel: "claude-3.5-sonnet",
|
|
11843
|
-
allowedDomains: [],
|
|
11844
|
-
forbiddenCdpMethods: ["Browser.close"],
|
|
11845
|
-
maxStepsDefault: 25
|
|
11846
|
-
});
|
|
11847
|
-
var FlowConfigSchema = z.object({
|
|
11848
|
-
/** Master switch. OFF = byte-identical legacy context behaviour. */
|
|
11849
|
-
enabled: z.boolean().default(false),
|
|
11850
|
-
/** λ_base — minimum architectural forgetting rate. */
|
|
11851
|
-
lambdaBase: z.number().min(0).default(0.15),
|
|
11852
|
-
/** α — hypofrontality accelerator (weight of Φ on λ_flow). */
|
|
11853
|
-
alpha: z.number().min(0).default(1.5),
|
|
11854
|
-
/** BFS depth used to pull distant pinned invariants back into scope. */
|
|
11855
|
-
maxDepth: z.number().int().min(0).max(6).default(3),
|
|
11856
|
-
/** Peripheral neighbours below this decayed weight are pruned (unless pinned). */
|
|
11857
|
-
weightThreshold: z.number().min(0).max(1).default(0.1),
|
|
11858
|
-
/** EMA gain per consecutive success when computing Φ. */
|
|
11859
|
-
emaGain: z.number().min(0).max(1).default(0.34),
|
|
11860
|
-
/** Multiplier applied to Φ on a failure (0 = hard reset → re-hydrate memory). */
|
|
11861
|
-
resetFactor: z.number().min(0).max(1).default(0),
|
|
11862
|
-
/** Damping fraction of `emaGain` applied on a `partial` outcome. */
|
|
11863
|
-
partialFactor: z.number().min(0).max(1).default(0.5),
|
|
11864
|
-
/** rag budget is never scaled below this fraction of baseline (long-range safety). */
|
|
11865
|
-
budgetFloorRatio: z.number().min(0).max(1).default(0.25),
|
|
11866
|
-
/** How many recent task outcomes feed Φ. */
|
|
11867
|
-
historyWindow: z.number().int().min(1).max(200).default(12),
|
|
11868
|
-
/** Node types that are never diluted. */
|
|
11869
|
-
pinnedTypes: z.array(z.string()).default(["constraint", "risk", "decision", "acceptance_criteria", "constitution", "requirement"]),
|
|
11870
|
-
/** A/B experiment: alternate flow_on/flow_off deterministically per node to measure impact. */
|
|
11871
|
-
experiment: z.object({ abEnabled: z.boolean().default(false) }).default({ abEnabled: false })
|
|
11872
|
-
});
|
|
11873
|
-
var ConfigSchema = z.object({
|
|
11874
|
-
port: z.number().int().min(1).max(65535).default(3e3),
|
|
11875
|
-
dbPath: z.string().default("workflow-graph"),
|
|
11876
|
-
basePath: z.string().optional(),
|
|
11877
|
-
contextMode: ContextModeSchema.default("lean"),
|
|
11878
|
-
profile: ProfileFilterConfigSchema.default("all"),
|
|
11879
|
-
dashboard: z.object({
|
|
11880
|
-
autoOpen: z.boolean().default(true)
|
|
11881
|
-
}).default({ autoOpen: true }),
|
|
11882
|
-
integrations: z.object({
|
|
11883
|
-
codeGraphAutoIndex: z.boolean().default(true),
|
|
11884
|
-
codeGraphReindexIntervalSec: z.number().int().min(0).default(0),
|
|
11885
|
-
lspServers: z.array(LspConfigOverrideSchema).default([]),
|
|
11886
|
-
browserAutomation: BrowserAutomationConfigSchema
|
|
11887
|
-
}).prefault({}),
|
|
11888
|
-
flow: FlowConfigSchema.prefault({})
|
|
11889
|
-
});
|
|
11890
|
-
|
|
11891
|
-
// src/core/config/config-loader.ts
|
|
12658
|
+
init_config_schema();
|
|
11892
12659
|
init_errors();
|
|
11893
12660
|
init_logger();
|
|
11894
|
-
var
|
|
12661
|
+
var log38 = createLogger({ layer: "core", source: "config-loader.ts" });
|
|
11895
12662
|
var CONFIG_FILENAME = "mcp-graph.config.json";
|
|
11896
12663
|
function loadConfig(basePath) {
|
|
11897
12664
|
const resolvedBase = basePath ?? process.cwd();
|
|
@@ -11901,13 +12668,13 @@ function loadConfig(basePath) {
|
|
|
11901
12668
|
try {
|
|
11902
12669
|
const raw = readFileSync(configPath, "utf-8").replace(/^\uFEFF/, "");
|
|
11903
12670
|
fileConfig = JSON.parse(raw);
|
|
11904
|
-
|
|
12671
|
+
log38.info(`Config loaded from ${configPath}`);
|
|
11905
12672
|
} catch (err) {
|
|
11906
12673
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11907
12674
|
throw new McpGraphError(`Invalid config at ${configPath}: ${msg}`);
|
|
11908
12675
|
}
|
|
11909
12676
|
} else {
|
|
11910
|
-
|
|
12677
|
+
log38.info("No config file found, using defaults");
|
|
11911
12678
|
}
|
|
11912
12679
|
if (process.env.MCP_PORT) {
|
|
11913
12680
|
const envPort = parseInt(process.env.MCP_PORT, 10);
|
|
@@ -11927,7 +12694,7 @@ function loadConfig(basePath) {
|
|
|
11927
12694
|
// src/core/config/ignore-templates.ts
|
|
11928
12695
|
init_esm_shims();
|
|
11929
12696
|
init_logger();
|
|
11930
|
-
var
|
|
12697
|
+
var log39 = createLogger({ layer: "core", source: "ignore-templates.ts" });
|
|
11931
12698
|
var IGNORE_TEMPLATE = `# ========================================
|
|
11932
12699
|
# LEAN CONTEXT (mcp-graph)
|
|
11933
12700
|
# Filosofia: zero auto-load, tudo on-demand via MCP
|
|
@@ -12078,21 +12845,21 @@ release-please-config.json
|
|
|
12078
12845
|
function ensureClaudeIgnore(projectDir) {
|
|
12079
12846
|
const filePath = path17__default.join(projectDir, ".claudeignore");
|
|
12080
12847
|
if (existsSync(filePath)) {
|
|
12081
|
-
|
|
12848
|
+
log39.debug(".claudeignore already exists, skipping");
|
|
12082
12849
|
return false;
|
|
12083
12850
|
}
|
|
12084
12851
|
writeFileSync(filePath, IGNORE_TEMPLATE, "utf-8");
|
|
12085
|
-
|
|
12852
|
+
log39.info(".claudeignore created with lean context template");
|
|
12086
12853
|
return true;
|
|
12087
12854
|
}
|
|
12088
12855
|
function ensureCopilotIgnore(projectDir) {
|
|
12089
12856
|
const filePath = path17__default.join(projectDir, ".copilotignore");
|
|
12090
12857
|
if (existsSync(filePath)) {
|
|
12091
|
-
|
|
12858
|
+
log39.debug(".copilotignore already exists, skipping");
|
|
12092
12859
|
return false;
|
|
12093
12860
|
}
|
|
12094
12861
|
writeFileSync(filePath, IGNORE_TEMPLATE, "utf-8");
|
|
12095
|
-
|
|
12862
|
+
log39.info(".copilotignore created with lean context template");
|
|
12096
12863
|
return true;
|
|
12097
12864
|
}
|
|
12098
12865
|
function updateIgnoreFile(filePath, label, dryRun) {
|
|
@@ -12100,7 +12867,7 @@ function updateIgnoreFile(filePath, label, dryRun) {
|
|
|
12100
12867
|
if (!exists) {
|
|
12101
12868
|
if (!dryRun) {
|
|
12102
12869
|
writeFileSync(filePath, IGNORE_TEMPLATE, "utf-8");
|
|
12103
|
-
|
|
12870
|
+
log39.info(`${label} created with lean context template`);
|
|
12104
12871
|
}
|
|
12105
12872
|
return { status: "created", message: `${label} created` };
|
|
12106
12873
|
}
|
|
@@ -12110,7 +12877,7 @@ function updateIgnoreFile(filePath, label, dryRun) {
|
|
|
12110
12877
|
}
|
|
12111
12878
|
if (!dryRun) {
|
|
12112
12879
|
writeFileSync(filePath, IGNORE_TEMPLATE, "utf-8");
|
|
12113
|
-
|
|
12880
|
+
log39.info(`${label} updated to latest template`);
|
|
12114
12881
|
}
|
|
12115
12882
|
return { status: "updated", message: `${label} updated` };
|
|
12116
12883
|
}
|
|
@@ -12787,7 +13554,7 @@ init_registry();
|
|
|
12787
13554
|
// src/core/atomic-files/writer-markdown.ts
|
|
12788
13555
|
init_esm_shims();
|
|
12789
13556
|
init_logger();
|
|
12790
|
-
var
|
|
13557
|
+
var log40 = createLogger({ layer: "core", source: "writer-markdown.ts" });
|
|
12791
13558
|
var markerStart2 = (id) => `<!-- MCP-GRAPH:MANAGED-START:${id} -->`;
|
|
12792
13559
|
var markerEnd2 = (id) => `<!-- MCP-GRAPH:MANAGED-END:${id} -->`;
|
|
12793
13560
|
function extractManagedBlock(content, fileId) {
|
|
@@ -12849,7 +13616,7 @@ async function write(file, mode) {
|
|
|
12849
13616
|
const existingBlock = extractManagedBlock(current, fileId);
|
|
12850
13617
|
const tampered = existingBlock !== null && detectTampering(filePath, fileId, existingBlock);
|
|
12851
13618
|
if (tampered) {
|
|
12852
|
-
|
|
13619
|
+
log40.warn("managed block tampered \u2014 system reconquering", { fileId, filePath });
|
|
12853
13620
|
fs.writeFileSync(filePath + ".user-modified.bak", current, "utf8");
|
|
12854
13621
|
}
|
|
12855
13622
|
if (!tampered && existingBlock === managedContent) {
|
|
@@ -12887,7 +13654,7 @@ async function atomicWrite(filePath, content) {
|
|
|
12887
13654
|
try {
|
|
12888
13655
|
fs.unlinkSync(tmp);
|
|
12889
13656
|
} catch (e) {
|
|
12890
|
-
|
|
13657
|
+
log40.debug("intentional swallow", { error: e, reason: "tmp file already gone, cleanup not needed" });
|
|
12891
13658
|
}
|
|
12892
13659
|
throw err;
|
|
12893
13660
|
}
|
|
@@ -12915,7 +13682,7 @@ async function runAtomicWrites(mode) {
|
|
|
12915
13682
|
}
|
|
12916
13683
|
|
|
12917
13684
|
// src/cli/commands/init-cmd.ts
|
|
12918
|
-
var
|
|
13685
|
+
var log41 = createLogger({ layer: "cli", source: "init.ts" });
|
|
12919
13686
|
var LEVEL_ICON = { ok: "\u2713", warning: "\u26A0", error: "\u2717" };
|
|
12920
13687
|
async function runInitOrchestration(opts, deps) {
|
|
12921
13688
|
const { dir, skipNeural, noServe, port } = opts;
|
|
@@ -13028,7 +13795,7 @@ function initCommand() {
|
|
|
13028
13795
|
const dir = path17__default.resolve(opts.dir);
|
|
13029
13796
|
const port = parseInt(opts.port, 10);
|
|
13030
13797
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
13031
|
-
|
|
13798
|
+
log41.error("Invalid port number", { port: opts.port });
|
|
13032
13799
|
process.exitCode = 1;
|
|
13033
13800
|
return;
|
|
13034
13801
|
}
|
|
@@ -13046,7 +13813,7 @@ function initCommand() {
|
|
|
13046
13813
|
out("\nPronto. Execute `mcp-graph serve` para iniciar o servidor.");
|
|
13047
13814
|
}
|
|
13048
13815
|
} catch (error) {
|
|
13049
|
-
|
|
13816
|
+
log41.error("Init failed", { error: getErrorMessage(error) });
|
|
13050
13817
|
process.exitCode = 1;
|
|
13051
13818
|
}
|
|
13052
13819
|
});
|
|
@@ -13111,7 +13878,7 @@ function readDaemonMeta(stateDir) {
|
|
|
13111
13878
|
|
|
13112
13879
|
// src/core/daemon/daemon-reaper.ts
|
|
13113
13880
|
init_logger();
|
|
13114
|
-
var
|
|
13881
|
+
var log43 = createLogger({ layer: "core", source: "daemon-reaper" });
|
|
13115
13882
|
function defaultDaemonRoot(home = os.homedir()) {
|
|
13116
13883
|
return path17__default.join(home, ".mcp-graph");
|
|
13117
13884
|
}
|
|
@@ -13150,7 +13917,7 @@ function reapDaemons(options = {}) {
|
|
|
13150
13917
|
try {
|
|
13151
13918
|
kill(lock.pid);
|
|
13152
13919
|
} catch (err) {
|
|
13153
|
-
|
|
13920
|
+
log43.debug("intentional-swallow", {
|
|
13154
13921
|
error: String(err),
|
|
13155
13922
|
reason: "process vanished between liveness probe and signal \u2014 treat as already reaped"
|
|
13156
13923
|
});
|
|
@@ -13180,7 +13947,7 @@ function reapDaemons(options = {}) {
|
|
|
13180
13947
|
try {
|
|
13181
13948
|
fs__default.rmSync(stateDir, { recursive: true, force: true });
|
|
13182
13949
|
} catch (err) {
|
|
13183
|
-
|
|
13950
|
+
log43.debug("intentional-swallow", {
|
|
13184
13951
|
error: String(err),
|
|
13185
13952
|
reason: "state dir removal hit a permission error or race \u2014 next reaper run retries"
|
|
13186
13953
|
});
|
|
@@ -13200,14 +13967,14 @@ function reapDaemons(options = {}) {
|
|
|
13200
13967
|
|
|
13201
13968
|
// src/cli/commands/daemon-cmd.ts
|
|
13202
13969
|
init_logger();
|
|
13203
|
-
var
|
|
13970
|
+
var log44 = createLogger({ layer: "cli", source: "daemon.ts" });
|
|
13204
13971
|
function output12(msg) {
|
|
13205
13972
|
process.stdout.write(msg + "\n");
|
|
13206
13973
|
}
|
|
13207
13974
|
function daemonCommand() {
|
|
13208
13975
|
const cmd = new Command("daemon").description("Inspect and clean up mcp-graph daemons");
|
|
13209
13976
|
cmd.command("prune").description("Kill orphaned daemons (workspace gone) and remove stale state dirs").option("--dry-run", "Show what would be reaped without killing or deleting", false).action((opts) => {
|
|
13210
|
-
|
|
13977
|
+
log44.info("cli:daemon:prune", { dryRun: opts.dryRun });
|
|
13211
13978
|
const report = reapDaemons({ dryRun: opts.dryRun });
|
|
13212
13979
|
const prefix = opts.dryRun ? "[dry-run] " : "";
|
|
13213
13980
|
for (const a of report.actions) {
|
|
@@ -13279,7 +14046,7 @@ function formatProviderReport(report) {
|
|
|
13279
14046
|
// src/cli/commands/doctor-cmd.ts
|
|
13280
14047
|
init_errors();
|
|
13281
14048
|
init_logger();
|
|
13282
|
-
var
|
|
14049
|
+
var log45 = createLogger({ layer: "cli", source: "doctor.ts" });
|
|
13283
14050
|
function output13(msg) {
|
|
13284
14051
|
process.stdout.write(msg + "\n");
|
|
13285
14052
|
}
|
|
@@ -13334,7 +14101,7 @@ function doctorCommand() {
|
|
|
13334
14101
|
process.exit(1);
|
|
13335
14102
|
}
|
|
13336
14103
|
} catch (err) {
|
|
13337
|
-
|
|
14104
|
+
log45.error(`Doctor failed: ${getErrorMessage(err)}`);
|
|
13338
14105
|
process.exit(1);
|
|
13339
14106
|
}
|
|
13340
14107
|
});
|
|
@@ -13346,7 +14113,7 @@ init_esm_shims();
|
|
|
13346
14113
|
// src/core/autonomy/shadow-branch.ts
|
|
13347
14114
|
init_esm_shims();
|
|
13348
14115
|
init_logger();
|
|
13349
|
-
var
|
|
14116
|
+
var log46 = createLogger({ layer: "core", source: "shadow-branch.ts" });
|
|
13350
14117
|
function parseShadowTimestamp(branchName) {
|
|
13351
14118
|
const match = /-(\d{10,})$/.exec(branchName);
|
|
13352
14119
|
if (!match) return null;
|
|
@@ -13388,7 +14155,7 @@ function pruneOrphanWorktrees(options) {
|
|
|
13388
14155
|
).toString();
|
|
13389
14156
|
branches = out2.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
13390
14157
|
} catch (err) {
|
|
13391
|
-
|
|
14158
|
+
log46.debug("shadow-branch:prune:list-failed", { error: String(err) });
|
|
13392
14159
|
}
|
|
13393
14160
|
const wtMap = branches.length > 0 ? listShadowWorktrees(execOpts) : /* @__PURE__ */ new Map();
|
|
13394
14161
|
for (const branch of branches) {
|
|
@@ -13400,34 +14167,34 @@ function pruneOrphanWorktrees(options) {
|
|
|
13400
14167
|
execSync(`git worktree remove --force --force ${wtPath}`, execOpts);
|
|
13401
14168
|
reapedWorktrees += 1;
|
|
13402
14169
|
} catch (err) {
|
|
13403
|
-
|
|
14170
|
+
log46.debug("shadow-branch:prune:wt-remove-failed", { branch, wtPath, error: String(err) });
|
|
13404
14171
|
}
|
|
13405
14172
|
}
|
|
13406
14173
|
try {
|
|
13407
14174
|
execSync(`git branch -D ${branch}`, execOpts);
|
|
13408
14175
|
reapedBranches += 1;
|
|
13409
14176
|
} catch (err) {
|
|
13410
|
-
|
|
14177
|
+
log46.debug("shadow-branch:prune:branch-delete-failed", { branch, error: String(err) });
|
|
13411
14178
|
}
|
|
13412
14179
|
}
|
|
13413
14180
|
try {
|
|
13414
|
-
const
|
|
14181
|
+
const output16 = execSync("git worktree prune --verbose", execOpts).toString();
|
|
13415
14182
|
if (reapedBranches > 0 || reapedWorktrees > 0) {
|
|
13416
|
-
|
|
14183
|
+
log46.info("shadow-branch:prune-ok", { reapedBranches, reapedWorktrees, ttlMs });
|
|
13417
14184
|
} else {
|
|
13418
|
-
|
|
14185
|
+
log46.debug("shadow-branch:prune-ok", { reapedBranches, reapedWorktrees, output: output16 });
|
|
13419
14186
|
}
|
|
13420
|
-
return { pruned: true, reapedBranches, reapedWorktrees, output:
|
|
14187
|
+
return { pruned: true, reapedBranches, reapedWorktrees, output: output16 };
|
|
13421
14188
|
} catch (err) {
|
|
13422
14189
|
const error = String(err);
|
|
13423
|
-
|
|
14190
|
+
log46.debug("shadow-branch:prune-failed", { error });
|
|
13424
14191
|
return { pruned: false, reapedBranches, reapedWorktrees, error };
|
|
13425
14192
|
}
|
|
13426
14193
|
}
|
|
13427
14194
|
|
|
13428
14195
|
// src/cli/commands/gc-cmd.ts
|
|
13429
14196
|
init_logger();
|
|
13430
|
-
var
|
|
14197
|
+
var log47 = createLogger({ layer: "cli", source: "gc.ts" });
|
|
13431
14198
|
function output14(msg) {
|
|
13432
14199
|
process.stdout.write(msg + "\n");
|
|
13433
14200
|
}
|
|
@@ -13435,7 +14202,7 @@ function gcCommand() {
|
|
|
13435
14202
|
return new Command("gc").description("Garbage-collect orphan ai-shadow/* worktrees and branches").option("-d, --dir <dir>", "Project directory (git root)", process.cwd()).option("--ttl <minutes>", "Only reap branches older than N minutes (0 = all)", "0").action((opts) => {
|
|
13436
14203
|
const ttlMinutes = parseInt(opts.ttl, 10);
|
|
13437
14204
|
const ttlMs = Number.isFinite(ttlMinutes) && ttlMinutes > 0 ? ttlMinutes * 60 * 1e3 : 0;
|
|
13438
|
-
|
|
14205
|
+
log47.info("cli:gc:start", { dir: opts.dir, ttlMs });
|
|
13439
14206
|
const result = pruneOrphanWorktrees({ cwd: opts.dir, ttlMs });
|
|
13440
14207
|
if (result.pruned) {
|
|
13441
14208
|
output14(`gc: reaped ${result.reapedBranches} branches, ${result.reapedWorktrees} worktrees`);
|
|
@@ -13446,6 +14213,48 @@ function gcCommand() {
|
|
|
13446
14213
|
});
|
|
13447
14214
|
}
|
|
13448
14215
|
|
|
14216
|
+
// src/cli/commands/skill-cmd.ts
|
|
14217
|
+
init_esm_shims();
|
|
14218
|
+
init_skill_registry();
|
|
14219
|
+
function output15(msg) {
|
|
14220
|
+
process.stdout.write(msg + "\n");
|
|
14221
|
+
}
|
|
14222
|
+
function skillCommand() {
|
|
14223
|
+
const cmd = new Command("skill").description("Lista e exibe skills (instru\xE7\xF5es para agentes)");
|
|
14224
|
+
cmd.command("list").description("Lista as skills dispon\xEDveis (src/skills, .agents/skills, .claude/skills)").option("-p, --phase <fase>", "Ordena/filtra pela fase do ciclo (ANALYZE, IMPLEMENT, \u2026)").option("-d, --dir <dir>", "Raiz do projeto", process.cwd()).action((opts) => {
|
|
14225
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14226
|
+
let count = 0;
|
|
14227
|
+
for (const root of defaultSkillRoots(opts.dir)) {
|
|
14228
|
+
const { skills } = listSkills(root, opts.phase);
|
|
14229
|
+
for (const s of skills) {
|
|
14230
|
+
if (seen.has(s.name)) continue;
|
|
14231
|
+
seen.add(s.name);
|
|
14232
|
+
count += 1;
|
|
14233
|
+
output15(`${s.name.padEnd(28)} [${s.category}] ${s.description}`);
|
|
14234
|
+
}
|
|
14235
|
+
}
|
|
14236
|
+
if (count === 0) output15("Nenhuma skill encontrada.");
|
|
14237
|
+
else output15(`
|
|
14238
|
+
${count} skill(s).`);
|
|
14239
|
+
});
|
|
14240
|
+
cmd.command("show <nome>").description("Imprime as instru\xE7\xF5es completas de uma skill").option("-d, --dir <dir>", "Raiz do projeto", process.cwd()).action((nome, opts) => {
|
|
14241
|
+
for (const root of defaultSkillRoots(opts.dir)) {
|
|
14242
|
+
const found = invokeSkill(root, nome);
|
|
14243
|
+
if (found) {
|
|
14244
|
+
output15(`=== ${found.name} ===`);
|
|
14245
|
+
output15(`[${found.category}] ${found.description}`);
|
|
14246
|
+
if (found.phases.length > 0) output15(`fases: ${found.phases.join(", ")}`);
|
|
14247
|
+
output15("");
|
|
14248
|
+
output15(found.body);
|
|
14249
|
+
return;
|
|
14250
|
+
}
|
|
14251
|
+
}
|
|
14252
|
+
output15(`Skill n\xE3o encontrada: ${nome}. Tente 'skill list'.`);
|
|
14253
|
+
process.exitCode = 1;
|
|
14254
|
+
});
|
|
14255
|
+
return cmd;
|
|
14256
|
+
}
|
|
14257
|
+
|
|
13449
14258
|
// src/cli/index.ts
|
|
13450
14259
|
var program = new Command();
|
|
13451
14260
|
program.name("agent-graph-flow").description(PROMISE).version(VERSION, "-v, --version");
|
|
@@ -13466,6 +14275,7 @@ program.addCommand(initCommand());
|
|
|
13466
14275
|
program.addCommand(daemonCommand());
|
|
13467
14276
|
program.addCommand(doctorCommand());
|
|
13468
14277
|
program.addCommand(gcCommand());
|
|
14278
|
+
program.addCommand(skillCommand());
|
|
13469
14279
|
function shouldLaunchTui() {
|
|
13470
14280
|
const noArgs = process.argv.length <= 2;
|
|
13471
14281
|
const isTty = Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|