@pedyc/harness-core 1.1.0 → 1.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/README.md +41 -0
- package/dist/config/agents.d.ts +14 -0
- package/dist/config/agents.d.ts.map +1 -0
- package/dist/config/agents.js +39 -0
- package/dist/config/agents.js.map +1 -0
- package/dist/config/bundled.d.ts +14 -0
- package/dist/config/bundled.d.ts.map +1 -0
- package/dist/config/bundled.js +38 -0
- package/dist/config/bundled.js.map +1 -0
- package/dist/config/defaults.d.ts +19 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +32 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/errors.d.ts +12 -0
- package/dist/config/errors.d.ts.map +1 -0
- package/dist/config/errors.js +11 -0
- package/dist/config/errors.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +18 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/json.d.ts +14 -0
- package/dist/config/json.d.ts.map +1 -0
- package/dist/config/json.js +5 -0
- package/dist/config/json.js.map +1 -0
- package/dist/config/loader.d.ts +16 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +221 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manifest.d.ts +22 -0
- package/dist/config/manifest.d.ts.map +1 -0
- package/dist/config/manifest.js +56 -0
- package/dist/config/manifest.js.map +1 -0
- package/dist/config/policy.d.ts +14 -0
- package/dist/config/policy.d.ts.map +1 -0
- package/dist/config/policy.js +35 -0
- package/dist/config/policy.js.map +1 -0
- package/dist/config/presets.d.ts +35 -0
- package/dist/config/presets.d.ts.map +1 -0
- package/dist/config/presets.js +187 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/schema.d.ts +16 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +24 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/contracts/harness.d.ts +86 -0
- package/dist/contracts/harness.d.ts.map +1 -0
- package/dist/contracts/harness.js +2 -0
- package/dist/contracts/harness.js.map +1 -0
- package/dist/contracts/index.d.ts +3 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/preset.d.ts +54 -20
- package/dist/contracts/preset.d.ts.map +1 -1
- package/dist/contracts/validator.d.ts +33 -0
- package/dist/contracts/validator.d.ts.map +1 -0
- package/dist/contracts/validator.js +23 -0
- package/dist/contracts/validator.js.map +1 -0
- package/dist/index.d.ts +18 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/runtime/agent.d.ts +22 -0
- package/dist/runtime/agent.d.ts.map +1 -0
- package/dist/runtime/agent.js +47 -0
- package/dist/runtime/agent.js.map +1 -0
- package/dist/runtime/approval-gate.d.ts +17 -0
- package/dist/runtime/approval-gate.d.ts.map +1 -0
- package/dist/runtime/approval-gate.js +18 -0
- package/dist/runtime/approval-gate.js.map +1 -0
- package/dist/runtime/command.d.ts +14 -0
- package/dist/runtime/command.d.ts.map +1 -0
- package/dist/runtime/command.js +33 -0
- package/dist/runtime/command.js.map +1 -0
- package/dist/runtime/diff-inspector.d.ts +7 -0
- package/dist/runtime/diff-inspector.d.ts.map +1 -0
- package/dist/runtime/diff-inspector.js +24 -0
- package/dist/runtime/diff-inspector.js.map +1 -0
- package/dist/runtime/executor.d.ts +21 -0
- package/dist/runtime/executor.d.ts.map +1 -0
- package/dist/runtime/executor.js +142 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/intake.d.ts +11 -0
- package/dist/runtime/intake.d.ts.map +1 -0
- package/dist/runtime/intake.js +33 -0
- package/dist/runtime/intake.js.map +1 -0
- package/dist/runtime/package-manager.d.ts +14 -0
- package/dist/runtime/package-manager.d.ts.map +1 -0
- package/dist/runtime/package-manager.js +20 -0
- package/dist/runtime/package-manager.js.map +1 -0
- package/dist/runtime/policy-engine.d.ts +7 -0
- package/dist/runtime/policy-engine.d.ts.map +1 -0
- package/dist/runtime/policy-engine.js +8 -0
- package/dist/runtime/policy-engine.js.map +1 -0
- package/dist/runtime/provider-runner.d.ts +18 -0
- package/dist/runtime/provider-runner.d.ts.map +1 -0
- package/dist/runtime/provider-runner.js +45 -0
- package/dist/runtime/provider-runner.js.map +1 -0
- package/package.json +24 -19
- package/schemas/harness.schema.json +41 -0
- package/schemas/preset.schema.json +62 -0
package/README.md
CHANGED
|
@@ -19,6 +19,17 @@ import {
|
|
|
19
19
|
validationDetails,
|
|
20
20
|
parseAgentResponse,
|
|
21
21
|
validateStageResponse,
|
|
22
|
+
loadHarnessConfig,
|
|
23
|
+
readManifest,
|
|
24
|
+
defaultPolicy,
|
|
25
|
+
defaultAgents,
|
|
26
|
+
policyProblems,
|
|
27
|
+
agentProblems,
|
|
28
|
+
formatConfigError,
|
|
29
|
+
resolvePresets,
|
|
30
|
+
presetPackageName,
|
|
31
|
+
presetFile,
|
|
32
|
+
presetDocument,
|
|
22
33
|
validatePolicy,
|
|
23
34
|
findOutOfScopeChanges,
|
|
24
35
|
isCommandAllowed,
|
|
@@ -32,17 +43,47 @@ Individual modules are also exported for narrower imports:
|
|
|
32
43
|
```js
|
|
33
44
|
import { detectPackageManager } from '@pedyc/harness-core/package-manager'
|
|
34
45
|
import { runOrchestrator } from '@pedyc/harness-core/orchestrator'
|
|
46
|
+
import { loadHarnessConfig } from '@pedyc/harness-core/config'
|
|
35
47
|
```
|
|
36
48
|
|
|
49
|
+
- `config` — the only module that reads a project's configuration documents.
|
|
50
|
+
`loadHarnessConfig(root)` resolves `.harness/harness.json` when there is one,
|
|
51
|
+
falls back to the conventional `.harness/policy.json` and `.harness/agents.json`,
|
|
52
|
+
then to the documents an installed preset provides, and finally to built-in
|
|
53
|
+
defaults. It returns either a complete configuration plus the sources it came
|
|
54
|
+
from, or a list of structured errors naming a file and a field. Nothing is
|
|
55
|
+
executed first, so a bad configuration fails before a run starts rather than
|
|
56
|
+
partway through one.
|
|
57
|
+
- `resolvePresets(root, names)` — preset resolution, exported from the same module.
|
|
58
|
+
A preset is an installed npm package exposing `preset.json`; the walk is
|
|
59
|
+
depth-first post-order, so a preset is loaded once however many chains reach it,
|
|
60
|
+
dependencies come before the presets that inherit from them, and re-entering a
|
|
61
|
+
package still on the stack is reported as a cycle listing the whole loop. Errors
|
|
62
|
+
are the same structured `HarnessConfigError` values the loader returns. Pass a
|
|
63
|
+
short name through `presetPackageName` first: `vue` becomes
|
|
64
|
+
`@pedyc/harness-preset-vue`, while anything containing `/` is a package name
|
|
65
|
+
already.
|
|
37
66
|
- `package-manager` / `command` — lockfile detection and command execution.
|
|
38
67
|
- `intake` / `schema` / `agent` — task normalization, Ajv validation and Agent
|
|
39
68
|
response parsing.
|
|
40
69
|
- `policy` / `provider` / `orchestrator` — path policy, Provider routing and the
|
|
41
70
|
four-phase execution loop.
|
|
42
71
|
|
|
72
|
+
The source is layered `contracts/` → `config/` → `runtime/`, with dependencies
|
|
73
|
+
pointing one way: `contracts/` holds pure types and schema compilation and never
|
|
74
|
+
touches the file system, `config/` owns every configuration read, and `runtime/`
|
|
75
|
+
executes against values `config/` already resolved.
|
|
76
|
+
|
|
43
77
|
`runOrchestrator({ dryRun: true })` skips every Agent Provider and verification gate
|
|
44
78
|
and returns a structured passing result.
|
|
45
79
|
|
|
80
|
+
## Changelog
|
|
81
|
+
|
|
82
|
+
All four Harness packages share one version number and are released together, so
|
|
83
|
+
release notes for this package live in the repository changelog:
|
|
84
|
+
|
|
85
|
+
https://github.com/pedyc/pedyc-harness/blob/main/CHANGELOG.md
|
|
86
|
+
|
|
46
87
|
## License
|
|
47
88
|
|
|
48
89
|
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConfigProblem } from './json.js';
|
|
2
|
+
/**
|
|
3
|
+
* Checks an agent configuration read from disk or declared inline in the manifest.
|
|
4
|
+
*
|
|
5
|
+
* The document is untrusted JSON, so this takes `unknown` and reports every
|
|
6
|
+
* problem it finds rather than throwing.
|
|
7
|
+
*
|
|
8
|
+
* `verify` and the config loader both call this, so a project cannot be valid
|
|
9
|
+
* for one entry point and invalid for the other.
|
|
10
|
+
*/
|
|
11
|
+
export declare const agentProblems: (agents: unknown) => ConfigProblem[];
|
|
12
|
+
/** The first problem, or `null` when the document may be treated as an `AgentsConfig`. */
|
|
13
|
+
export declare const validateAgents: (agents: unknown) => string | null;
|
|
14
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/config/agents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAI9C;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,OAAO,KAAG,aAAa,EA0B5D,CAAA;AAED,0FAA0F;AAC1F,eAAO,MAAM,cAAc,GAAI,QAAQ,OAAO,KAAG,MAAM,GAAG,IACf,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { asRecord } from './json.js';
|
|
2
|
+
const roles = ['planner', 'coder', 'tester', 'reviewer'];
|
|
3
|
+
/**
|
|
4
|
+
* Checks an agent configuration read from disk or declared inline in the manifest.
|
|
5
|
+
*
|
|
6
|
+
* The document is untrusted JSON, so this takes `unknown` and reports every
|
|
7
|
+
* problem it finds rather than throwing.
|
|
8
|
+
*
|
|
9
|
+
* `verify` and the config loader both call this, so a project cannot be valid
|
|
10
|
+
* for one entry point and invalid for the other.
|
|
11
|
+
*/
|
|
12
|
+
export const agentProblems = (agents) => {
|
|
13
|
+
const candidate = asRecord(agents);
|
|
14
|
+
if (!candidate)
|
|
15
|
+
return [{ message: 'Harness agents must be an object.' }];
|
|
16
|
+
const providers = asRecord(candidate.providers);
|
|
17
|
+
if (!providers)
|
|
18
|
+
return [{ field: 'providers', message: 'Harness agents must define a providers object.' }];
|
|
19
|
+
const problems = [];
|
|
20
|
+
for (const [provider, config] of Object.entries(providers)) {
|
|
21
|
+
const entry = asRecord(config);
|
|
22
|
+
if (!entry || typeof entry.command !== 'string' || !entry.command.trim() || !Array.isArray(entry.args)) {
|
|
23
|
+
problems.push({
|
|
24
|
+
field: `providers.${provider}`,
|
|
25
|
+
message: `Harness provider '${provider}' must define a command and an args array.`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
for (const role of roles) {
|
|
30
|
+
const config = asRecord(candidate[role]);
|
|
31
|
+
if (!config || !['internal', 'external'].includes(config.mode)) {
|
|
32
|
+
problems.push({ field: role, message: `Harness agent '${role}' must declare mode internal or external.` });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return problems;
|
|
36
|
+
};
|
|
37
|
+
/** The first problem, or `null` when the document may be treated as an `AgentsConfig`. */
|
|
38
|
+
export const validateAgents = (agents) => agentProblems(agents)[0]?.message ?? null;
|
|
39
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/config/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGpC,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAA;AAEjE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAe,EAAmB,EAAE;IAChE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,SAAS;QAAE,OAAO,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAA;IAEzE,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IAC/C,IAAI,CAAC,SAAS;QAAE,OAAO,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gDAAgD,EAAE,CAAC,CAAA;IAE1G,MAAM,QAAQ,GAAoB,EAAE,CAAA;IACpC,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3D,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;QAC9B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACvG,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,aAAa,QAAQ,EAAE;gBAC9B,OAAO,EAAE,qBAAqB,QAAQ,4CAA4C;aACnF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACxC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAc,CAAC,EAAE,CAAC;YACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,kBAAkB,IAAI,2CAA2C,EAAE,CAAC,CAAA;QAC5G,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,0FAA0F;AAC1F,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAe,EAAiB,EAAE,CAC/D,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,IAAI,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { compileSchema } from './schema.js';
|
|
2
|
+
import type { ErrorObject } from 'ajv';
|
|
3
|
+
/** How a bundled schema is named in an error, since it is not part of the project. */
|
|
4
|
+
export declare const bundledSchemaFile: (name: string) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Compiles, and caches, one schema bundled with this package.
|
|
7
|
+
*
|
|
8
|
+
* Throws when the schema cannot be read: a missing bundled schema means the
|
|
9
|
+
* installation is incomplete, which the caller reports rather than masking.
|
|
10
|
+
*/
|
|
11
|
+
export declare const bundledValidator: (name: string) => ReturnType<typeof compileSchema>;
|
|
12
|
+
/** Turns one Ajv failure into the dot path of the field it is about. */
|
|
13
|
+
export declare const fieldOf: (error: ErrorObject) => string | undefined;
|
|
14
|
+
//# sourceMappingURL=bundled.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled.d.ts","sourceRoot":"","sources":["../../src/config/bundled.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAYtC,sFAAsF;AACtF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAAyC,CAAA;AAI1F;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,UAAU,CAAC,OAAO,aAAa,CAM9E,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,OAAO,GAAI,OAAO,WAAW,KAAG,MAAM,GAAG,SAMrD,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { compileSchema } from './schema.js';
|
|
4
|
+
// Bundled schemas are the contracts a project and a preset are checked against,
|
|
5
|
+
// so the runtime reads its own copies rather than ones a project supplies: a
|
|
6
|
+
// project must not be able to loosen the rules its own configuration is validated
|
|
7
|
+
// against. The copies under `packages/core/schemas/` are derived from the
|
|
8
|
+
// repository's `schemas/` by `pnpm run schemas:sync`. Both this module's source and
|
|
9
|
+
// its compiled form sit two directories below the package root, so `../../schemas`
|
|
10
|
+
// resolves to `packages/core/schemas` either way.
|
|
11
|
+
const bundledPath = (name) => fileURLToPath(new URL(`../../schemas/${name}`, import.meta.url));
|
|
12
|
+
/** How a bundled schema is named in an error, since it is not part of the project. */
|
|
13
|
+
export const bundledSchemaFile = (name) => `packages/core/schemas/${name}`;
|
|
14
|
+
const validators = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* Compiles, and caches, one schema bundled with this package.
|
|
17
|
+
*
|
|
18
|
+
* Throws when the schema cannot be read: a missing bundled schema means the
|
|
19
|
+
* installation is incomplete, which the caller reports rather than masking.
|
|
20
|
+
*/
|
|
21
|
+
export const bundledValidator = (name) => {
|
|
22
|
+
const cached = validators.get(name);
|
|
23
|
+
if (cached)
|
|
24
|
+
return cached;
|
|
25
|
+
const compiled = compileSchema(JSON.parse(readFileSync(bundledPath(name), 'utf8')));
|
|
26
|
+
validators.set(name, compiled);
|
|
27
|
+
return compiled;
|
|
28
|
+
};
|
|
29
|
+
/** Turns one Ajv failure into the dot path of the field it is about. */
|
|
30
|
+
export const fieldOf = (error) => {
|
|
31
|
+
const params = error.params;
|
|
32
|
+
const path = error.instancePath.replace(/^\//, '').replaceAll('/', '.');
|
|
33
|
+
const leaf = params.missingProperty ?? params.additionalProperty;
|
|
34
|
+
if (leaf)
|
|
35
|
+
return path ? `${path}.${leaf}` : leaf;
|
|
36
|
+
return path || undefined;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=bundled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled.js","sourceRoot":"","sources":["../../src/config/bundled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,gFAAgF;AAChF,6EAA6E;AAC7E,kFAAkF;AAClF,0EAA0E;AAC1E,oFAAoF;AACpF,mFAAmF;AACnF,kDAAkD;AAClD,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE,CAC3C,aAAa,CAAC,IAAI,GAAG,CAAC,iBAAiB,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAElE,sFAAsF;AACtF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,yBAAyB,IAAI,EAAE,CAAA;AAE1F,MAAM,UAAU,GAAG,IAAI,GAAG,EAA4C,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAoC,EAAE;IACjF,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IACzB,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAW,CAAC,CAAA;IAC7F,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC9B,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAkB,EAAsB,EAAE;IAChE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAmE,CAAA;IACxF,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACvE,MAAM,IAAI,GAAG,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,kBAAkB,CAAA;IAChE,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAChD,OAAO,IAAI,IAAI,SAAS,CAAA;AAC1B,CAAC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AgentsConfig, Policy } from '../contracts/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The built-in policy a project with a manifest but no `policy.json` runs under.
|
|
4
|
+
*
|
|
5
|
+
* It has to be stack-neutral: Core must never grow a branch that knows which
|
|
6
|
+
* technology a project uses, so these are the same generic values every preset
|
|
7
|
+
* starts from and a preset only ever adds to them.
|
|
8
|
+
*/
|
|
9
|
+
export declare const defaultPolicy: () => Policy;
|
|
10
|
+
/**
|
|
11
|
+
* The built-in agent routing for a project with a manifest but no `agents.json`.
|
|
12
|
+
*
|
|
13
|
+
* No provider is configured, so the stages that need one report a structured
|
|
14
|
+
* failure until an adapter is declared. `verify` and `run --dry-run` never
|
|
15
|
+
* invoke a provider, which is what lets a freshly initialized project work
|
|
16
|
+
* before an adapter exists.
|
|
17
|
+
*/
|
|
18
|
+
export declare const defaultAgents: () => AgentsConfig;
|
|
19
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAEjE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,QAAO,MAQ/B,CAAA;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,QAAO,YAM/B,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in policy a project with a manifest but no `policy.json` runs under.
|
|
3
|
+
*
|
|
4
|
+
* It has to be stack-neutral: Core must never grow a branch that knows which
|
|
5
|
+
* technology a project uses, so these are the same generic values every preset
|
|
6
|
+
* starts from and a preset only ever adds to them.
|
|
7
|
+
*/
|
|
8
|
+
export const defaultPolicy = () => ({
|
|
9
|
+
maxIterations: 3,
|
|
10
|
+
allowedProductPaths: ['src/'],
|
|
11
|
+
protectedPaths: [],
|
|
12
|
+
requiredChecks: [],
|
|
13
|
+
forbiddenCommands: [],
|
|
14
|
+
allowedAgentCommands: [],
|
|
15
|
+
agentTimeoutMs: 300000,
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* The built-in agent routing for a project with a manifest but no `agents.json`.
|
|
19
|
+
*
|
|
20
|
+
* No provider is configured, so the stages that need one report a structured
|
|
21
|
+
* failure until an adapter is declared. `verify` and `run --dry-run` never
|
|
22
|
+
* invoke a provider, which is what lets a freshly initialized project work
|
|
23
|
+
* before an adapter exists.
|
|
24
|
+
*/
|
|
25
|
+
export const defaultAgents = () => ({
|
|
26
|
+
providers: {},
|
|
27
|
+
planner: { mode: 'internal' },
|
|
28
|
+
coder: { mode: 'external', provider: 'custom' },
|
|
29
|
+
tester: { mode: 'external', provider: 'custom' },
|
|
30
|
+
reviewer: { mode: 'external', provider: 'custom' },
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAW,EAAE,CAAC,CAAC;IAC1C,aAAa,EAAE,CAAC;IAChB,mBAAmB,EAAE,CAAC,MAAM,CAAC;IAC7B,cAAc,EAAE,EAAE;IAClB,cAAc,EAAE,EAAE;IAClB,iBAAiB,EAAE,EAAE;IACrB,oBAAoB,EAAE,EAAE;IACxB,cAAc,EAAE,MAAM;CACvB,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAiB,EAAE,CAAC,CAAC;IAChD,SAAS,EAAE,EAAE;IACb,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;IAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE;IAC/C,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE;IAChD,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE;CACnD,CAAC,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ConfigErrorCode, HarnessConfigError } from '../contracts/index.js';
|
|
2
|
+
/** Builds one structured configuration error. */
|
|
3
|
+
export declare const configError: (code: ConfigErrorCode, file: string, message: string, field?: string) => HarnessConfigError;
|
|
4
|
+
/**
|
|
5
|
+
* Renders an error the way the CLI prints it.
|
|
6
|
+
*
|
|
7
|
+
* The file and the field are both part of the sentence on purpose: "the
|
|
8
|
+
* configuration is invalid" is not actionable, ".harness/harness.json → presets"
|
|
9
|
+
* is.
|
|
10
|
+
*/
|
|
11
|
+
export declare const formatConfigError: (error: HarnessConfigError) => string;
|
|
12
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/config/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAEhF,iDAAiD;AACjD,eAAO,MAAM,WAAW,GACtB,MAAM,eAAe,EACrB,MAAM,MAAM,EACZ,SAAS,MAAM,EACf,QAAQ,MAAM,KACb,kBAAsG,CAAA;AAEzG;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,kBAAkB,KAAG,MACc,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Builds one structured configuration error. */
|
|
2
|
+
export const configError = (code, file, message, field) => (field === undefined ? { code, file, message } : { code, file, field, message });
|
|
3
|
+
/**
|
|
4
|
+
* Renders an error the way the CLI prints it.
|
|
5
|
+
*
|
|
6
|
+
* The file and the field are both part of the sentence on purpose: "the
|
|
7
|
+
* configuration is invalid" is not actionable, ".harness/harness.json → presets"
|
|
8
|
+
* is.
|
|
9
|
+
*/
|
|
10
|
+
export const formatConfigError = (error) => `${error.file}${error.field ? ` → ${error.field}` : ''}: ${error.message}`;
|
|
11
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/config/errors.ts"],"names":[],"mappings":"AAEA,iDAAiD;AACjD,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,IAAqB,EACrB,IAAY,EACZ,OAAe,EACf,KAAc,EACM,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;AAEzG;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAyB,EAAU,EAAE,CACrE,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { agentProblems, validateAgents } from './agents.js';
|
|
2
|
+
export { bundledSchemaFile, bundledValidator, fieldOf } from './bundled.js';
|
|
3
|
+
export { defaultAgents, defaultPolicy } from './defaults.js';
|
|
4
|
+
export { configError, formatConfigError } from './errors.js';
|
|
5
|
+
export { asRecord } from './json.js';
|
|
6
|
+
export type { ConfigProblem } from './json.js';
|
|
7
|
+
export { harnessDirectory, loadHarnessConfig } from './loader.js';
|
|
8
|
+
export { manifestFile, manifestPath, readManifest } from './manifest.js';
|
|
9
|
+
export type { ManifestResult } from './manifest.js';
|
|
10
|
+
export { policyProblems, validatePolicy } from './policy.js';
|
|
11
|
+
export { presetDocument, presetFile, presetPackageName, presetSchema, resolvePresets } from './presets.js';
|
|
12
|
+
export type { PresetsResult } from './presets.js';
|
|
13
|
+
export { compileSchema, createAjv, createValidators, loadSchemas, readSchema, validationDetails, } from './schema.js';
|
|
14
|
+
export type { HarnessSchemas, HarnessValidators, ResponseValidator, SchemaErrorFormatter, } from './schema.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC1G,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EACL,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// The configuration layer.
|
|
2
|
+
//
|
|
3
|
+
// Everything that touches a project's configuration documents lives here, so
|
|
4
|
+
// the runtime only ever receives values that have already been read, checked and
|
|
5
|
+
// resolved. Dependencies point one way: `runtime` may import `config`, never the
|
|
6
|
+
// reverse, and `contracts` stays free of both file system access and side
|
|
7
|
+
// effects.
|
|
8
|
+
export { agentProblems, validateAgents } from './agents.js';
|
|
9
|
+
export { bundledSchemaFile, bundledValidator, fieldOf } from './bundled.js';
|
|
10
|
+
export { defaultAgents, defaultPolicy } from './defaults.js';
|
|
11
|
+
export { configError, formatConfigError } from './errors.js';
|
|
12
|
+
export { asRecord } from './json.js';
|
|
13
|
+
export { harnessDirectory, loadHarnessConfig } from './loader.js';
|
|
14
|
+
export { manifestFile, manifestPath, readManifest } from './manifest.js';
|
|
15
|
+
export { policyProblems, validatePolicy } from './policy.js';
|
|
16
|
+
export { presetDocument, presetFile, presetPackageName, presetSchema, resolvePresets } from './presets.js';
|
|
17
|
+
export { compileSchema, createAjv, createValidators, loadSchemas, readSchema, validationDetails, } from './schema.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,EAAE;AACF,6EAA6E;AAC7E,iFAAiF;AACjF,iFAAiF;AACjF,0EAA0E;AAC1E,WAAW;AAEX,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAExE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAE1G,OAAO,EACL,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,iBAAiB,GAClB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Narrows untrusted JSON to an object without asserting anything about its keys. */
|
|
2
|
+
export declare const asRecord: (value: unknown) => Record<string, unknown> | null;
|
|
3
|
+
/**
|
|
4
|
+
* One reason a document is not usable configuration.
|
|
5
|
+
*
|
|
6
|
+
* The field is optional because some problems are about the document as a whole
|
|
7
|
+
* ("policy must be an object"), but naming it whenever it is known is what makes
|
|
8
|
+
* the CLI's configuration errors actionable.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConfigProblem {
|
|
11
|
+
field?: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/config/json.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAG1D,CAAA;AAEV;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/config/json.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAkC,EAAE,CACzE,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;IAClE,CAAC,CAAC,KAAgC;IAClC,CAAC,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LoadConfigResult } from '../contracts/index.js';
|
|
2
|
+
/** The governance directory inside a target project. */
|
|
3
|
+
export declare const harnessDirectory = ".harness";
|
|
4
|
+
/**
|
|
5
|
+
* Turns a project's configuration documents into one validated input.
|
|
6
|
+
*
|
|
7
|
+
* Two layouts are supported. A project with `.harness/harness.json` declares its
|
|
8
|
+
* sources through the manifest, presets included; a project without one keeps
|
|
9
|
+
* reading `.harness/policy.json` and `.harness/agents.json`, because migrating to
|
|
10
|
+
* the manifest is meant to be incremental rather than a flag day.
|
|
11
|
+
*
|
|
12
|
+
* Nothing is executed before every document has been read and checked, so a bad
|
|
13
|
+
* configuration fails as a structured error rather than midway through a run.
|
|
14
|
+
*/
|
|
15
|
+
export declare const loadHarnessConfig: (root: string) => LoadConfigResult;
|
|
16
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAMV,gBAAgB,EAIjB,MAAM,uBAAuB,CAAA;AAE9B,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,aAAa,CAAA;AAqL1C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,gBAsDhD,CAAA"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { agentProblems } from './agents.js';
|
|
4
|
+
import { defaultAgents, defaultPolicy } from './defaults.js';
|
|
5
|
+
import { configError } from './errors.js';
|
|
6
|
+
import { policyProblems } from './policy.js';
|
|
7
|
+
import { manifestFile, manifestPath, readManifest } from './manifest.js';
|
|
8
|
+
import { presetFile, resolvePresets } from './presets.js';
|
|
9
|
+
/** The governance directory inside a target project. */
|
|
10
|
+
export const harnessDirectory = '.harness';
|
|
11
|
+
const describe = (error) => (error instanceof Error ? error.message : 'unknown error');
|
|
12
|
+
/**
|
|
13
|
+
* Resolves a manifest path and proves it stays inside `.harness/`.
|
|
14
|
+
*
|
|
15
|
+
* A manifest may only point at documents that belong to this project's
|
|
16
|
+
* governance definition. Letting it escape would make a committed configuration
|
|
17
|
+
* file able to pull in anything the process can read, and a preset is held to
|
|
18
|
+
* the same rule inside its own package.
|
|
19
|
+
*
|
|
20
|
+
* Returns the repository-relative POSIX path, or `null` when the path escapes.
|
|
21
|
+
*/
|
|
22
|
+
const insideHarness = (root, path) => {
|
|
23
|
+
if (isAbsolute(path))
|
|
24
|
+
return null;
|
|
25
|
+
const harnessRoot = join(root, harnessDirectory);
|
|
26
|
+
const offset = relative(harnessRoot, resolve(harnessRoot, path));
|
|
27
|
+
if (!offset || offset.startsWith('..') || isAbsolute(offset))
|
|
28
|
+
return null;
|
|
29
|
+
return `${harnessDirectory}/${offset.split(sep).join('/')}`;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Reads one JSON document.
|
|
33
|
+
*
|
|
34
|
+
* `label` is what an error names: a project document is named by its
|
|
35
|
+
* repository-relative path, and a preset's document by its package-qualified one,
|
|
36
|
+
* because the two live in different places and a reader has to be able to open
|
|
37
|
+
* what the message points at.
|
|
38
|
+
*/
|
|
39
|
+
const readDocument = (base, path, label = path) => {
|
|
40
|
+
let raw;
|
|
41
|
+
try {
|
|
42
|
+
raw = readFileSync(join(base, path), 'utf8');
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return { errors: [configError('config_file_unreadable', label, `The file could not be read: ${describe(error)}`)] };
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
return { value: JSON.parse(raw) };
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return { errors: [configError('config_file_invalid_json', label, `The file is not valid JSON: ${describe(error)}`)] };
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const problemsToErrors = (problems, code, file, prefix) => problems.map(({ field, message }) => configError(code, file, message, prefix && field ? `${prefix}.${field}` : field));
|
|
55
|
+
/**
|
|
56
|
+
* Reads one configuration document.
|
|
57
|
+
*
|
|
58
|
+
* Precedence is source selection, not field merging: a manifest-declared
|
|
59
|
+
* document, then the project's conventional file, then the presets, then the
|
|
60
|
+
* built-in defaults. A project's own document outranks its presets because it is
|
|
61
|
+
* a statement about this project while a preset is a statement about its stack;
|
|
62
|
+
* among presets the last one wins, and the resolver returns them dependencies
|
|
63
|
+
* first, so a preset that extends another overrides it.
|
|
64
|
+
*
|
|
65
|
+
* Which value wins when two sources both declare the same field is a separate
|
|
66
|
+
* question that the merge layer (M17) owns.
|
|
67
|
+
*/
|
|
68
|
+
const resolveDocument = (root, manifest, presets, kind) => {
|
|
69
|
+
const declared = manifest?.[kind.kind];
|
|
70
|
+
if (typeof declared === 'string') {
|
|
71
|
+
const file = insideHarness(root, declared);
|
|
72
|
+
if (!file) {
|
|
73
|
+
return { errors: [configError('config_path_outside_harness', manifestFile, `${kind.kind} must point at a file inside ${harnessDirectory}/; '${declared}' does not.`, kind.kind)] };
|
|
74
|
+
}
|
|
75
|
+
if (!existsSync(join(root, file))) {
|
|
76
|
+
return { errors: [configError('config_file_missing', manifestFile, `${kind.kind} points at ${file}, which does not exist.`, kind.kind)] };
|
|
77
|
+
}
|
|
78
|
+
const document = readDocument(root, file);
|
|
79
|
+
if ('errors' in document)
|
|
80
|
+
return document;
|
|
81
|
+
const problems = kind.problems(document.value);
|
|
82
|
+
if (problems.length)
|
|
83
|
+
return { errors: problemsToErrors(problems, 'config_file_invalid', file) };
|
|
84
|
+
return { value: document.value, source: { kind: kind.kind, location: file, active: true } };
|
|
85
|
+
}
|
|
86
|
+
if (declared !== undefined) {
|
|
87
|
+
const problems = kind.problems(declared);
|
|
88
|
+
if (problems.length)
|
|
89
|
+
return { errors: problemsToErrors(problems, 'manifest_invalid', manifestFile, kind.kind) };
|
|
90
|
+
return {
|
|
91
|
+
value: declared,
|
|
92
|
+
source: { kind: kind.kind, location: `${manifestFile} (inline)`, active: true },
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const conventional = `${harnessDirectory}/${kind.kind}.json`;
|
|
96
|
+
if (existsSync(join(root, conventional))) {
|
|
97
|
+
const document = readDocument(root, conventional);
|
|
98
|
+
if ('errors' in document)
|
|
99
|
+
return document;
|
|
100
|
+
const problems = kind.problems(document.value);
|
|
101
|
+
if (problems.length)
|
|
102
|
+
return { errors: problemsToErrors(problems, 'config_file_invalid', conventional) };
|
|
103
|
+
return { value: document.value, source: { kind: kind.kind, location: conventional, active: true } };
|
|
104
|
+
}
|
|
105
|
+
for (const preset of [...presets].reverse()) {
|
|
106
|
+
const path = preset.manifest[kind.kind];
|
|
107
|
+
if (path === undefined)
|
|
108
|
+
continue;
|
|
109
|
+
const label = presetFile(preset, path);
|
|
110
|
+
const document = readDocument(preset.directory, path, label);
|
|
111
|
+
if ('errors' in document)
|
|
112
|
+
return document;
|
|
113
|
+
const problems = kind.problems(document.value);
|
|
114
|
+
if (problems.length)
|
|
115
|
+
return { errors: problemsToErrors(problems, 'config_file_invalid', label) };
|
|
116
|
+
return { value: document.value, source: { kind: kind.kind, location: label, active: true } };
|
|
117
|
+
}
|
|
118
|
+
return { value: kind.fallback(), source: { kind: kind.kind, location: 'built-in defaults', active: true } };
|
|
119
|
+
};
|
|
120
|
+
const policyKind = {
|
|
121
|
+
kind: 'policy',
|
|
122
|
+
problems: policyProblems,
|
|
123
|
+
fallback: defaultPolicy,
|
|
124
|
+
};
|
|
125
|
+
const agentsKind = {
|
|
126
|
+
kind: 'agents',
|
|
127
|
+
problems: agentProblems,
|
|
128
|
+
fallback: defaultAgents,
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Records the manifest's remaining sources: the ones no runtime consumes yet.
|
|
132
|
+
*
|
|
133
|
+
* Reporting them keeps `doctor` honest: a declared document that is silently
|
|
134
|
+
* ignored is the same failure mode as a fallback that never says it fell back.
|
|
135
|
+
*/
|
|
136
|
+
const recordDeclaredSources = (root, manifest) => {
|
|
137
|
+
const sources = [];
|
|
138
|
+
const errors = [];
|
|
139
|
+
if (manifest.verification !== undefined) {
|
|
140
|
+
const file = insideHarness(root, manifest.verification);
|
|
141
|
+
if (!file) {
|
|
142
|
+
errors.push(configError('config_path_outside_harness', manifestFile, `verification must point at a file inside ${harnessDirectory}/; '${manifest.verification}' does not.`, 'verification'));
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
sources.push({ kind: 'verification', location: file, active: false });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const rule of manifest.rules ?? []) {
|
|
149
|
+
const file = insideHarness(root, rule);
|
|
150
|
+
if (!file) {
|
|
151
|
+
errors.push(configError('config_path_outside_harness', manifestFile, `rules must point at a file inside ${harnessDirectory}/; '${rule}' does not.`, 'rules'));
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
sources.push({ kind: 'rules', location: file, active: false });
|
|
155
|
+
}
|
|
156
|
+
return errors.length > 0 ? { errors } : { sources };
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Turns a project's configuration documents into one validated input.
|
|
160
|
+
*
|
|
161
|
+
* Two layouts are supported. A project with `.harness/harness.json` declares its
|
|
162
|
+
* sources through the manifest, presets included; a project without one keeps
|
|
163
|
+
* reading `.harness/policy.json` and `.harness/agents.json`, because migrating to
|
|
164
|
+
* the manifest is meant to be incremental rather than a flag day.
|
|
165
|
+
*
|
|
166
|
+
* Nothing is executed before every document has been read and checked, so a bad
|
|
167
|
+
* configuration fails as a structured error rather than midway through a run.
|
|
168
|
+
*/
|
|
169
|
+
export const loadHarnessConfig = (root) => {
|
|
170
|
+
const harnessRoot = join(root, harnessDirectory);
|
|
171
|
+
if (!existsSync(harnessRoot)) {
|
|
172
|
+
return {
|
|
173
|
+
ok: false,
|
|
174
|
+
errors: [configError('harness_directory_missing', harnessDirectory, `The governance directory ${harnessDirectory}/ was not found. Run \`pedyc-harness init\` first.`)],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const sources = [];
|
|
178
|
+
let manifest = null;
|
|
179
|
+
if (existsSync(manifestPath(root))) {
|
|
180
|
+
const result = readManifest(root);
|
|
181
|
+
if (!result.ok)
|
|
182
|
+
return { ok: false, errors: result.errors };
|
|
183
|
+
manifest = result.manifest;
|
|
184
|
+
sources.push({ kind: 'manifest', location: manifestFile, active: true });
|
|
185
|
+
}
|
|
186
|
+
const resolved = resolvePresets(root, manifest?.presets ?? []);
|
|
187
|
+
if (!resolved.ok)
|
|
188
|
+
return { ok: false, errors: resolved.errors };
|
|
189
|
+
const presets = resolved.presets;
|
|
190
|
+
if (manifest) {
|
|
191
|
+
const declared = recordDeclaredSources(root, manifest);
|
|
192
|
+
if ('errors' in declared)
|
|
193
|
+
return { ok: false, errors: declared.errors };
|
|
194
|
+
sources.push(...declared.sources);
|
|
195
|
+
}
|
|
196
|
+
const policy = resolveDocument(root, manifest, presets, policyKind);
|
|
197
|
+
if ('errors' in policy)
|
|
198
|
+
return { ok: false, errors: policy.errors };
|
|
199
|
+
const agents = resolveDocument(root, manifest, presets, agentsKind);
|
|
200
|
+
if ('errors' in agents)
|
|
201
|
+
return { ok: false, errors: agents.errors };
|
|
202
|
+
// Reported in the order a reader resolves them: the entry point, the values
|
|
203
|
+
// that were actually read, then the declarations that produced them.
|
|
204
|
+
const ordered = [
|
|
205
|
+
...sources.filter(({ kind }) => kind === 'manifest'),
|
|
206
|
+
policy.source,
|
|
207
|
+
agents.source,
|
|
208
|
+
...presets.map(({ packageName }) => ({ kind: 'preset', location: packageName, active: true })),
|
|
209
|
+
...sources.filter(({ kind }) => kind !== 'manifest'),
|
|
210
|
+
];
|
|
211
|
+
const config = {
|
|
212
|
+
root,
|
|
213
|
+
manifest,
|
|
214
|
+
policy: policy.value,
|
|
215
|
+
agents: agents.value,
|
|
216
|
+
presets,
|
|
217
|
+
sources: ordered,
|
|
218
|
+
};
|
|
219
|
+
return { ok: true, config };
|
|
220
|
+
};
|
|
221
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
|