agentic-workflow-manager 3.13.7 → 4.0.1
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.
|
@@ -11,6 +11,8 @@ const picocolors_1 = __importDefault(require("picocolors"));
|
|
|
11
11
|
const context_1 = require("../core/diagnostics/context");
|
|
12
12
|
const checks_1 = require("../core/diagnostics/checks");
|
|
13
13
|
const paths_1 = require("../core/paths");
|
|
14
|
+
// `readPreferences`, no `getPreferences`: este comando esta documentado como
|
|
15
|
+
// read-only y el segundo auto-vivifica el archivo. Ver la nota en config.ts.
|
|
14
16
|
const config_1 = require("../utils/config");
|
|
15
17
|
const agent_targets_1 = require("../core/agent-targets");
|
|
16
18
|
function glyph(status) {
|
|
@@ -128,7 +130,7 @@ function runDoctor(opts = {}) {
|
|
|
128
130
|
// internal-error catch further down.
|
|
129
131
|
let targets;
|
|
130
132
|
try {
|
|
131
|
-
const prefs = (0, config_1.
|
|
133
|
+
const prefs = (0, config_1.readPreferences)();
|
|
132
134
|
targets = resolveTargets({ prefs, explicit: opts.agent });
|
|
133
135
|
}
|
|
134
136
|
catch (err) {
|
package/dist/src/index.js
CHANGED
|
@@ -88,9 +88,19 @@ function resolveSelectedArtifacts(selections) {
|
|
|
88
88
|
}
|
|
89
89
|
return Array.from(result.values());
|
|
90
90
|
}
|
|
91
|
+
// AWM instala BUNDLES, no artefactos sueltos. Es una decision de producto, no una
|
|
92
|
+
// limitacion pendiente: las skills de AWM se apoyan unas en otras (el spine de
|
|
93
|
+
// development-process invoca brainstorming, writing-plans, los gates de QA...), asi que
|
|
94
|
+
// una skill instalada sola casi nunca hace lo que el usuario espera. Ver
|
|
95
|
+
// docs/decisions.md, D-001.
|
|
96
|
+
//
|
|
97
|
+
// El flag `-t, --type` existia y `add.ts` NUNCA lo leia: se aceptaba y se descartaba en
|
|
98
|
+
// silencio. Peor, la doc y los playbooks de aceptacion documentaban `awm add <skill>
|
|
99
|
+
// --type skill` como el camino scripteado — una invocacion que siempre fallo con
|
|
100
|
+
// «Bundle "<skill>" not found». Los playbooks se escribieron contra la documentacion, no
|
|
101
|
+
// contra el comportamiento. Un flag que no se lee es peor que uno ausente: promete.
|
|
91
102
|
program.command('add [name]')
|
|
92
|
-
.description('Add a
|
|
93
|
-
.option('-t, --type <type>', 'Artifact type: skill, workflow, or process')
|
|
103
|
+
.description('Add a bundle (package of skills) interactively, or non-interactively with flags')
|
|
94
104
|
.option('-a, --agent <agent>', `Target agent: ${providers_1.AGENT_TARGETS.join(', ')}`)
|
|
95
105
|
.option('-s, --scope <scope>', 'Scope: local or global')
|
|
96
106
|
.option('-m, --method <method>', 'Install method: symlink or copy')
|
package/dist/src/utils/config.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.preferencesExist = preferencesExist;
|
|
7
|
+
exports.readPreferences = readPreferences;
|
|
7
8
|
exports.getPreferences = getPreferences;
|
|
8
9
|
exports.loadPreferences = loadPreferences;
|
|
9
10
|
exports.savePreferences = savePreferences;
|
|
@@ -84,6 +85,28 @@ function normalizePreferences(value, allowEnabledAgentsMigration = true) {
|
|
|
84
85
|
JSON.stringify(source) !== JSON.stringify(enabledAgents),
|
|
85
86
|
};
|
|
86
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Las preferencias TAL COMO ESTAN, sin escribir nada. Devuelve los defaults en memoria
|
|
90
|
+
* cuando el archivo no existe todavia.
|
|
91
|
+
*
|
|
92
|
+
* `getPreferences` auto-vivifica: si no hay archivo, lo crea con los defaults. Eso esta
|
|
93
|
+
* bien para un comando que va a configurar la maquina, y esta mal para uno que solo
|
|
94
|
+
* mira. `awm doctor` —documentado como «Read-only dashboard. Changes nothing.»— lo
|
|
95
|
+
* llamaba, asi que en una maquina limpia el comando de inspeccion dejaba un
|
|
96
|
+
* `preferences.json` con `claude-code` como agente por defecto, que despues se lee como
|
|
97
|
+
* «el usuario configuro esto» cuando no lo hizo. Lo encontro el playbook de aceptacion,
|
|
98
|
+
* no la suite: ningun test preguntaba si un comando de lectura escribia.
|
|
99
|
+
*
|
|
100
|
+
* Se midieron los otros siete comandos de inspeccion (`list`, `preflight`, `sensors
|
|
101
|
+
* status`, `context-budget`, `backup list`, `ledger list`, `registry status`): todos
|
|
102
|
+
* limpios. `doctor` era el unico.
|
|
103
|
+
*/
|
|
104
|
+
function readPreferences() {
|
|
105
|
+
const loaded = loadPreferences();
|
|
106
|
+
return loaded.exists
|
|
107
|
+
? loaded.prefs
|
|
108
|
+
: { ...DEFAULT_PREFS, enabledAgents: [...DEFAULT_PREFS.enabledAgents] };
|
|
109
|
+
}
|
|
87
110
|
function getPreferences() {
|
|
88
111
|
const loaded = loadPreferences();
|
|
89
112
|
if (!loaded.exists) {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
// `awm doctor` está documentado como «Read-only dashboard of machine + project harness
|
|
7
|
+
// state. **Changes nothing.**» — y escribía.
|
|
8
|
+
//
|
|
9
|
+
// `getPreferences()` auto-vivifica `preferences.json` con los defaults cuando el archivo
|
|
10
|
+
// no existe (`config.ts`: `if (!loaded.exists) savePreferences(DEFAULT_PREFS)`). Un
|
|
11
|
+
// getter con efecto de escritura escondido adentro. `doctor` lo llamaba para resolver a
|
|
12
|
+
// qué agentes mirar, así que en una máquina limpia el comando de inspección dejaba un
|
|
13
|
+
// `preferences.json` con `claude-code` como agente por defecto — que después se lee como
|
|
14
|
+
// «el usuario configuró esto» cuando no lo hizo.
|
|
15
|
+
//
|
|
16
|
+
// Lo encontró el playbook de aceptación en su segundo check, no la suite: ningún test
|
|
17
|
+
// preguntaba si un comando de lectura escribía. Se midieron los otros siete comandos de
|
|
18
|
+
// inspección (`list`, `preflight`, `sensors status`, `context-budget`, `backup list`,
|
|
19
|
+
// `ledger list`, `registry status`) y todos estaban limpios — así que acá el sitio ES la
|
|
20
|
+
// clase, con medición en vez de suposición.
|
|
21
|
+
const fs_1 = __importDefault(require("fs"));
|
|
22
|
+
const os_1 = __importDefault(require("os"));
|
|
23
|
+
const path_1 = __importDefault(require("path"));
|
|
24
|
+
describe('awm doctor no escribe nada', () => {
|
|
25
|
+
let home;
|
|
26
|
+
let projectRoot;
|
|
27
|
+
let saved;
|
|
28
|
+
let writeSpy;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
home = fs_1.default.realpathSync(fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'awm-doctor-ro-')));
|
|
31
|
+
saved = { HOME: process.env.HOME, AWM_HOME: process.env.AWM_HOME };
|
|
32
|
+
process.env.HOME = home;
|
|
33
|
+
process.env.AWM_HOME = path_1.default.join(home, '.awm');
|
|
34
|
+
projectRoot = path_1.default.join(home, 'proj');
|
|
35
|
+
fs_1.default.mkdirSync(path_1.default.join(projectRoot, '.git'), { recursive: true });
|
|
36
|
+
jest.resetModules();
|
|
37
|
+
writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
writeSpy.mockRestore();
|
|
41
|
+
if (saved.HOME === undefined)
|
|
42
|
+
delete process.env.HOME;
|
|
43
|
+
else
|
|
44
|
+
process.env.HOME = saved.HOME;
|
|
45
|
+
if (saved.AWM_HOME === undefined)
|
|
46
|
+
delete process.env.AWM_HOME;
|
|
47
|
+
else
|
|
48
|
+
process.env.AWM_HOME = saved.AWM_HOME;
|
|
49
|
+
fs_1.default.rmSync(home, { recursive: true, force: true });
|
|
50
|
+
});
|
|
51
|
+
/** Todo lo que exista bajo `home`, para comparar el antes y el después. */
|
|
52
|
+
const treeOf = (dir) => {
|
|
53
|
+
const out = [];
|
|
54
|
+
const walk = (sub) => {
|
|
55
|
+
for (const e of fs_1.default.readdirSync(path_1.default.join(dir, sub), { withFileTypes: true })) {
|
|
56
|
+
const rel = path_1.default.join(sub, e.name);
|
|
57
|
+
out.push(rel);
|
|
58
|
+
if (e.isDirectory())
|
|
59
|
+
walk(rel);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
walk('.');
|
|
63
|
+
return out.sort();
|
|
64
|
+
};
|
|
65
|
+
it('no crea AWM_HOME ni preferences.json en una máquina limpia', () => {
|
|
66
|
+
const { runDoctor } = require('../../src/commands/doctor');
|
|
67
|
+
const before = treeOf(home);
|
|
68
|
+
runDoctor({ cwd: projectRoot, json: true });
|
|
69
|
+
expect(fs_1.default.existsSync(path_1.default.join(home, '.awm', 'preferences.json'))).toBe(false);
|
|
70
|
+
expect(treeOf(home)).toEqual(before);
|
|
71
|
+
});
|
|
72
|
+
it('tampoco escribe cuando ya hay preferencias', () => {
|
|
73
|
+
// El otro camino de `getPreferences`: el archivo existe. `migrationRequired`
|
|
74
|
+
// podía reescribirlo — sigue siendo una escritura desde un comando de lectura.
|
|
75
|
+
fs_1.default.mkdirSync(path_1.default.join(home, '.awm'), { recursive: true });
|
|
76
|
+
const prefsPath = path_1.default.join(home, '.awm', 'preferences.json');
|
|
77
|
+
fs_1.default.writeFileSync(prefsPath, JSON.stringify({
|
|
78
|
+
enabledAgents: ['claude-code'], defaultAgent: 'claude-code',
|
|
79
|
+
installMethod: 'symlink', defaultScope: 'global',
|
|
80
|
+
}));
|
|
81
|
+
const before = fs_1.default.readFileSync(prefsPath, 'utf-8');
|
|
82
|
+
const beforeTree = treeOf(home);
|
|
83
|
+
const { runDoctor } = require('../../src/commands/doctor');
|
|
84
|
+
runDoctor({ cwd: projectRoot, json: true });
|
|
85
|
+
expect(fs_1.default.readFileSync(prefsPath, 'utf-8')).toBe(before);
|
|
86
|
+
expect(treeOf(home)).toEqual(beforeTree);
|
|
87
|
+
});
|
|
88
|
+
it('sigue reportando sobre el agente por defecto sin archivo de preferencias', () => {
|
|
89
|
+
// No alcanza con no escribir: tiene que seguir funcionando. Sin preferencias,
|
|
90
|
+
// los defaults en memoria son la respuesta correcta.
|
|
91
|
+
const { runDoctor } = require('../../src/commands/doctor');
|
|
92
|
+
const code = runDoctor({ cwd: projectRoot, json: true });
|
|
93
|
+
expect([0, 1]).toContain(code); // 0 sano / 1 degradado, nunca 2 (error)
|
|
94
|
+
const emitted = writeSpy.mock.calls.map((c) => String(c[0])).join('');
|
|
95
|
+
expect(JSON.parse(emitted).providers.map((p) => p.id)).toEqual(['claude-code']);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -11,7 +11,8 @@ const exec_wrapper_1 = require("../../../src/commands/job/exec-wrapper");
|
|
|
11
11
|
const store_1 = require("../../../src/core/journal/store");
|
|
12
12
|
const paths_1 = require("../../../src/core/journal/paths");
|
|
13
13
|
const process_1 = require("../../../src/core/journal/process");
|
|
14
|
-
// Presupuesto explicito, como sus tres
|
|
14
|
+
// Presupuesto explicito POR ENCIMA del global (30s en jest.config.js), como sus tres
|
|
15
|
+
// hermanos de `tests/commands/watch/`
|
|
15
16
|
// (integration 30s, supervisor-loop 60s, e2e-crash 180s). Este archivo era el unico de
|
|
16
17
|
// la familia sin uno, y hace el mismo trabajo que ellos: cada `collectAndReconcile`
|
|
17
18
|
// consulta si el proceso sigue vivo, y en Windows eso spawnea `tasklist` — cientos de ms
|