@mcp-graph-workflow/agent-graph-flow 0.6.0 → 0.8.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 +357 -13
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2890,6 +2890,28 @@ var init_migrations = __esm({
|
|
|
2890
2890
|
ON flow_metrics(project_id, created_at DESC);
|
|
2891
2891
|
CREATE INDEX IF NOT EXISTS idx_flow_metrics_mode
|
|
2892
2892
|
ON flow_metrics(mode, created_at DESC);
|
|
2893
|
+
`
|
|
2894
|
+
},
|
|
2895
|
+
{
|
|
2896
|
+
version: 97,
|
|
2897
|
+
// Reuso determinístico (Épico R): cache de artefatos (edits gerados e verdes)
|
|
2898
|
+
// por assinatura de task. Quando a mesma assinatura reaparece, o loop reusa os
|
|
2899
|
+
// edits sem chamar o modelo (~0 tokens). Pairs com src/core/reuse/*.
|
|
2900
|
+
description: "artifact_cache \u2014 reuso determin\xEDstico de edits por task-signature",
|
|
2901
|
+
sql: `
|
|
2902
|
+
CREATE TABLE IF NOT EXISTS artifact_cache (
|
|
2903
|
+
id TEXT PRIMARY KEY,
|
|
2904
|
+
signature TEXT NOT NULL,
|
|
2905
|
+
node_id TEXT,
|
|
2906
|
+
applied_edits TEXT NOT NULL,
|
|
2907
|
+
approach_summary TEXT,
|
|
2908
|
+
model TEXT,
|
|
2909
|
+
outcome TEXT NOT NULL,
|
|
2910
|
+
created_at INTEGER NOT NULL,
|
|
2911
|
+
UNIQUE(signature, outcome)
|
|
2912
|
+
);
|
|
2913
|
+
CREATE INDEX IF NOT EXISTS idx_artifact_cache_signature
|
|
2914
|
+
ON artifact_cache(signature, created_at DESC);
|
|
2893
2915
|
`
|
|
2894
2916
|
}
|
|
2895
2917
|
];
|
|
@@ -7094,8 +7116,8 @@ var init_implementation_executor = __esm({
|
|
|
7094
7116
|
};
|
|
7095
7117
|
defaultRunner = (command, cwd) => {
|
|
7096
7118
|
try {
|
|
7097
|
-
const
|
|
7098
|
-
return { exitCode: 0, output:
|
|
7119
|
+
const output18 = execSync(command, { cwd, encoding: "utf8", stdio: "pipe" });
|
|
7120
|
+
return { exitCode: 0, output: output18 };
|
|
7099
7121
|
} catch (err) {
|
|
7100
7122
|
const e = err;
|
|
7101
7123
|
return {
|
|
@@ -7255,9 +7277,11 @@ function defaultSleep(ms) {
|
|
|
7255
7277
|
function buildInitialPrompt(node, opts = {}) {
|
|
7256
7278
|
const repoMapBlock = opts.repoMap && opts.repoMap.length > 0 ? [`Contexto do reposit\xF3rio (refer\xEAncia, n\xE3o reescreva o que j\xE1 existe):`, opts.repoMap, ""] : [];
|
|
7257
7279
|
const flowBlock = opts.flowContext && opts.flowContext.length > 0 ? [opts.flowContext, ""] : [];
|
|
7280
|
+
const scaffoldBlock = opts.scaffoldHint && opts.scaffoldHint.length > 0 ? [`Scaffold de refer\xEAncia (task semelhante j\xE1 resolvida \u2014 reaproveite o que servir):`, opts.scaffoldHint, ""] : [];
|
|
7258
7281
|
return [
|
|
7259
7282
|
...repoMapBlock,
|
|
7260
7283
|
...flowBlock,
|
|
7284
|
+
...scaffoldBlock,
|
|
7261
7285
|
`Implemente a task "${node.title}" (id: ${node.id}) seguindo TDD.`,
|
|
7262
7286
|
"Responda APENAS com um bloco ```json. H\xE1 DOIS mecanismos:",
|
|
7263
7287
|
'- "edits" (PREFIRA \u2014 economia de token): [{ "path", "oldString", "newString", "replaceAll"? }].',
|
|
@@ -7286,8 +7310,25 @@ async function attemptImplementation(deps, options) {
|
|
|
7286
7310
|
const sleep2 = deps.sleep ?? defaultSleep;
|
|
7287
7311
|
let lastResult;
|
|
7288
7312
|
let lastError;
|
|
7313
|
+
const reuse = options.reuse;
|
|
7314
|
+
if (reuse?.kind === "exact") {
|
|
7315
|
+
const result = await deps.execute({ edits: reuse.edits });
|
|
7316
|
+
if (result.testPassed === true) {
|
|
7317
|
+
log25.info("Reuso exato verde \u2014 0 tokens de modelo", { node: options.node.id, sourceId: reuse.sourceId });
|
|
7318
|
+
return { success: true, attempts: 1, lastResult: result, appliedEdits: reuse.edits, reused: "exact" };
|
|
7319
|
+
}
|
|
7320
|
+
lastResult = result;
|
|
7321
|
+
lastError = result.testOutput;
|
|
7322
|
+
log25.warn("Reuso exato vermelho \u2014 caindo para gera\xE7\xE3o", { node: options.node.id });
|
|
7323
|
+
}
|
|
7324
|
+
const scaffoldHint = reuse?.kind === "scaffold" ? reuse.edits.map((e) => `\u2500\u2500 ${e.path} \u2500\u2500
|
|
7325
|
+
+ ${e.newString}`).join("\n") : void 0;
|
|
7289
7326
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
7290
|
-
const prompt = attempt === 1 || !lastResult ? buildInitialPrompt(options.node, {
|
|
7327
|
+
const prompt = attempt === 1 || !lastResult ? buildInitialPrompt(options.node, {
|
|
7328
|
+
repoMap: options.repoMap,
|
|
7329
|
+
flowContext: options.flowContext,
|
|
7330
|
+
scaffoldHint
|
|
7331
|
+
}) : buildRetryPrompt(options.node, lastResult, maxFeedbackChars);
|
|
7291
7332
|
let text;
|
|
7292
7333
|
try {
|
|
7293
7334
|
text = await deps.generate(prompt);
|
|
@@ -7328,7 +7369,13 @@ async function attemptImplementation(deps, options) {
|
|
|
7328
7369
|
oldString: e.oldString,
|
|
7329
7370
|
newString: e.newString
|
|
7330
7371
|
}));
|
|
7331
|
-
return {
|
|
7372
|
+
return {
|
|
7373
|
+
success: true,
|
|
7374
|
+
attempts: attempt,
|
|
7375
|
+
lastResult,
|
|
7376
|
+
appliedEdits,
|
|
7377
|
+
...reuse?.kind === "scaffold" ? { reused: "scaffold" } : {}
|
|
7378
|
+
};
|
|
7332
7379
|
}
|
|
7333
7380
|
lastError = lastResult.testOutput;
|
|
7334
7381
|
log25.warn("Testes vermelhos", { attempt, node: options.node.id });
|
|
@@ -8653,6 +8700,97 @@ var init_flow_compact = __esm({
|
|
|
8653
8700
|
log28 = createLogger({ layer: "core", source: "flow-compact.ts" });
|
|
8654
8701
|
}
|
|
8655
8702
|
});
|
|
8703
|
+
function norm2(text) {
|
|
8704
|
+
return text.trim().toLowerCase().replace(/\s+/g, " ");
|
|
8705
|
+
}
|
|
8706
|
+
function normSorted(items) {
|
|
8707
|
+
return (items ?? []).map(norm2).filter((s) => s.length > 0).sort();
|
|
8708
|
+
}
|
|
8709
|
+
function computeTaskSignature(input) {
|
|
8710
|
+
const canonical = {
|
|
8711
|
+
title: norm2(input.title),
|
|
8712
|
+
type: norm2(input.type ?? "task"),
|
|
8713
|
+
ac: normSorted(input.acceptanceCriteria),
|
|
8714
|
+
tags: normSorted(input.tags)
|
|
8715
|
+
};
|
|
8716
|
+
return createHash("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
8717
|
+
}
|
|
8718
|
+
var init_task_signature = __esm({
|
|
8719
|
+
"src/core/reuse/task-signature.ts"() {
|
|
8720
|
+
init_esm_shims();
|
|
8721
|
+
}
|
|
8722
|
+
});
|
|
8723
|
+
|
|
8724
|
+
// src/core/reuse/artifact-cache.ts
|
|
8725
|
+
function recordArtifact(db, row) {
|
|
8726
|
+
db.prepare(
|
|
8727
|
+
`INSERT OR IGNORE INTO artifact_cache
|
|
8728
|
+
(id, signature, node_id, applied_edits, approach_summary, model, outcome, created_at)
|
|
8729
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
8730
|
+
).run(
|
|
8731
|
+
row.id,
|
|
8732
|
+
row.signature,
|
|
8733
|
+
row.nodeId ?? null,
|
|
8734
|
+
JSON.stringify(row.appliedEdits),
|
|
8735
|
+
row.approachSummary ?? null,
|
|
8736
|
+
row.model ?? null,
|
|
8737
|
+
row.outcome,
|
|
8738
|
+
row.createdAt
|
|
8739
|
+
);
|
|
8740
|
+
}
|
|
8741
|
+
function parseEdits(json) {
|
|
8742
|
+
try {
|
|
8743
|
+
const parsed = JSON.parse(json);
|
|
8744
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
8745
|
+
} catch {
|
|
8746
|
+
return [];
|
|
8747
|
+
}
|
|
8748
|
+
}
|
|
8749
|
+
function queryBySignature(db, signature) {
|
|
8750
|
+
const rows = db.prepare(
|
|
8751
|
+
`SELECT id, signature, node_id, applied_edits, approach_summary, model, outcome, created_at
|
|
8752
|
+
FROM artifact_cache
|
|
8753
|
+
WHERE signature = ?
|
|
8754
|
+
ORDER BY created_at DESC`
|
|
8755
|
+
).all(signature);
|
|
8756
|
+
return rows.map((r) => ({
|
|
8757
|
+
id: r.id,
|
|
8758
|
+
signature: r.signature,
|
|
8759
|
+
nodeId: r.node_id ?? void 0,
|
|
8760
|
+
appliedEdits: parseEdits(r.applied_edits),
|
|
8761
|
+
approachSummary: r.approach_summary ?? void 0,
|
|
8762
|
+
model: r.model ?? void 0,
|
|
8763
|
+
outcome: r.outcome,
|
|
8764
|
+
createdAt: r.created_at
|
|
8765
|
+
}));
|
|
8766
|
+
}
|
|
8767
|
+
var init_artifact_cache = __esm({
|
|
8768
|
+
"src/core/reuse/artifact-cache.ts"() {
|
|
8769
|
+
init_esm_shims();
|
|
8770
|
+
}
|
|
8771
|
+
});
|
|
8772
|
+
|
|
8773
|
+
// src/core/reuse/resolve-reuse.ts
|
|
8774
|
+
function resolveReuse(db, signature, deps = {}, options = {}) {
|
|
8775
|
+
const exact = queryBySignature(db, signature).find((r) => r.outcome === "success");
|
|
8776
|
+
if (exact && exact.appliedEdits.length > 0) {
|
|
8777
|
+
return { kind: "exact", edits: exact.appliedEdits, sourceId: exact.id };
|
|
8778
|
+
}
|
|
8779
|
+
const threshold = options.scaffoldThreshold ?? DEFAULT_SCAFFOLD_THRESHOLD;
|
|
8780
|
+
const neighbor = deps.findNeighbor?.(signature);
|
|
8781
|
+
if (neighbor && neighbor.similarity >= threshold && neighbor.edits.length > 0) {
|
|
8782
|
+
return { kind: "scaffold", edits: neighbor.edits, sourceId: neighbor.sourceId, similarity: neighbor.similarity };
|
|
8783
|
+
}
|
|
8784
|
+
return { kind: "none" };
|
|
8785
|
+
}
|
|
8786
|
+
var DEFAULT_SCAFFOLD_THRESHOLD;
|
|
8787
|
+
var init_resolve_reuse = __esm({
|
|
8788
|
+
"src/core/reuse/resolve-reuse.ts"() {
|
|
8789
|
+
init_esm_shims();
|
|
8790
|
+
init_artifact_cache();
|
|
8791
|
+
DEFAULT_SCAFFOLD_THRESHOLD = 0.85;
|
|
8792
|
+
}
|
|
8793
|
+
});
|
|
8656
8794
|
|
|
8657
8795
|
// src/cli/shared/live-implement.ts
|
|
8658
8796
|
function buildLiveImplement(options) {
|
|
@@ -8689,6 +8827,17 @@ function buildLiveImplement(options) {
|
|
|
8689
8827
|
` [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`
|
|
8690
8828
|
);
|
|
8691
8829
|
}
|
|
8830
|
+
const fullNode = store2.getNodeById?.(node.id);
|
|
8831
|
+
const signature = computeTaskSignature({
|
|
8832
|
+
title: node.title,
|
|
8833
|
+
acceptanceCriteria: fullNode?.acceptanceCriteria,
|
|
8834
|
+
type: fullNode?.type,
|
|
8835
|
+
tags: fullNode?.tags
|
|
8836
|
+
});
|
|
8837
|
+
const reuse = resolveReuse(store2.getDb(), signature);
|
|
8838
|
+
if (reuse.kind !== "none") {
|
|
8839
|
+
onLog?.(` [reuse] ${reuse.kind} (sig ${signature.slice(0, 8)}\u2026) \u2192 ${reuse.kind === "exact" ? "0 tok se verde" : "scaffold no prompt"}`);
|
|
8840
|
+
}
|
|
8692
8841
|
const outcome = await attemptImplementation(
|
|
8693
8842
|
{
|
|
8694
8843
|
generate: async (prompt) => {
|
|
@@ -8704,8 +8853,9 @@ function buildLiveImplement(options) {
|
|
|
8704
8853
|
},
|
|
8705
8854
|
execute: (plan) => executePlan(plan, { workspaceDir: dir, defaultTestCommand: testCmd, runCommand: guardedRunner })
|
|
8706
8855
|
},
|
|
8707
|
-
{ node, maxAttempts, repoMap, flowContext }
|
|
8856
|
+
{ node, maxAttempts, repoMap, flowContext, reuse }
|
|
8708
8857
|
);
|
|
8858
|
+
if (outcome.reused === "exact") onLog?.(` [reuse] exact verde \u2014 0 tokens de modelo`);
|
|
8709
8859
|
const files = outcome.lastResult?.applied.length ?? 0;
|
|
8710
8860
|
const task = ledger.byTask(node.id);
|
|
8711
8861
|
onLog?.(
|
|
@@ -8729,6 +8879,21 @@ function buildLiveImplement(options) {
|
|
|
8729
8879
|
});
|
|
8730
8880
|
} catch {
|
|
8731
8881
|
}
|
|
8882
|
+
if (outcome.success && outcome.appliedEdits && outcome.appliedEdits.length > 0) {
|
|
8883
|
+
try {
|
|
8884
|
+
recordArtifact(store2.getDb(), {
|
|
8885
|
+
id: generateId("art"),
|
|
8886
|
+
signature,
|
|
8887
|
+
nodeId: node.id,
|
|
8888
|
+
appliedEdits: outcome.appliedEdits,
|
|
8889
|
+
approachSummary: buildApproachSummary(outcome.lastResult?.applied ?? [], []),
|
|
8890
|
+
model: client.modelFor("implement"),
|
|
8891
|
+
outcome: "success",
|
|
8892
|
+
createdAt: Date.now()
|
|
8893
|
+
});
|
|
8894
|
+
} catch {
|
|
8895
|
+
}
|
|
8896
|
+
}
|
|
8732
8897
|
return outcome.success;
|
|
8733
8898
|
};
|
|
8734
8899
|
return { implement, repoSymbolCount: repoSymbols.length };
|
|
@@ -8748,6 +8913,9 @@ var init_live_implement = __esm({
|
|
|
8748
8913
|
init_flow_compact();
|
|
8749
8914
|
init_episodic_outcomes_store();
|
|
8750
8915
|
init_id();
|
|
8916
|
+
init_task_signature();
|
|
8917
|
+
init_resolve_reuse();
|
|
8918
|
+
init_artifact_cache();
|
|
8751
8919
|
REPO_MAP_TOKEN_BUDGET = 1e3;
|
|
8752
8920
|
}
|
|
8753
8921
|
});
|
|
@@ -9856,15 +10024,15 @@ function meanPoolAndNormalize(data, validTokens, dim) {
|
|
|
9856
10024
|
embedding[dVar] += data[tVar * dim + dVar];
|
|
9857
10025
|
}
|
|
9858
10026
|
}
|
|
9859
|
-
let
|
|
10027
|
+
let norm3 = 0;
|
|
9860
10028
|
for (let dVar = 0; dVar < dim; dVar++) {
|
|
9861
10029
|
embedding[dVar] /= validTokens;
|
|
9862
|
-
|
|
10030
|
+
norm3 += embedding[dVar] * embedding[dVar];
|
|
9863
10031
|
}
|
|
9864
|
-
|
|
9865
|
-
if (
|
|
10032
|
+
norm3 = Math.sqrt(norm3);
|
|
10033
|
+
if (norm3 > 0) {
|
|
9866
10034
|
for (let dVar = 0; dVar < dim; dVar++) {
|
|
9867
|
-
embedding[dVar] /=
|
|
10035
|
+
embedding[dVar] /= norm3;
|
|
9868
10036
|
}
|
|
9869
10037
|
}
|
|
9870
10038
|
return embedding;
|
|
@@ -14578,13 +14746,13 @@ function pruneOrphanWorktrees(options) {
|
|
|
14578
14746
|
}
|
|
14579
14747
|
}
|
|
14580
14748
|
try {
|
|
14581
|
-
const
|
|
14749
|
+
const output18 = execSync("git worktree prune --verbose", execOpts).toString();
|
|
14582
14750
|
if (reapedBranches > 0 || reapedWorktrees > 0) {
|
|
14583
14751
|
log46.info("shadow-branch:prune-ok", { reapedBranches, reapedWorktrees, ttlMs });
|
|
14584
14752
|
} else {
|
|
14585
|
-
log46.debug("shadow-branch:prune-ok", { reapedBranches, reapedWorktrees, output:
|
|
14753
|
+
log46.debug("shadow-branch:prune-ok", { reapedBranches, reapedWorktrees, output: output18 });
|
|
14586
14754
|
}
|
|
14587
|
-
return { pruned: true, reapedBranches, reapedWorktrees, output:
|
|
14755
|
+
return { pruned: true, reapedBranches, reapedWorktrees, output: output18 };
|
|
14588
14756
|
} catch (err) {
|
|
14589
14757
|
const error = String(err);
|
|
14590
14758
|
log46.debug("shadow-branch:prune-failed", { error });
|
|
@@ -14655,6 +14823,181 @@ ${count} skill(s).`);
|
|
|
14655
14823
|
return cmd;
|
|
14656
14824
|
}
|
|
14657
14825
|
|
|
14826
|
+
// src/cli/commands/principles-cmd.ts
|
|
14827
|
+
init_esm_shims();
|
|
14828
|
+
|
|
14829
|
+
// src/core/doctrine/principles.ts
|
|
14830
|
+
init_esm_shims();
|
|
14831
|
+
var PRINCIPLES = Object.freeze([
|
|
14832
|
+
// ── Promessa (o filtro de toda decisão) ──────────────────
|
|
14833
|
+
{
|
|
14834
|
+
id: "three-pillars",
|
|
14835
|
+
title: "Tr\xEAs pilares",
|
|
14836
|
+
category: "promise",
|
|
14837
|
+
statement: "R\xE1pido \xB7 best-practice SWE \xB7 custo de token brutalmente baixo. O que n\xE3o serve aos tr\xEAs, n\xE3o entra.",
|
|
14838
|
+
rationale: "Uma promessa \xFAnica alinha cada decis\xE3o de produto; remove ambiguidade sobre o que merece existir."
|
|
14839
|
+
},
|
|
14840
|
+
// ── TDD ──────────────────────────────────────────────────
|
|
14841
|
+
{
|
|
14842
|
+
id: "tdd-red-green-refactor",
|
|
14843
|
+
title: "TDD Red \u2192 Green \u2192 Refactor",
|
|
14844
|
+
category: "tdd",
|
|
14845
|
+
statement: "Sem teste, sem c\xF3digo. Escreva o teste que falha (Red), fa\xE7a passar (Green), ent\xE3o refatore.",
|
|
14846
|
+
rationale: "O teste primeiro define o contrato e elimina retrabalho \u2014 o anti-vibe-coding por excel\xEAncia."
|
|
14847
|
+
},
|
|
14848
|
+
{
|
|
14849
|
+
id: "ac-as-contract",
|
|
14850
|
+
title: "AC como contrato",
|
|
14851
|
+
category: "tdd",
|
|
14852
|
+
statement: "Crit\xE9rios de aceita\xE7\xE3o Given/When/Then s\xE3o o contrato; o DoD precisa passar antes de `done`.",
|
|
14853
|
+
rationale: "AC test\xE1vel transforma inten\xE7\xE3o em verifica\xE7\xE3o objetiva \u2014 nada \xE9 'pronto' por opini\xE3o."
|
|
14854
|
+
},
|
|
14855
|
+
// ── Clean Code ───────────────────────────────────────────
|
|
14856
|
+
{
|
|
14857
|
+
id: "clean-functions",
|
|
14858
|
+
title: "Fun\xE7\xF5es pequenas e reveladoras",
|
|
14859
|
+
category: "clean-code",
|
|
14860
|
+
statement: "Fun\xE7\xF5es fazem uma coisa, num s\xF3 n\xEDvel de abstra\xE7\xE3o, com nomes que revelam inten\xE7\xE3o.",
|
|
14861
|
+
rationale: "C\xF3digo que se l\xEA como prosa reduz alucina\xE7\xE3o do agente e custo de manuten\xE7\xE3o."
|
|
14862
|
+
},
|
|
14863
|
+
{
|
|
14864
|
+
id: "typed-errors",
|
|
14865
|
+
title: "Erros tipados",
|
|
14866
|
+
category: "clean-code",
|
|
14867
|
+
statement: "Nunca lance string crua; use erros tipados e trate falhas explicitamente.",
|
|
14868
|
+
rationale: "Erros classific\xE1veis permitem retry inteligente e diagn\xF3sticos \u2014 n\xE3o silenciam o sistema."
|
|
14869
|
+
},
|
|
14870
|
+
{
|
|
14871
|
+
id: "no-magic",
|
|
14872
|
+
title: "Sem m\xE1gica, sem `any`",
|
|
14873
|
+
category: "clean-code",
|
|
14874
|
+
statement: "Sem n\xFAmeros m\xE1gicos, sem `any`; tipos estritos e constantes nomeadas.",
|
|
14875
|
+
rationale: "Tipos s\xE3o contexto de m\xE1quina \u2014 elevam o agent-readiness e barram regress\xF5es em compila\xE7\xE3o."
|
|
14876
|
+
},
|
|
14877
|
+
// ── XP ───────────────────────────────────────────────────
|
|
14878
|
+
{
|
|
14879
|
+
id: "atomic-decomposition",
|
|
14880
|
+
title: "Decomposi\xE7\xE3o at\xF4mica",
|
|
14881
|
+
category: "xp",
|
|
14882
|
+
statement: "Cada task \xE9 complet\xE1vel em \u22642h; epics viram tasks at\xF4micas antes de implementar.",
|
|
14883
|
+
rationale: "Pequenos passos verific\xE1veis mant\xEAm o ciclo curto e o custo previs\xEDvel."
|
|
14884
|
+
},
|
|
14885
|
+
{
|
|
14886
|
+
id: "anti-one-shot",
|
|
14887
|
+
title: "Anti-one-shot",
|
|
14888
|
+
category: "xp",
|
|
14889
|
+
statement: "Nunca gere um sistema inteiro num prompt; decomponha e itere.",
|
|
14890
|
+
rationale: "Gera\xE7\xE3o one-shot infla tokens e esconde defeitos \u2014 o oposto da disciplina incremental."
|
|
14891
|
+
},
|
|
14892
|
+
{
|
|
14893
|
+
id: "code-detachment",
|
|
14894
|
+
title: "Code detachment",
|
|
14895
|
+
category: "xp",
|
|
14896
|
+
statement: "Se a IA errou, explique o erro via prompt e regenere \u2014 n\xE3o edite o resultado \xE0 m\xE3o.",
|
|
14897
|
+
rationale: "Mant\xE9m o agente como autor respons\xE1vel e preserva a rastreabilidade no grafo."
|
|
14898
|
+
},
|
|
14899
|
+
// ── Lean / Theory of Constraints ─────────────────────────
|
|
14900
|
+
{
|
|
14901
|
+
id: "wip-one",
|
|
14902
|
+
title: "WIP = 1",
|
|
14903
|
+
category: "lean",
|
|
14904
|
+
statement: "No m\xE1ximo uma task `in_progress` por vez.",
|
|
14905
|
+
rationale: "Lei de Little: cycle_time = WIP / throughput \u2014 menos WIP, menos cycle time."
|
|
14906
|
+
},
|
|
14907
|
+
{
|
|
14908
|
+
id: "pull-not-push",
|
|
14909
|
+
title: "Pull, n\xE3o push",
|
|
14910
|
+
category: "lean",
|
|
14911
|
+
statement: "`next` puxa a pr\xF3xima task desbloqueada; nunca empurre para `in_progress`.",
|
|
14912
|
+
rationale: "Sistema pull respeita o gargalo (TOC) e evita ac\xFAmulo de WIP."
|
|
14913
|
+
},
|
|
14914
|
+
// ── Flow / economia de token (a fórmula do dono no centro) ─
|
|
14915
|
+
{
|
|
14916
|
+
id: "token-economy-lambda-flow",
|
|
14917
|
+
title: "Hipofrontalidade: \u03BB_flow",
|
|
14918
|
+
category: "flow",
|
|
14919
|
+
statement: "\u03BB_flow = \u03BB_base + (\u03B1 \xB7 \u03A6(t)). \u03A6 (\xEDndice de flow, EMA com histerese) governa a agressividade do esquecimento; o decaimento e^{-\u03BB\xB7d} dilui a vizinhan\xE7a do grafo \u2014 cortando tokens de contexto sem perder invariantes.",
|
|
14920
|
+
rationale: "O diferencial do projeto: um controlador determin\xEDstico de esquecimento corta o custo de contexto sem sumariza\xE7\xE3o por LLM."
|
|
14921
|
+
},
|
|
14922
|
+
{
|
|
14923
|
+
id: "repo-map-ranked",
|
|
14924
|
+
title: "Repo-map ranqueado",
|
|
14925
|
+
category: "flow",
|
|
14926
|
+
statement: "Injete s\xEDmbolos ranqueados por PageRank num budget ~1k tokens, focados na task.",
|
|
14927
|
+
rationale: "Contexto de entrada m\xEDnimo e relevante \u2014 corte de token sem perder sinal."
|
|
14928
|
+
},
|
|
14929
|
+
{
|
|
14930
|
+
id: "compact-feedback",
|
|
14931
|
+
title: "Feedback compacto no retry",
|
|
14932
|
+
category: "flow",
|
|
14933
|
+
statement: "No retry, realimente s\xF3 a sa\xEDda de teste que falhou (truncada), pedindo fix incremental.",
|
|
14934
|
+
rationale: "Menos tokens por itera\xE7\xE3o e menos escala\xE7\xF5es que re-geram do zero."
|
|
14935
|
+
}
|
|
14936
|
+
]);
|
|
14937
|
+
function listPrinciples() {
|
|
14938
|
+
return PRINCIPLES;
|
|
14939
|
+
}
|
|
14940
|
+
function getPrinciple(id) {
|
|
14941
|
+
return PRINCIPLES.find((p) => p.id === id);
|
|
14942
|
+
}
|
|
14943
|
+
function principlesByCategory(category) {
|
|
14944
|
+
return PRINCIPLES.filter((p) => p.category === category);
|
|
14945
|
+
}
|
|
14946
|
+
function listCategories() {
|
|
14947
|
+
const seen = [];
|
|
14948
|
+
for (const p of PRINCIPLES) {
|
|
14949
|
+
if (!seen.includes(p.category)) seen.push(p.category);
|
|
14950
|
+
}
|
|
14951
|
+
return seen;
|
|
14952
|
+
}
|
|
14953
|
+
|
|
14954
|
+
// src/cli/commands/principles-cmd.ts
|
|
14955
|
+
function output17(msg) {
|
|
14956
|
+
process.stdout.write(msg + "\n");
|
|
14957
|
+
}
|
|
14958
|
+
var CATEGORY_LABEL = {
|
|
14959
|
+
promise: "Promessa",
|
|
14960
|
+
tdd: "TDD",
|
|
14961
|
+
"clean-code": "Clean Code",
|
|
14962
|
+
xp: "XP",
|
|
14963
|
+
lean: "Lean / TOC",
|
|
14964
|
+
flow: "Flow / economia de token"
|
|
14965
|
+
};
|
|
14966
|
+
function principlesCommand() {
|
|
14967
|
+
const cmd = new Command("principles").description(
|
|
14968
|
+
"O credo de engenharia da CLI: Clean Code \xB7 XP \xB7 TDD \xB7 Lean + \u03BB_flow (economia de token)"
|
|
14969
|
+
);
|
|
14970
|
+
cmd.command("list", { isDefault: true }).description("Lista os princ\xEDpios agrupados por categoria").option("-c, --category <cat>", "Filtra por categoria (promise|tdd|clean-code|xp|lean|flow)").action((opts) => {
|
|
14971
|
+
const cats = opts.category ? [opts.category] : listCategories();
|
|
14972
|
+
for (const cat of cats) {
|
|
14973
|
+
const items = principlesByCategory(cat);
|
|
14974
|
+
if (items.length === 0) {
|
|
14975
|
+
output17(`(categoria desconhecida: ${cat})`);
|
|
14976
|
+
continue;
|
|
14977
|
+
}
|
|
14978
|
+
output17(`
|
|
14979
|
+
${CATEGORY_LABEL[cat] ?? cat}`);
|
|
14980
|
+
for (const p of items) output17(` \u2022 ${p.title.padEnd(28)} ${p.statement}`);
|
|
14981
|
+
}
|
|
14982
|
+
output17(`
|
|
14983
|
+
${listPrinciples().length} princ\xEDpios \xB7 use 'principles show <id>' para detalhes.`);
|
|
14984
|
+
});
|
|
14985
|
+
cmd.command("show <id>").description("Detalha um princ\xEDpio (t\xEDtulo, categoria, statement, rationale)").action((id) => {
|
|
14986
|
+
const p = getPrinciple(id);
|
|
14987
|
+
if (!p) {
|
|
14988
|
+
output17(`Princ\xEDpio desconhecido: ${id}. Tente 'principles list'.`);
|
|
14989
|
+
process.exitCode = 1;
|
|
14990
|
+
return;
|
|
14991
|
+
}
|
|
14992
|
+
output17(`${p.title} [${CATEGORY_LABEL[p.category] ?? p.category}]`);
|
|
14993
|
+
output17(`
|
|
14994
|
+
${p.statement}`);
|
|
14995
|
+
output17(`
|
|
14996
|
+
Por qu\xEA: ${p.rationale}`);
|
|
14997
|
+
});
|
|
14998
|
+
return cmd;
|
|
14999
|
+
}
|
|
15000
|
+
|
|
14658
15001
|
// src/cli/index.ts
|
|
14659
15002
|
var program = new Command();
|
|
14660
15003
|
program.name("agent-graph-flow").description(PROMISE).version(VERSION, "-v, --version");
|
|
@@ -14677,6 +15020,7 @@ program.addCommand(doctorCommand());
|
|
|
14677
15020
|
program.addCommand(gcCommand());
|
|
14678
15021
|
program.addCommand(skillCommand());
|
|
14679
15022
|
program.addCommand(profileCommand());
|
|
15023
|
+
program.addCommand(principlesCommand());
|
|
14680
15024
|
function shouldLaunchTui() {
|
|
14681
15025
|
const noArgs = process.argv.length <= 2;
|
|
14682
15026
|
const isTty = Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-graph-workflow/agent-graph-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Agente SWE autônomo, local-first e token-frugal: PRD → grafo de execução persistente, TDD obrigatório, custo de token brutalmente baixo. AGPL v3.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|