agentic-workflow-manager 9.21.0 → 9.22.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.
- package/dist/src/commands/change/index.js +16 -5
- package/dist/src/commands/init.js +8 -4
- package/dist/src/commands/preflight/checks.js +22 -0
- package/dist/src/commands/registry/add.js +9 -3
- package/dist/src/commands/sensors/compatibility/contract.js +56 -3
- package/dist/src/commands/sensors/compatibility/manifest.js +16 -2
- package/dist/src/commands/sensors/index.js +10 -1
- package/dist/src/commands/sensors/inputs-digest.js +315 -0
- package/dist/src/commands/sensors/prepare.js +10 -0
- package/dist/src/commands/sensors/result-cache.js +278 -0
- package/dist/src/commands/sensors/result.js +31 -12
- package/dist/src/commands/sensors/run.js +265 -8
- package/dist/src/commands/sensors/status.js +66 -7
- package/dist/src/commands/sync.js +11 -5
- package/dist/src/commands/update.js +23 -12
- package/dist/src/core/changes/derive.js +6 -3
- package/dist/src/core/changes/git.js +1 -2
- package/dist/src/core/changes/receipt.js +219 -9
- package/dist/src/core/changes/worktree.js +15 -3
- package/dist/src/core/init/steps.js +3 -8
- package/dist/src/core/registries.js +20 -15
- package/dist/src/core/registry-git-errors.js +107 -0
- package/dist/src/core/registry-git.js +93 -0
- package/dist/src/core/registry-sync-report.js +74 -0
- package/dist/src/core/versioning.js +3 -6
- package/dist/src/index.js +5 -8
- package/dist/tests/commands/change/new.test.js +104 -58
- package/dist/tests/commands/change/validate-unmeasured.test.js +246 -0
- package/dist/tests/commands/change/validate.test.js +164 -108
- package/dist/tests/commands/changes/list.test.js +41 -22
- package/dist/tests/commands/job/gate-reconcile.test.js +13 -2
- package/dist/tests/commands/preflight/sensors-inputs.test.js +110 -0
- package/dist/tests/commands/registry-sync-honesty.test.js +175 -0
- package/dist/tests/commands/sensors/compatibility/contract.test.js +60 -0
- package/dist/tests/commands/sensors/compatibility/manifest.test.js +94 -0
- package/dist/tests/commands/sensors/exec.test.js +3 -1
- package/dist/tests/commands/sensors/inputs-digest.test.js +373 -0
- package/dist/tests/commands/sensors/result-cache.test.js +352 -0
- package/dist/tests/commands/sensors/run-cache.test.js +434 -0
- package/dist/tests/commands/sensors/run-slice.test.js +171 -0
- package/dist/tests/commands/sensors/status-inputs.test.js +271 -0
- package/dist/tests/commands/update.test.js +8 -8
- package/dist/tests/commands/watch/supervisor-loop.test.js +21 -5
- package/dist/tests/core/changes/helpers.js +15 -3
- package/dist/tests/core/changes/list-paging.test.js +131 -110
- package/dist/tests/core/changes/list.test.js +133 -83
- package/dist/tests/core/changes/receipt.test.js +279 -8
- package/dist/tests/core/diagnostics/provider-checks.test.js +3 -0
- package/dist/tests/core/init/steps-registry-sync.test.js +6 -8
- package/dist/tests/core/registry-git.test.js +153 -0
- package/dist/tests/helpers/commit-seeded-registry.js +18 -0
- package/dist/tests/integration/codex-provider-isolated.test.js +7 -2
- package/dist/tests/integration/copilot-init-isolated.test.js +7 -4
- package/dist/tests/structural/active-documentation.test.js +0 -41
- package/dist/tests/structural/bundle-skill-reference-contract.test.js +0 -12
- package/dist/tests/structural/cli-reference-matches-commander.test.js +94 -0
- package/dist/tests/structural/native-release-artifacts.test.js +116 -107
- package/dist/tests/structural/sensor-documentation-contract.test.js +0 -47
- package/dist/tests/structural/sensor-portability-contract.test.js +0 -7
- package/dist/tests/structural/simple-git-v4-pin.test.js +49 -0
- package/package.json +3 -2
- package/prebuilds/darwin-arm64/secure_fs.node +0 -0
- package/prebuilds/darwin-x64/secure_fs.node +0 -0
- package/prebuilds/win32-arm64/secure_fs.node +0 -0
- package/prebuilds/win32-x64/secure_fs.node +0 -0
- package/dist/tests/structural/cloud-admission-docs-contract.test.js +0 -54
- package/dist/tests/structural/documentation-phase-is-mechanized.test.js +0 -29
- package/dist/tests/structural/operator-environments-docs-contract.test.js +0 -70
- package/dist/tests/structural/process-model-description-contract.test.js +0 -34
- package/dist/tests/structural/project-declared-sensors-docs-contract.test.js +0 -104
- package/dist/tests/structural/r4-plan-currentness-docs.test.js +0 -37
|
@@ -24,13 +24,6 @@ describe('Publication B portable bootstrap contract', () => {
|
|
|
24
24
|
expect(help).toContain('--reason <text>');
|
|
25
25
|
expect(help).toContain('--dry-run');
|
|
26
26
|
});
|
|
27
|
-
it('documents schema v3, explicit migration, dry-run, and environment separation', () => {
|
|
28
|
-
const reference = fs_1.default.readFileSync(path_1.default.join(root, 'docs/cli-reference.md'), 'utf8');
|
|
29
|
-
expect(reference).toContain('awm sensors bootstrap [--mode project-sensors|native-gate|opt-out] [--reason <text>] [--dry-run]');
|
|
30
|
-
expect(reference).toContain('schemaVersion: 3');
|
|
31
|
-
expect(reference).toContain('never writes');
|
|
32
|
-
expect(reference).toContain('each environment updates its own AWM installation separately');
|
|
33
|
-
});
|
|
34
27
|
it('keeps all documented v3 declarations free of machine registry paths', () => {
|
|
35
28
|
const reference = fs_1.default.readFileSync(path_1.default.join(root, 'docs/cli-reference.md'), 'utf8');
|
|
36
29
|
const examples = Array.from(reference.matchAll(/```json\s*\n([\s\S]*?)```/g), match => JSON.parse(match[1]));
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const CLI_ROOT = path_1.default.resolve(__dirname, '..', '..');
|
|
9
|
+
const FACTORY = 'src/core/registry-git.ts';
|
|
10
|
+
describe('simple-git v4 pin (#238)', () => {
|
|
11
|
+
it('pins simple-git exactly to 4.0.2', () => {
|
|
12
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(path_1.default.join(CLI_ROOT, 'package.json'), 'utf8'));
|
|
13
|
+
expect(pkg.dependencies['simple-git']).toBe('4.0.2');
|
|
14
|
+
});
|
|
15
|
+
it('imports simple-git only from registry-git.ts via named simpleGit', () => {
|
|
16
|
+
const factory = fs_1.default.readFileSync(path_1.default.join(CLI_ROOT, FACTORY), 'utf8');
|
|
17
|
+
expect(factory).toMatch(/import\s*\{[^}]*\bsimpleGit\b[^}]*\}\s*from\s*['"]simple-git['"]/);
|
|
18
|
+
expect(factory).not.toMatch(/import\s+simpleGit\s+from\s*['"]simple-git['"]/);
|
|
19
|
+
const walk = (dir) => {
|
|
20
|
+
const out = [];
|
|
21
|
+
for (const ent of fs_1.default.readdirSync(dir, { withFileTypes: true })) {
|
|
22
|
+
const p = path_1.default.join(dir, ent.name);
|
|
23
|
+
if (ent.isDirectory())
|
|
24
|
+
out.push(...walk(p));
|
|
25
|
+
else if (ent.name.endsWith('.ts'))
|
|
26
|
+
out.push(p);
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
};
|
|
30
|
+
for (const file of walk(path_1.default.join(CLI_ROOT, 'src'))) {
|
|
31
|
+
const rel = path_1.default.relative(CLI_ROOT, file).replace(/\\/g, '/');
|
|
32
|
+
if (rel === FACTORY)
|
|
33
|
+
continue;
|
|
34
|
+
const text = fs_1.default.readFileSync(file, 'utf8');
|
|
35
|
+
expect(text).not.toMatch(/from\s*['"]simple-git['"]/);
|
|
36
|
+
expect(text).not.toMatch(/\bsimpleGit\s*\(/);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
it('factory allowEnvironment is only GIT_TERMINAL_PROMPT and enables no allowUnsafe*', () => {
|
|
40
|
+
const factory = fs_1.default.readFileSync(path_1.default.join(CLI_ROOT, FACTORY), 'utf8');
|
|
41
|
+
expect(factory).toMatch(/allowEnvironment:\s*\[\s*['"]GIT_TERMINAL_PROMPT['"]\s*\]/);
|
|
42
|
+
expect(factory).not.toMatch(/allowUnsafe/);
|
|
43
|
+
// B1 / V1: factory must use the shared constant (not a duplicated literal).
|
|
44
|
+
expect(factory).toMatch(/timeout:\s*\{\s*block:\s*REGISTRY_GIT_TIMEOUT_MS\s*\}/);
|
|
45
|
+
expect(factory).toMatch(/export\s+const\s+REGISTRY_GIT_TIMEOUT_MS\s*=\s*60_?000\s*;/);
|
|
46
|
+
// SG-3: guarded env must be applied — deleting `.env(buildRegistryGitEnv())` must fail this pin.
|
|
47
|
+
expect(factory).toMatch(/\.env\(\s*buildRegistryGitEnv\(\)/);
|
|
48
|
+
});
|
|
49
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-workflow-manager",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.22.1",
|
|
4
4
|
"main": "dist/src/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"awm": "./dist/src/index.js"
|
|
@@ -53,8 +53,9 @@
|
|
|
53
53
|
"commander": "^14.0.3",
|
|
54
54
|
"js-yaml": "4.3.2",
|
|
55
55
|
"picocolors": "^1.1.1",
|
|
56
|
+
"picomatch": "4.0.7",
|
|
56
57
|
"semver": "^7.7.4",
|
|
57
|
-
"simple-git": "
|
|
58
|
+
"simple-git": "4.0.2"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
61
|
"@types/jest": "^30.0.0",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,54 +0,0 @@
|
|
|
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
|
-
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
/** CMD-DOCS — V-R4 (issue #215 documentation). */
|
|
9
|
-
const repoRoot = path_1.default.resolve(__dirname, '../../..');
|
|
10
|
-
/** Whitespace-normalized so re-wrapping the prose never breaks a pinned phrase. */
|
|
11
|
-
const read = (relative) => fs_1.default.readFileSync(path_1.default.join(repoRoot, ...relative.split('/')), 'utf8').replace(/\s+/g, ' ');
|
|
12
|
-
describe('issue #215 documentation contract (V-R4)', () => {
|
|
13
|
-
const configuration = read('docs/configuration.md');
|
|
14
|
-
it('documents .awm/admission.json with defaults, the git rule and the accepted risk', () => {
|
|
15
|
-
expect(configuration).toContain('## Read-only admission observation (`.awm/admission.json`)');
|
|
16
|
-
for (const name of ['node_modules', '.next', '.turbo', 'dist', 'build', 'coverage', '.venv', 'target'])
|
|
17
|
-
expect(configuration).toContain(`\`${name}\``);
|
|
18
|
-
expect(configuration).toContain('git-ignored and contains no tracked file');
|
|
19
|
-
expect(configuration).toContain('**Accepted risk:**');
|
|
20
|
-
expect(configuration).toContain('`admission-config-invalid`');
|
|
21
|
-
expect(configuration).toContain('`readOnlyObservation`');
|
|
22
|
-
expect(configuration).toContain('`awm plan admit` does not print it');
|
|
23
|
-
});
|
|
24
|
-
it.each([
|
|
25
|
-
'250000',
|
|
26
|
-
'1 GiB',
|
|
27
|
-
'`read-only-mutation-detected`',
|
|
28
|
-
'`read-only-observation-unavailable`',
|
|
29
|
-
'`not-ignored`',
|
|
30
|
-
'`contains-tracked`',
|
|
31
|
-
'`git-unavailable`',
|
|
32
|
-
'`.git` or `.awm`',
|
|
33
|
-
'never skipped',
|
|
34
|
-
'including any `.awm` or `.git` nested',
|
|
35
|
-
'regular file',
|
|
36
|
-
'65536 bytes',
|
|
37
|
-
])('documents the observation limit, reason code or reserved-name rule %s', literal => {
|
|
38
|
-
expect(configuration).toContain(literal);
|
|
39
|
-
});
|
|
40
|
-
it('points --verify-sensors in the CLI reference at the observation rules', () => {
|
|
41
|
-
const doc = read('docs/cli-reference.md');
|
|
42
|
-
expect(doc).toContain('configuration.md#read-only-admission-observation-awmadmissionjson');
|
|
43
|
-
expect(doc).toContain('`ADMISSION_SENSORS_BLOCKED`');
|
|
44
|
-
});
|
|
45
|
-
it('states that the D-7 insteadOf recipe passes strict currentness', () => {
|
|
46
|
-
const doc = read('docs/operations/cloud-and-platforms.md');
|
|
47
|
-
expect(doc).toContain('`awm preflight --require-current`');
|
|
48
|
-
expect(doc).toContain('`remote.origin.url`');
|
|
49
|
-
expect(doc).toContain('--local');
|
|
50
|
-
});
|
|
51
|
-
it('describes the snapshot exclusions in the plan admit help', () => {
|
|
52
|
-
expect(read('cli/src/commands/plan/index.ts')).toContain("'require an empirical sensor pass; read-only observation skips git-ignored build output (see .awm/admission.json)'");
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1,29 +0,0 @@
|
|
|
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
|
-
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const ROOT = path_1.default.resolve(__dirname, '../../..');
|
|
9
|
-
const read = (file) => fs_1.default.readFileSync(path_1.default.join(ROOT, file), 'utf8');
|
|
10
|
-
describe('la fase de documentacion esta mecanizada, no solo enunciada', () => {
|
|
11
|
-
it('CONSTITUTION.md enuncia la regla y nombra el marker', () => {
|
|
12
|
-
const text = read('CONSTITUTION.md');
|
|
13
|
-
expect(text).toMatch(/awm-docs-complete/);
|
|
14
|
-
expect(text).toMatch(/post-implementation-docs/);
|
|
15
|
-
});
|
|
16
|
-
it('CONSTITUTION.md apunta al mecanismo, no lo reemplaza', () => {
|
|
17
|
-
const text = read('CONSTITUTION.md');
|
|
18
|
-
// debe citar el archivo que efectivamente hace cumplir la regla
|
|
19
|
-
expect(text).toMatch(/plan-state\.ts/);
|
|
20
|
-
expect(text).toMatch(/development-process/);
|
|
21
|
-
});
|
|
22
|
-
it('el enunciado NO es el unico lugar donde la fase existe', () => {
|
|
23
|
-
// Si esto pasa solo por CONSTITUTION.md, la regla es decorativa.
|
|
24
|
-
expect(read('cli/src/core/dashboard/plan-state.ts')).toMatch(/docsComplete/);
|
|
25
|
-
expect(read('cli/src/core/dashboard/plan-state.ts')).toMatch(/docs_pending/);
|
|
26
|
-
expect(read('cli/src/core/dashboard/sanitize.ts')).toMatch(/docsComplete/);
|
|
27
|
-
expect(read('cli/src/commands/evidence/index.ts')).toMatch(/awm-docs-complete/);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
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
|
-
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
/**
|
|
9
|
-
* CMD-SCAFFOLD-DOCS — RF-5.2 operator-environments documentation contract.
|
|
10
|
-
* Asserts runbook + cli-reference document scaffold/doctor/env and state that
|
|
11
|
-
* awm-cenco-infra-registry migration is out of scope (RF-5.2).
|
|
12
|
-
*/
|
|
13
|
-
const repoRoot = path_1.default.resolve(__dirname, '../../..');
|
|
14
|
-
const runbookPath = path_1.default.join(repoRoot, 'docs', 'runbook.md');
|
|
15
|
-
const cliReferencePath = path_1.default.join(repoRoot, 'docs', 'cli-reference.md');
|
|
16
|
-
const designPath = 'docs/plans/2026-10-12-operator-environments-design.md';
|
|
17
|
-
function teamRegistriesSection(runbook) {
|
|
18
|
-
const start = runbook.indexOf('## Team registries');
|
|
19
|
-
expect(start).toBeGreaterThanOrEqual(0);
|
|
20
|
-
const rest = runbook.slice(start);
|
|
21
|
-
const nextH2 = rest.search(/\n## (?!Team)/);
|
|
22
|
-
return nextH2 === -1 ? rest : rest.slice(0, nextH2);
|
|
23
|
-
}
|
|
24
|
-
function registriesSection(cliRef) {
|
|
25
|
-
const start = cliRef.indexOf('## Registries & pinning');
|
|
26
|
-
expect(start).toBeGreaterThanOrEqual(0);
|
|
27
|
-
const rest = cliRef.slice(start);
|
|
28
|
-
const nextH2 = rest.search(/\n## (?!Registries)/);
|
|
29
|
-
return nextH2 === -1 ? rest : rest.slice(0, nextH2);
|
|
30
|
-
}
|
|
31
|
-
describe('operator-environments docs contract (RF-5.2)', () => {
|
|
32
|
-
it('runbook team-registries leads with scaffold and mentions doctor + design RF-5.2 out-of-scope', () => {
|
|
33
|
-
const runbook = fs_1.default.readFileSync(runbookPath, 'utf-8');
|
|
34
|
-
const section = teamRegistriesSection(runbook);
|
|
35
|
-
const scaffoldIdx = section.indexOf('awm registry scaffold');
|
|
36
|
-
const addIdx = section.indexOf('awm registry add');
|
|
37
|
-
expect(scaffoldIdx).toBeGreaterThanOrEqual(0);
|
|
38
|
-
expect(addIdx).toBeGreaterThan(scaffoldIdx);
|
|
39
|
-
expect(section).toContain('awm registry doctor');
|
|
40
|
-
// RF-5.2: Cenco infra registry is out of scope — require the out-of-scope
|
|
41
|
-
// phrase near the cenco mention (same paragraph/window), not a loose
|
|
42
|
-
// match elsewhere in the section.
|
|
43
|
-
expect(section).toMatch(/RF-5\.2/);
|
|
44
|
-
expect(section).toContain(designPath);
|
|
45
|
-
const cencoIdx = section.search(/awm-cenco-infra-registry/);
|
|
46
|
-
expect(cencoIdx).toBeGreaterThanOrEqual(0);
|
|
47
|
-
const windowStart = Math.max(0, cencoIdx - 120);
|
|
48
|
-
const windowEnd = Math.min(section.length, cencoIdx + 160);
|
|
49
|
-
const nearCenco = section.slice(windowStart, windowEnd);
|
|
50
|
-
expect(nearCenco).toMatch(/out of scope|out-of-scope|does not modify|SHALL NOT modify/i);
|
|
51
|
-
});
|
|
52
|
-
it('cli-reference documents registry scaffold, registry doctor, and awm env', () => {
|
|
53
|
-
const cliRef = fs_1.default.readFileSync(cliReferencePath, 'utf-8');
|
|
54
|
-
const registries = registriesSection(cliRef);
|
|
55
|
-
expect(registries).toMatch(/###\s+`awm registry scaffold/);
|
|
56
|
-
expect(registries).toMatch(/###\s+`awm registry doctor/);
|
|
57
|
-
// env lives as its own H2; require the three command strings in the file
|
|
58
|
-
// with scoped checks so headings cannot be satisfied by a stray mention.
|
|
59
|
-
expect(cliRef).toContain('awm registry scaffold');
|
|
60
|
-
expect(cliRef).toContain('awm registry doctor');
|
|
61
|
-
const envStart = cliRef.search(/^##\s+.*\benv\b/im);
|
|
62
|
-
expect(envStart).toBeGreaterThanOrEqual(0);
|
|
63
|
-
const envRest = cliRef.slice(envStart);
|
|
64
|
-
const envNext = envRest.search(/\n## /);
|
|
65
|
-
const envSection = envNext === -1 ? envRest : envRest.slice(0, envNext);
|
|
66
|
-
expect(envSection).toMatch(/awm env/);
|
|
67
|
-
expect(envSection).toMatch(/env set|`awm env set`/i);
|
|
68
|
-
expect(envSection).toMatch(/env status|`awm env status`/i);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
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
|
-
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const DESIGN = path_1.default.resolve(__dirname, '../../../docs/plans/2026-08-23-process-lifecycle-design.md');
|
|
9
|
-
function artifactSection() {
|
|
10
|
-
const text = fs_1.default.readFileSync(DESIGN, 'utf8');
|
|
11
|
-
const start = text.indexOf('### El artefacto');
|
|
12
|
-
expect(start).toBeGreaterThan(-1);
|
|
13
|
-
const end = text.indexOf('\n### ', start + 1);
|
|
14
|
-
return text.slice(start, end === -1 ? undefined : end);
|
|
15
|
-
}
|
|
16
|
-
describe('process-model contract documents the optional description (PD-4)', () => {
|
|
17
|
-
it('lists description in the frontmatter block as optional', () => {
|
|
18
|
-
const section = artifactSection();
|
|
19
|
-
expect(section).toMatch(/^description: <texto de una línea> {2}# opcional$/m);
|
|
20
|
-
});
|
|
21
|
-
it('states the rules the parser enforces and why the field exists', () => {
|
|
22
|
-
/** Whitespace-normalized so re-wrapping the prose never breaks a pinned phrase. */
|
|
23
|
-
const section = artifactSection().replace(/\s+/g, ' ');
|
|
24
|
-
expect(section).toContain('#### Enmienda 2026-10-18 — `description` opcional');
|
|
25
|
-
expect(section).toContain('una sola línea');
|
|
26
|
-
expect(section).toContain('1024 caracteres');
|
|
27
|
-
expect(section).toContain('Codex');
|
|
28
|
-
expect(section).toContain('único campo opcional');
|
|
29
|
-
expect(section).toContain('parser YAML');
|
|
30
|
-
expect(section).not.toContain('no reemplaza a un parser YAML');
|
|
31
|
-
expect(section).toContain('code points');
|
|
32
|
-
expect(section).toContain('caracteres de control');
|
|
33
|
-
});
|
|
34
|
-
});
|
|
@@ -1,104 +0,0 @@
|
|
|
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
|
-
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
/**
|
|
9
|
-
* CMD-DOCS — RF-5.1 / RF-5.2 (project-declared sensors documentation).
|
|
10
|
-
*
|
|
11
|
-
* Resolves awm-baseline-registry from (in order):
|
|
12
|
-
* 1. `AWM_BASELINE_REGISTRY_ROOT` (CI docs checkout)
|
|
13
|
-
* 2. nested `repoRoot/awm-baseline-registry` (CI support-matrix layout)
|
|
14
|
-
* 3. sibling `repoRoot/../awm-baseline-registry` (maintainer workspace)
|
|
15
|
-
*
|
|
16
|
-
* Prefer a checkout that already contains RF-5.1 (`## Project sensors vs packs`).
|
|
17
|
-
* Missing / too-old checkouts fail loudly (no silent skip).
|
|
18
|
-
*/
|
|
19
|
-
const repoRoot = path_1.default.resolve(__dirname, '../../..');
|
|
20
|
-
const cliReferencePath = path_1.default.join(repoRoot, 'docs', 'cli-reference.md');
|
|
21
|
-
const RF51_HEADING = '## Project sensors vs packs';
|
|
22
|
-
function setupSensorsSkillPath(registryRoot) {
|
|
23
|
-
return path_1.default.join(registryRoot, 'skills', 'setup-sensors', 'SKILL.md');
|
|
24
|
-
}
|
|
25
|
-
function resolveSetupSensorsPath() {
|
|
26
|
-
const envRoot = process.env.AWM_BASELINE_REGISTRY_ROOT?.trim();
|
|
27
|
-
// When CI/maintainer sets the override, that root is authoritative (no silent
|
|
28
|
-
// fallback to a nested immutable pin that lacks RF-5.1 prose).
|
|
29
|
-
const candidates = envRoot
|
|
30
|
-
? [path_1.default.resolve(envRoot)]
|
|
31
|
-
: [
|
|
32
|
-
path_1.default.join(repoRoot, 'awm-baseline-registry'),
|
|
33
|
-
path_1.default.join(repoRoot, '..', 'awm-baseline-registry'),
|
|
34
|
-
];
|
|
35
|
-
const existing = candidates
|
|
36
|
-
.map(root => ({ root, skill: setupSensorsSkillPath(root) }))
|
|
37
|
-
.filter(entry => fs_1.default.existsSync(entry.skill));
|
|
38
|
-
if (existing.length === 0) {
|
|
39
|
-
throw new Error('Baseline registry checkout missing for RF-5.1 docs contract. Tried:\n'
|
|
40
|
-
+ candidates.map(root => ` - ${setupSensorsSkillPath(root)}`).join('\n')
|
|
41
|
-
+ '\nClone awm-baseline-registry as a sibling, nest it under the CLI repo, '
|
|
42
|
-
+ 'or set AWM_BASELINE_REGISTRY_ROOT to a checkout that includes setup-sensors RF-5.1.');
|
|
43
|
-
}
|
|
44
|
-
const withRf51 = existing.find(entry => fs_1.default.readFileSync(entry.skill, 'utf8').includes(RF51_HEADING));
|
|
45
|
-
if (!withRf51) {
|
|
46
|
-
throw new Error('Baseline registry checkout is present but too old for RF-5.1 '
|
|
47
|
-
+ `(missing ${RF51_HEADING}). Checked:\n`
|
|
48
|
-
+ existing.map(entry => ` - ${entry.skill}`).join('\n')
|
|
49
|
-
+ '\nPoint AWM_BASELINE_REGISTRY_ROOT at a registry tip that documents project-declared sensors '
|
|
50
|
-
+ '(coordinated awm-baseline-registry PR), without replacing the immutable v2.0.1 support-matrix pin.');
|
|
51
|
-
}
|
|
52
|
-
return withRf51.skill;
|
|
53
|
-
}
|
|
54
|
-
function sensorsSection(text) {
|
|
55
|
-
const start = text.indexOf('## Sensors (per-project computational checks)');
|
|
56
|
-
expect(start).toBeGreaterThanOrEqual(0);
|
|
57
|
-
const rest = text.slice(start);
|
|
58
|
-
const nextH2 = rest.search(/\n## (?!Sensors)/);
|
|
59
|
-
return nextH2 === -1 ? rest : rest.slice(0, nextH2);
|
|
60
|
-
}
|
|
61
|
-
/** Skill body after YAML frontmatter (content after the closing `---`). */
|
|
62
|
-
function skillBody(skill) {
|
|
63
|
-
const match = skill.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/);
|
|
64
|
-
if (!match) {
|
|
65
|
-
throw new Error('setup-sensors SKILL.md missing YAML frontmatter delimiters');
|
|
66
|
-
}
|
|
67
|
-
return match[1];
|
|
68
|
-
}
|
|
69
|
-
/** Named H2 section inside the skill body; fails if the heading is absent. */
|
|
70
|
-
function skillSection(body, heading) {
|
|
71
|
-
const start = body.indexOf(heading);
|
|
72
|
-
expect(start).toBeGreaterThanOrEqual(0);
|
|
73
|
-
const rest = body.slice(start);
|
|
74
|
-
const nextH2 = rest.search(/\n## /);
|
|
75
|
-
return nextH2 === -1 ? rest : rest.slice(0, nextH2);
|
|
76
|
-
}
|
|
77
|
-
describe('project-declared sensors docs contract (CMD-DOCS)', () => {
|
|
78
|
-
it('cli-reference sensors section documents project markers, provenance, exit-code, and non-gating (RF-5.2)', () => {
|
|
79
|
-
const text = fs_1.default.readFileSync(cliReferencePath, 'utf8');
|
|
80
|
-
const section = sensorsSection(text);
|
|
81
|
-
expect(section).toMatch(/source:\s*"project"|source"\s*:\s*"project"/);
|
|
82
|
-
expect(section).toContain('project-declared');
|
|
83
|
-
expect(section).toContain('exit-code');
|
|
84
|
-
expect(section).toMatch(/provenance[\s\S]{0,220}(?:does not|never)\s+(?:block|blocks)[\s\S]{0,100}(?:unattended|gates)/i);
|
|
85
|
-
// Optional pack (omit or null) — RF-5.2 clause already in cli-reference prose.
|
|
86
|
-
expect(section).toMatch(/[Pp]ack may be omitted or set\s+to\s+`?null`?[\s\S]{0,120}project-declared/i);
|
|
87
|
-
// JSON-vs-schema diagnostics distinction — RF-5.2.
|
|
88
|
-
expect(section).toMatch(/not valid JSON[\s\S]{0,220}schema-invalid/i);
|
|
89
|
-
});
|
|
90
|
-
it('setup-sensors skill documents project vs pack, JSON example, and non-gating provenance (RF-5.1)', () => {
|
|
91
|
-
const setupSensorsPath = resolveSetupSensorsPath();
|
|
92
|
-
const skill = fs_1.default.readFileSync(setupSensorsPath, 'utf8');
|
|
93
|
-
const body = skillBody(skill);
|
|
94
|
-
// Scope when-to-use / project-vs-packs (and related RF-5.1 prose) to the
|
|
95
|
-
// dedicated body section — frontmatter description must not satisfy these.
|
|
96
|
-
const projectVsPacks = skillSection(body, RF51_HEADING);
|
|
97
|
-
// Both guidance clauses are required — Prefer|Declare OR let either alone satisfy.
|
|
98
|
-
expect(projectVsPacks).toMatch(/Prefer a \*\*pack\*\*/);
|
|
99
|
-
expect(projectVsPacks).toMatch(/Declare a \*\*project sensor\*\*\s+when\s+the check is project-owned/i);
|
|
100
|
-
expect(projectVsPacks).toMatch(/"source"\s*:\s*"project"/);
|
|
101
|
-
expect(projectVsPacks).toMatch(/```json[\s\S]*?"source"\s*:\s*"project"[\s\S]*?```/);
|
|
102
|
-
expect(projectVsPacks).toMatch(/project-declared[\s\S]{0,220}(?:does not|never)\s+(?:block|blocks)[\s\S]{0,100}unattended/i);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
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
|
-
const fs_1 = __importDefault(require("fs"));
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const cliReference = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../../docs/cli-reference.md'), 'utf8');
|
|
9
|
-
const readme = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../../README.md'), 'utf8');
|
|
10
|
-
const installation = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../../docs/installation.md'), 'utf8');
|
|
11
|
-
const developmentProcess = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../../docs/guides/development-process.md'), 'utf8');
|
|
12
|
-
describe('R4 plan/currentness documentation contract', () => {
|
|
13
|
-
it('documents plan validation and the unchanged legacy path', () => {
|
|
14
|
-
expect(cliReference).toContain('awm plan validate PLAN_PATH');
|
|
15
|
-
expect(cliReference).toMatch(/legacy/i);
|
|
16
|
-
});
|
|
17
|
-
it('documents strict currentness separately from minCliVersion compatibility', () => {
|
|
18
|
-
expect(cliReference).toContain('--require-current');
|
|
19
|
-
expect(cliReference).toContain('minCliVersion');
|
|
20
|
-
expect(cliReference).toMatch(/currentness[\s\S]{0,700}compatib|compatib[\s\S]{0,700}currentness/i);
|
|
21
|
-
});
|
|
22
|
-
it('documents the exact cache-resistant bootstrap and its enforceable boundary', () => {
|
|
23
|
-
expect(cliReference).toContain('npm exec --yes --package=agentic-workflow-manager@latest -- awm preflight --require-current');
|
|
24
|
-
expect(cliReference).toMatch(/fresh CLI\/bootstrap/i);
|
|
25
|
-
expect(cliReference).toMatch(/cannot update a host or cached container that\s+never runs new code/i);
|
|
26
|
-
});
|
|
27
|
-
it('keeps supported commands, remedies, bootstrap, and the enforceable boundary discoverable across user docs', () => {
|
|
28
|
-
expect(readme).toContain('awm plan validate PLAN_PATH');
|
|
29
|
-
expect(readme).toContain('awm preflight --require-current');
|
|
30
|
-
expect(installation).toContain('npm exec --yes --package=agentic-workflow-manager@latest -- awm preflight --require-current');
|
|
31
|
-
expect(installation).toMatch(/cannot update a host or cached container that\s+never runs new code/i);
|
|
32
|
-
expect(developmentProcess).toContain('awm preflight --require-current');
|
|
33
|
-
expect(developmentProcess).toContain('awm plan validate PLAN_PATH');
|
|
34
|
-
expect(developmentProcess).toMatch(/awm update --yes/);
|
|
35
|
-
expect(cliReference).toMatch(/awm unpin REGISTRY_NAME.*awm update --yes/s);
|
|
36
|
-
});
|
|
37
|
-
});
|