@sentropic/harness 0.4.0 → 0.5.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.
Files changed (39) hide show
  1. package/README.md +84 -3
  2. package/dist/branch-md/parse.d.ts +2 -1
  3. package/dist/branch-md/parse.d.ts.map +1 -1
  4. package/dist/branch-md/parse.js +12 -6
  5. package/dist/branch-md/parse.js.map +1 -1
  6. package/dist/checks/scope-check.d.ts +2 -0
  7. package/dist/checks/scope-check.d.ts.map +1 -1
  8. package/dist/checks/scope-check.js +11 -0
  9. package/dist/checks/scope-check.js.map +1 -1
  10. package/dist/cli/mechanical-verbs.d.ts.map +1 -1
  11. package/dist/cli/mechanical-verbs.js +6 -18
  12. package/dist/cli/mechanical-verbs.js.map +1 -1
  13. package/dist/cli/run.d.ts +0 -8
  14. package/dist/cli/run.d.ts.map +1 -1
  15. package/dist/cli/run.js +20 -9
  16. package/dist/cli/run.js.map +1 -1
  17. package/dist/cli/scope.d.ts.map +1 -1
  18. package/dist/cli/scope.js +8 -4
  19. package/dist/cli/scope.js.map +1 -1
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/profile/document.d.ts +16 -0
  25. package/dist/profile/document.d.ts.map +1 -0
  26. package/dist/profile/document.js +71 -0
  27. package/dist/profile/document.js.map +1 -0
  28. package/dist/profile/profile.d.ts +16 -0
  29. package/dist/profile/profile.d.ts.map +1 -1
  30. package/dist/profile/resolve.d.ts +7 -0
  31. package/dist/profile/resolve.d.ts.map +1 -0
  32. package/dist/profile/resolve.js +63 -0
  33. package/dist/profile/resolve.js.map +1 -0
  34. package/dist/scope/scope-boundary.d.ts +2 -1
  35. package/dist/scope/scope-boundary.d.ts.map +1 -1
  36. package/dist/scope/scope-boundary.js +6 -1
  37. package/dist/scope/scope-boundary.js.map +1 -1
  38. package/package.json +1 -1
  39. package/schema/harness-profile.schema.json +49 -0
package/README.md CHANGED
@@ -11,7 +11,7 @@ behind a pluggable **profile** SPI. The NATIVE sentropic replacement for superpo
11
11
  - **Policy as data**: the Sentropic rules (scope paths, exception grammar, thresholds) live
12
12
  in a `sentropic` profile module behind the `HarnessProfile` interface. The check **kernel**
13
13
  is profile-driven (a second `stub` profile exercises it with divergent policy); full
14
- plugin-surface genericity (plan-adapter SPI, profile resolution, `harness init`/`audit`) is
14
+ plugin-surface genericity (plan-adapter SPI and additional checks) is
15
15
  the G1–G4 follow-on tracked in `SPEC_STUDY_HARNESS_GENERICITY_AUDIT.md`.
16
16
 
17
17
  > Status: **BR-42h** — published to npm (D7 lifted 2026-06-08). Installs like every other
@@ -32,8 +32,89 @@ harness check branch --current-branch "$(git branch --show-current)" --expected-
32
32
  harness check scope --branch-md BRANCH.md --staged-files "$(git diff --cached --name-only | paste -sd,)" [--json]
33
33
  ```
34
34
 
35
- `--json` emits a neutral artifact. `--profile sentropic|stub` selects the policy pack (default
36
- `sentropic`). In an `@sentropic` repo, `make scope-check` wraps the staged+unstaged scope check.
35
+ `--json` emits a neutral artifact. Policy selection for `check`, `verify`, `audit` and `init`:
36
+ explicit `--profile sentropic|stub` > `--profile-file <path>` > repository-root
37
+ `harness.profile.json` > built-in `sentropic`. An explicit built-in ignores lower-priority files,
38
+ even if they are invalid. Unknown built-in names are errors. In an `@sentropic` repo,
39
+ `make scope-check` wraps the staged+unstaged scope check.
40
+
41
+ ## Repository-owned profiles
42
+
43
+ Commit `harness.profile.json` at your Git root. Discovery walks upward to the nearest `.git`
44
+ directory or worktree file and checks only that root, including when invoked in a subdirectory.
45
+ Outside Git, the current directory is the root. `--profile-file` resolves relative to the current
46
+ directory; an absolute path also works. These files contain data only; no code is executed.
47
+
48
+ The published [JSON Schema](schema/harness-profile.schema.json) is also the runtime validation
49
+ contract. All objects reject unknown keys; fields are never coerced. Invalid configuration exits
50
+ with code **2**, including when `--json` is requested. Programmatic callers receive
51
+ `ProfileValidationError` with `code` and `path`; an unknown property has code `UNKNOWN_KEY`.
52
+ Other codes: `INVALID_PROFILE`, `INVALID_REGEX`, `PROFILE_READ`, `PROFILE_JSON`, `UNKNOWN_PROFILE`.
53
+ Unreadable or invalid selected files fail closed. Ordinary C1/C2 violations retain advisory exit 0.
54
+
55
+ A Rust + Node repository such as sentbase can start with:
56
+
57
+ ```json
58
+ {
59
+ "id": "sentbase",
60
+ "forbiddenPathDefaults": ["Cargo.toml", ".githooks/**", "LICENSE"],
61
+ "allowedPathDefaults": ["src/**", "web/**", "tests/**", "BRANCH.md"],
62
+ "conditionalPathDefaults": ["Cargo.lock", "package.json", "package-lock.json"],
63
+ "exceptionIdPattern": "^EXC-\\d+$",
64
+ "conditionalRequiresException": true,
65
+ "branchMatch": "exact",
66
+ "branchMd": {
67
+ "file": "BRANCH.md",
68
+ "allowedHeading": "Allowed Paths",
69
+ "forbiddenHeading": "Forbidden Paths",
70
+ "conditionalHeading": "Conditional Paths",
71
+ "planHeading": "Plan / Todo"
72
+ },
73
+ "commitMessage": {
74
+ "requiredPattern": "^(feat|fix|docs|test|chore|refactor): .+",
75
+ "forbiddenPatterns": ["Co-Authored-By:", "Claude-Session:", "Generated with"]
76
+ }
77
+ }
78
+ ```
79
+
80
+ ```bash
81
+ harness check scope --staged-files src/lib.rs,web/index.ts
82
+ harness check scope --profile-file ./harness.profile.json --staged-files LICENSE
83
+ harness check scope --commit-message 'feat: add endpoint'
84
+ harness init --profile sentropic --json > harness.profile.json
85
+ ```
86
+
87
+ | Field | Contract |
88
+ |---|---|
89
+ | `id` | Required nonempty profile identifier. |
90
+ | `forbiddenPathDefaults` | Required array of forbidden path globs; `[]` is valid. |
91
+ | `allowedPathDefaults`, `conditionalPathDefaults` | Optional default glob arrays; omitted means empty. |
92
+ | `exceptionIdPattern` | Required ECMAScript regex source for exception IDs, without `/` delimiters or flags. |
93
+ | `conditionalRequiresException` | Required boolean; when true, a declared matching exception permits conditional paths. |
94
+ | `branchMatch` | Required `exact` or `prefix` comparison for C1. |
95
+ | `branchMd` | Optional plan conventions; when present all five fields above are required. |
96
+ | `commitMessage` | Optional guards: required `forbiddenPatterns` array and optional `requiredPattern`, both regex sources. |
97
+ | `$schema` | Optional editor schema reference. |
98
+
99
+ Globs are repository-relative POSIX paths: `*` matches within one segment, `**` spans `/`,
100
+ and other characters are literal (no brace expansion, `?`, negation or implicit directory matching).
101
+ Empty paths, absolute paths, backslashes and `..` segments are rejected. Scope precedence is:
102
+ BRANCH allowed > BRANCH forbidden > BRANCH conditional > profile forbidden > profile conditional >
103
+ profile allowed > unknown. Thus an explicit branch grant can override a profile prohibition;
104
+ the example forbids `Cargo.toml`, `.githooks/**` and `LICENSE` by default.
105
+
106
+ Plans use `#` for the title, `##` for sections, bold bucket labels and backtick-quoted globs.
107
+ Bucket headings match case-insensitive prefixes, preserving parenthetical suffixes. `planHeading`
108
+ identifies the lot section; checkbox lots retain the `Lot` prefix. `exceptionIdPattern` also drives
109
+ exception extraction from plan text. Without `branchMd`, canonical headings apply and a plan is
110
+ read only via `--branch-md`. With `branchMd`, its `file` is relative to the Git root and is read
111
+ when present; `--branch-md` overrides it and is relative to the current directory. Missing explicit
112
+ plans are errors. Missing default plans leave the profile defaults in effect.
113
+
114
+ Commit guards run only when `--commit-message <text>` is supplied to scope, verify or audit.
115
+ Regexes inspect the entire message, including trailers, case-sensitively and without flags.
116
+ Built-in profiles have no commit guards. Both built-ins are valid schema documents, available via
117
+ `harness init --profile sentropic|stub --json`; loading those documents preserves their C1/C2 results.
37
118
 
38
119
  ## Verbs
39
120
 
@@ -1,3 +1,4 @@
1
+ import type { HarnessProfile } from '../profile/profile.js';
1
2
  export interface ParsedLotItem {
2
3
  text: string;
3
4
  checked: boolean;
@@ -15,5 +16,5 @@ export interface ParsedBranchMd {
15
16
  exceptions: string[];
16
17
  lots: ParsedLot[];
17
18
  }
18
- export declare function parseBranchMd(text: string): ParsedBranchMd;
19
+ export declare function parseBranchMd(text: string, profile?: HarnessProfile): ParsedBranchMd;
19
20
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/branch-md/parse.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAWD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CA4F1D"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/branch-md/parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAWD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,cAAc,CAkGpF"}
@@ -9,7 +9,11 @@ function backtickGlobs(line) {
9
9
  out.push(m[1]);
10
10
  return out;
11
11
  }
12
- export function parseBranchMd(text) {
12
+ export function parseBranchMd(text, profile) {
13
+ const conventions = profile?.branchMd;
14
+ const exception = profile
15
+ ? new RegExp('\\b(?:' + profile.exceptionIdPattern.source.replace(/^\^/, '').replace(/\$$/, '') + ')\\b', 'g')
16
+ : EXCEPTION;
13
17
  const lines = text.split(/\r?\n/);
14
18
  const result = {
15
19
  title: '',
@@ -39,11 +43,13 @@ export function parseBranchMd(text) {
39
43
  result.conditionalPaths.push(...globs);
40
44
  };
41
45
  for (const line of lines) {
42
- for (const m of line.matchAll(EXCEPTION))
46
+ for (const m of line.matchAll(exception))
43
47
  result.exceptions.push(m[0]);
44
48
  if (/^##\s+/.test(line)) {
45
49
  bucket = null;
46
- inPlan = /plan\s*\/\s*todo/i.test(line);
50
+ inPlan = conventions
51
+ ? line.toLowerCase().includes(conventions.planHeading.toLowerCase())
52
+ : /plan\s*\/\s*todo/i.test(line);
47
53
  currentLot = null;
48
54
  continue;
49
55
  }
@@ -52,17 +58,17 @@ export function parseBranchMd(text) {
52
58
  // closing `**` is NOT adjacent to "Paths". Match the prefix only (as Conditional
53
59
  // already did) — otherwise Allowed/Forbidden silently parse to empty on every
54
60
  // real BRANCH.md and in-scope files wrongly classify as `unknown`.
55
- if (/\*\*Allowed Paths/i.test(line)) {
61
+ if (line.toLowerCase().includes('**' + (conventions?.allowedHeading ?? 'Allowed Paths').toLowerCase())) {
56
62
  bucket = 'allowed';
57
63
  pushBucket(backtickGlobs(line));
58
64
  continue;
59
65
  }
60
- if (/\*\*Forbidden Paths/i.test(line)) {
66
+ if (line.toLowerCase().includes('**' + (conventions?.forbiddenHeading ?? 'Forbidden Paths').toLowerCase())) {
61
67
  bucket = 'forbidden';
62
68
  pushBucket(backtickGlobs(line));
63
69
  continue;
64
70
  }
65
- if (/\*\*Conditional Paths/i.test(line)) {
71
+ if (line.toLowerCase().includes('**' + (conventions?.conditionalHeading ?? 'Conditional Paths').toLowerCase())) {
66
72
  bucket = 'conditional';
67
73
  pushBucket(backtickGlobs(line));
68
74
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/branch-md/parse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/branch-md/parse.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,8 @@ export interface ScopeCheckInput {
8
8
  profile: HarnessProfile;
9
9
  /** Exception ids declared in the BRANCH.md (e.g. parser `exceptions`). */
10
10
  declaredExceptions?: string[];
11
+ /** Optional commit text; absent means commit guards are not run. */
12
+ commitMessage?: string;
11
13
  bypass?: {
12
14
  reason: string;
13
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"scope-check.d.ts","sourceRoot":"","sources":["../../src/checks/scope-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,WAAW,CAqB9D"}
1
+ {"version":3,"file":"scope-check.d.ts","sourceRoot":"","sources":["../../src/checks/scope-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,WAAW,CAgC9D"}
@@ -12,6 +12,17 @@ export function checkScope(input) {
12
12
  const { stagedFiles, boundary, profile, declaredExceptions = [] } = input;
13
13
  const hasValidException = declaredExceptions.some((id) => profile.exceptionIdPattern.test(id));
14
14
  const violations = [];
15
+ if (input.commitMessage !== undefined && profile.commitMessage) {
16
+ const { requiredPattern, forbiddenPatterns } = profile.commitMessage;
17
+ if (requiredPattern !== undefined && !new RegExp(requiredPattern).test(input.commitMessage)) {
18
+ violations.push({ code: 'C2', message: 'commit message does not match required pattern', severity: 'advisory' });
19
+ }
20
+ for (const pattern of forbiddenPatterns) {
21
+ if (new RegExp(pattern).test(input.commitMessage)) {
22
+ violations.push({ code: 'C2', message: `commit message matches forbidden pattern: ${pattern}`, severity: 'advisory' });
23
+ }
24
+ }
25
+ }
15
26
  for (const path of stagedFiles) {
16
27
  const cls = classifyPath(path, boundary, profile);
17
28
  if (cls === 'forbidden') {
@@ -1 +1 @@
1
- {"version":3,"file":"scope-check.js","sourceRoot":"","sources":["../../src/checks/scope-check.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAsB,MAAM,4BAA4B,CAAC;AAY9E;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAC9E,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAC1E,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/F,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,2BAA2B,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1G,CAAC;aAAM,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,CAAC,4BAA4B,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/F,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,IAAI;gBACV,IAAI;gBACJ,OAAO,EAAE,0DAA0D,IAAI,EAAE;gBACzE,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,0CAA0C,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACzH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"scope-check.js","sourceRoot":"","sources":["../../src/checks/scope-check.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAsB,MAAM,4BAA4B,CAAC;AAc9E;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAC9E,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAC1E,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/F,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC/D,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;QACrE,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,IAAI,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YAC5F,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,gDAAgD,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACnH,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;YACxC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;gBAClD,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,6CAA6C,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;YACzH,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,2BAA2B,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1G,CAAC;aAAM,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,CAAC,4BAA4B,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/F,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,IAAI;gBACV,IAAI;gBACJ,OAAO,EAAE,0DAA0D,IAAI,EAAE;gBACzE,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,0CAA0C,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACzH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;AACvD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"mechanical-verbs.d.ts","sourceRoot":"","sources":["../../src/cli/mechanical-verbs.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAO,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAKhD,eAAO,MAAM,gBAAgB,sCAAuC,CAAC;AACrE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAuE/D;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EAAE,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAChC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GACvB,MAAM,GAAG,IAAI,CA+Cf"}
1
+ {"version":3,"file":"mechanical-verbs.d.ts","sourceRoot":"","sources":["../../src/cli/mechanical-verbs.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAO,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAKhD,eAAO,MAAM,gBAAgB,sCAAuC,CAAC;AACrE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAmE/D;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EAAE,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAChC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GACvB,MAAM,GAAG,IAAI,CAsCf"}
@@ -4,11 +4,11 @@
4
4
  // `VerificationRun`: `verify` is the category-level roll-up over the available static checks (the
5
5
  // canonical VerificationRun producer); `audit` diffs the repo against the active profile; `init`
6
6
  // scaffolds a profile descriptor so the same C1/C2 kernel can run against ANY repo. Pure: the only
7
- // IO is reading the `--branch-md` file (shared with `check scope`); no git/docker/fs writes.
7
+ // IO is reading profile/plan files (shared with `check scope`); no git/docker/fs writes.
8
8
  import { toVerificationRun } from '../run/emit.js';
9
9
  import { checkBranch } from '../checks/branch-check.js';
10
- import { sentropicProfile } from '../profile/sentropic.js';
11
- import { stubProfile } from '../profile/stub.js';
10
+ import { resolveProfile } from '../profile/resolve.js';
11
+ import { toProfileDocument } from '../profile/document.js';
12
12
  import { scopeFromFlags } from './scope.js';
13
13
  import { str } from './args.js';
14
14
  const PLACEHOLDER_TS = '1970-01-01T00:00:00.000Z';
@@ -20,9 +20,6 @@ function isMechanicalVerb(v) {
20
20
  function isCategory(s) {
21
21
  return CATEGORIES.includes(s);
22
22
  }
23
- function resolveProfile(flags) {
24
- return str(flags.profile) === 'stub' ? stubProfile : sentropicProfile;
25
- }
26
23
  function runContext(flags, category, command) {
27
24
  return {
28
25
  runId: 'cli',
@@ -39,7 +36,7 @@ function runContext(flags, category, command) {
39
36
  /** Gather the static checks computable from supplied flags (C2 scope, C1 branch). */
40
37
  function staticChecks(flags, profile, out) {
41
38
  const checks = [];
42
- if (flags['staged-files'] !== undefined || flags['branch-md'] !== undefined) {
39
+ if (flags['staged-files'] !== undefined || flags['branch-md'] !== undefined || flags['commit-message'] !== undefined) {
43
40
  const outcome = scopeFromFlags(flags, profile);
44
41
  if (outcome.unreadable !== undefined) {
45
42
  out(`harness: cannot read plan file: ${outcome.unreadable}`);
@@ -80,22 +77,13 @@ export function handleMechanicalVerb(positionals, flags, out) {
80
77
  return null;
81
78
  const profile = resolveProfile(flags);
82
79
  if (verb === 'init') {
83
- const descriptor = {
84
- id: profile.id,
85
- forbiddenPathDefaults: profile.forbiddenPathDefaults,
86
- exceptionIdPattern: profile.exceptionIdPattern.source,
87
- conditionalRequiresException: profile.conditionalRequiresException,
88
- branchMatch: profile.branchMatch,
89
- };
80
+ const descriptor = toProfileDocument(profile);
90
81
  if (flags.json === true) {
91
82
  out(JSON.stringify(descriptor, null, 2));
92
83
  }
93
84
  else {
94
85
  out(`harness init — profile '${descriptor.id}' (edit and commit as harness.profile.json):`);
95
- out(` forbiddenPathDefaults: ${descriptor.forbiddenPathDefaults.join(', ') || '(none)'}`);
96
- out(` exceptionIdPattern: ${descriptor.exceptionIdPattern}`);
97
- out(` conditionalRequiresException: ${descriptor.conditionalRequiresException}`);
98
- out(` branchMatch: ${descriptor.branchMatch}`);
86
+ out(JSON.stringify(descriptor, null, 2));
99
87
  }
100
88
  return 0;
101
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mechanical-verbs.js","sourceRoot":"","sources":["../../src/cli/mechanical-verbs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mechanical-verbs.js","sourceRoot":"","sources":["../../src/cli/mechanical-verbs.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,iGAAiG;AACjG,mGAAmG;AACnG,yFAAyF;AAEzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAkB,MAAM,WAAW,CAAC;AAEhD,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAClD,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAU,CAAC;AAE1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAGrE,SAAS,gBAAgB,CAAC,CAAqB;IAC7C,OAAO,CAAC,KAAK,SAAS,IAAK,gBAAsC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAQ,UAAgC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,UAAU,CAAC,KAAgC,EAAE,QAA8B,EAAE,OAAe;IACnG,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,SAAS;QACtC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,SAAS;QACjD,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK;QAC5B,MAAM,EAAE,SAAS;QACjB,QAAQ;QACR,OAAO;QACP,SAAS,EAAE,cAAc;QACzB,UAAU,EAAE,cAAc;KAC3B,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,SAAS,YAAY,CACnB,KAAgC,EAChC,OAAuB,EACvB,GAAwB;IAExB,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,gBAAgB,CAAC,KAAK,SAAS,EAAE,CAAC;QACrH,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,GAAG,CAAC,mCAAmC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,SAAS,EAAE,CAAC;QACpF,MAAM,MAAM,GAAG,WAAW,CAAC;YACzB,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE;YACjD,cAAc,EAAE,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE;YACnD,OAAO;SACR,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,OAAO,CACd,MAAoB,EACpB,KAAgC,EAChC,QAA8B,EAC9B,OAAe,EACf,GAAwB;IAExB,MAAM,GAAG,GAAG,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5E,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACxB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,KAAK,QAAQ,MAAM,MAAM,CAAC,MAAM,WAAW,CAAC,CAAC;QACtG,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU;YAAE,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,WAAqB,EACrB,KAAgC,EAChC,GAAwB;IAExB,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,2BAA2B,UAAU,CAAC,EAAE,8CAA8C,CAAC,CAAC;YAC5F,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,qCAAqC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtE,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;QAC9B,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC;IAED,wEAAwE;IACxE,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACrC,GAAG,CAAC,mCAAmC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,MAAM,GAAiB,OAAO,CAAC,MAAM;QACzC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAC9D,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC;AAChE,CAAC"}
package/dist/cli/run.d.ts CHANGED
@@ -1,10 +1,2 @@
1
- /**
2
- * Pure, arg-based CLI driver — reads everything from `argv`, writes via `out`, returns an exit code.
3
- * No internal git calls (the caller supplies branch + staged files), no `process.exit`, no fs writes.
4
- * Advisory (D5 Layer A): a failing check returns 0; only a usage error returns non-zero.
5
- *
6
- * Verb families: `check` (C1/C2 → VerificationRun); method/recorder verbs (brainstorm/test/debug/
7
- * review/plan/branch/skills → WorkEvent + skill pointer, see `method-verbs.ts`).
8
- */
9
1
  export declare function runHarnessCli(argv: string[], out: (s: string) => void): number;
10
2
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAuFA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAgB9E"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAiHA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAO9E"}
package/dist/cli/run.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import { checkBranch } from '../checks/branch-check.js';
2
2
  import { toVerificationRun } from '../run/emit.js';
3
- import { sentropicProfile } from '../profile/sentropic.js';
4
- import { stubProfile } from '../profile/stub.js';
3
+ import { resolveProfile } from '../profile/resolve.js';
4
+ import { ProfileValidationError } from '../profile/document.js';
5
5
  import { parseFlags, str } from './args.js';
6
6
  import { scopeFromFlags } from './scope.js';
7
7
  import { handleMethodVerb } from './method-verbs.js';
8
8
  import { handleMechanicalVerb } from './mechanical-verbs.js';
9
9
  const USAGE = [
10
10
  'usage: harness check <scope|branch> [--current-branch <b>] [--expected-branch <b>] ' +
11
- '[--staged-files <list>] [--branch-md <path>] [--profile sentropic|stub] [--json]',
11
+ '[--staged-files <list>] [--branch-md <path>] [--profile sentropic|stub] [--profile-file <path>] [--commit-message <text>] [--json]',
12
12
  ' harness verify [--category static|unit|integration|e2e|ci|uat] [--staged-files <list>] ' +
13
- '[--current-branch <b>] [--expected-branch <b>] [--branch-md <path>] [--profile sentropic|stub] [--json]',
14
- ' harness init [--profile sentropic|stub] [--json]',
15
- ' harness audit [--staged-files <list>] [--branch-md <path>] [--profile sentropic|stub] [--json]',
13
+ '[--current-branch <b>] [--expected-branch <b>] [--branch-md <path>] [--profile sentropic|stub] [--profile-file <path>] [--commit-message <text>] [--json]',
14
+ ' harness init [--profile sentropic|stub] [--profile-file <path>] [--json]',
15
+ ' harness audit [--staged-files <list>] [--branch-md <path>] [--profile sentropic|stub] [--profile-file <path>] [--commit-message <text>] [--json]',
16
16
  ' harness brainstorm [<topic>] [--peers <n>] [--ladder study|vol|evol] [--json]',
17
17
  ' harness test [<scope>] [--category unit|integration|e2e] [--watch] [--json]',
18
18
  ' harness debug [<symptom>] [--json]',
@@ -28,7 +28,7 @@ function handleCheck(positionals, flags, out) {
28
28
  out(USAGE);
29
29
  return 2;
30
30
  }
31
- const profile = str(flags.profile) === 'stub' ? stubProfile : sentropicProfile;
31
+ const profile = resolveProfile(flags);
32
32
  const category = 'static';
33
33
  let result;
34
34
  let code;
@@ -76,14 +76,14 @@ function handleCheck(positionals, flags, out) {
76
76
  return 0;
77
77
  }
78
78
  /**
79
- * Pure, arg-based CLI driver — reads everything from `argv`, writes via `out`, returns an exit code.
79
+ * Arg-based CLI driver — reads profile/plan files, writes via `out`, returns an exit code.
80
80
  * No internal git calls (the caller supplies branch + staged files), no `process.exit`, no fs writes.
81
81
  * Advisory (D5 Layer A): a failing check returns 0; only a usage error returns non-zero.
82
82
  *
83
83
  * Verb families: `check` (C1/C2 → VerificationRun); method/recorder verbs (brainstorm/test/debug/
84
84
  * review/plan/branch/skills → WorkEvent + skill pointer, see `method-verbs.ts`).
85
85
  */
86
- export function runHarnessCli(argv, out) {
86
+ function dispatch(argv, out) {
87
87
  const { positionals, flags } = parseFlags(argv);
88
88
  const command = positionals[0];
89
89
  if (command === 'check') {
@@ -98,4 +98,15 @@ export function runHarnessCli(argv, out) {
98
98
  out(USAGE);
99
99
  return command === undefined ? 0 : 2;
100
100
  }
101
+ export function runHarnessCli(argv, out) {
102
+ try {
103
+ return dispatch(argv, out);
104
+ }
105
+ catch (error) {
106
+ if (!(error instanceof ProfileValidationError))
107
+ throw error;
108
+ out(`harness: ${error.message}`);
109
+ return 2;
110
+ }
111
+ }
101
112
  //# sourceMappingURL=run.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/cli/scope.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,YAAY,CAqBtG"}
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/cli/scope.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,YAAY,CAuBtG"}
package/dist/cli/scope.js CHANGED
@@ -1,16 +1,19 @@
1
1
  // Shared scope-check input resolution — used by `check scope`, `verify`, and `audit` so the
2
2
  // BRANCH.md parsing + boundary wiring lives in ONE place (no duplicated file IO).
3
- import { readFileSync } from 'node:fs';
3
+ import { existsSync, readFileSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
5
+ import { findRepoRoot } from '../profile/resolve.js';
4
6
  import { parseBranchMd } from '../branch-md/parse.js';
5
7
  import { checkScope } from '../checks/scope-check.js';
6
8
  import { list, str } from './args.js';
7
9
  /** Resolve `--branch-md` + `--staged-files` into a C2 scope CheckResult (pure but for the file read). */
8
10
  export function scopeFromFlags(flags, profile) {
9
- const branchMdPath = str(flags['branch-md']);
11
+ const explicitPath = str(flags['branch-md']);
12
+ const branchMdPath = explicitPath ?? (profile.branchMd ? resolve(findRepoRoot(), profile.branchMd.file) : undefined);
10
13
  let parsed;
11
- if (branchMdPath) {
14
+ if (branchMdPath && (explicitPath !== undefined || existsSync(branchMdPath))) {
12
15
  try {
13
- parsed = parseBranchMd(readFileSync(branchMdPath, 'utf8'));
16
+ parsed = parseBranchMd(readFileSync(branchMdPath, 'utf8'), profile);
14
17
  }
15
18
  catch {
16
19
  return { unreadable: branchMdPath };
@@ -25,6 +28,7 @@ export function scopeFromFlags(flags, profile) {
25
28
  },
26
29
  profile,
27
30
  declaredExceptions: parsed?.exceptions ?? [],
31
+ commitMessage: str(flags['commit-message']),
28
32
  });
29
33
  return { result };
30
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/cli/scope.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,kFAAkF;AAElF,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAkB,MAAM,WAAW,CAAC;AAStD,yGAAyG;AACzG,MAAM,UAAU,cAAc,CAAC,KAAgC,EAAE,OAAuB;IACtF,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7C,IAAI,MAAoD,CAAC;IACzD,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC;QACxB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,QAAQ,EAAE;YACR,OAAO,EAAE,MAAM,EAAE,YAAY,IAAI,EAAE;YACnC,SAAS,EAAE,MAAM,EAAE,cAAc,IAAI,EAAE;YACvC,WAAW,EAAE,MAAM,EAAE,gBAAgB,IAAI,EAAE;SAC5C;QACD,OAAO;QACP,kBAAkB,EAAE,MAAM,EAAE,UAAU,IAAI,EAAE;KAC7C,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/cli/scope.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,kFAAkF;AAElF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAkB,MAAM,WAAW,CAAC;AAStD,yGAAyG;AACzG,MAAM,UAAU,cAAc,CAAC,KAAgC,EAAE,OAAuB;IACtF,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,YAAY,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACrH,IAAI,MAAoD,CAAC;IACzD,IAAI,YAAY,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QAC7E,IAAI,CAAC;YACH,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;QACtE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC;QACxB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,QAAQ,EAAE;YACR,OAAO,EAAE,MAAM,EAAE,YAAY,IAAI,EAAE;YACnC,SAAS,EAAE,MAAM,EAAE,cAAc,IAAI,EAAE;YACvC,WAAW,EAAE,MAAM,EAAE,gBAAgB,IAAI,EAAE;SAC5C;QACD,OAAO;QACP,kBAAkB,EAAE,MAAM,EAAE,UAAU,IAAI,EAAE;QAC5C,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;KAC5C,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,9 @@ export type { WorkEventInput, WorkEventContext } from './run/work-event.js';
8
8
  export type { HarnessProfile } from './profile/profile.js';
9
9
  export { sentropicProfile } from './profile/sentropic.js';
10
10
  export { stubProfile } from './profile/stub.js';
11
+ export { parseHarnessProfile, toProfileDocument, ProfileValidationError } from './profile/document.js';
12
+ export type { HarnessProfileDocument, ProfileErrorCode } from './profile/document.js';
13
+ export { resolveProfile, loadProfileFile, findRepoRoot } from './profile/resolve.js';
11
14
  export { parseBranchMd } from './branch-md/parse.js';
12
15
  export type { ParsedBranchMd, ParsedLot, ParsedLotItem } from './branch-md/parse.js';
13
16
  export { classifyPath, matchGlob, globToRegExp } from './scope/scope-boundary.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,sBAAgC,CAAC;AAG7D,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,0CAA0C,CAAC;AAClD,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,MAAM,0CAA0C,CAAC;AAGlD,YAAY,EACV,SAAS,EACT,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5E,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAClF,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAG1E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChF,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,sBAAgC,CAAC;AAG7D,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,0CAA0C,CAAC;AAClD,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,MAAM,0CAA0C,CAAC;AAGlD,YAAY,EACV,SAAS,EACT,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5E,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACvG,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGrF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAClF,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAG1E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChF,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -8,6 +8,8 @@ export { validateVerificationRunV0, deriveVerdict, VERIFICATION_CATEGORIES, VIOL
8
8
  export { toWorkEvent } from './run/work-event.js';
9
9
  export { sentropicProfile } from './profile/sentropic.js';
10
10
  export { stubProfile } from './profile/stub.js';
11
+ export { parseHarnessProfile, toProfileDocument, ProfileValidationError } from './profile/document.js';
12
+ export { resolveProfile, loadProfileFile, findRepoRoot } from './profile/resolve.js';
11
13
  // BRANCH.md parser.
12
14
  export { parseBranchMd } from './branch-md/parse.js';
13
15
  // Scope classification.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,gFAAgF;AAChF,mFAAmF;AAEnF,MAAM,CAAC,MAAM,eAAe,GAAG,oBAA6B,CAAC;AAa7D,2FAA2F;AAC3F,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,0CAA0C,CAAC;AAclD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,wBAAwB;AACxB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGlF,uDAAuD;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,6EAA6E;AAC7E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhF,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,gFAAgF;AAChF,mFAAmF;AAEnF,MAAM,CAAC,MAAM,eAAe,GAAG,oBAA6B,CAAC;AAa7D,2FAA2F;AAC3F,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,0CAA0C,CAAC;AAclD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEvG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAErF,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,wBAAwB;AACxB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGlF,uDAAuD;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,6EAA6E;AAC7E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhF,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { HarnessProfile } from './profile.js';
2
+ /** JSON representation; regular expressions use sources without delimiters or flags. */
3
+ export interface HarnessProfileDocument extends Omit<HarnessProfile, 'exceptionIdPattern'> {
4
+ $schema?: string;
5
+ exceptionIdPattern: string;
6
+ }
7
+ export type ProfileErrorCode = 'UNKNOWN_KEY' | 'INVALID_PROFILE' | 'INVALID_REGEX' | 'PROFILE_READ' | 'PROFILE_JSON' | 'UNKNOWN_PROFILE';
8
+ export declare class ProfileValidationError extends Error {
9
+ readonly code: ProfileErrorCode;
10
+ readonly path: string;
11
+ constructor(code: ProfileErrorCode, path: string, detail: string);
12
+ }
13
+ /** Strict parser: rejects unknown keys at every level and never substitutes another profile. */
14
+ export declare function parseHarnessProfile(value: unknown): HarnessProfile;
15
+ export declare function toProfileDocument(profile: HarnessProfile): HarnessProfileDocument;
16
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/profile/document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,wFAAwF;AACxF,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,cAAc,EAAE,oBAAoB,CAAC;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,iBAAiB,GAAG,eAAe,GAChF,cAAc,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAEtD,qBAAa,sBAAuB,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,gBAAgB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAA7C,IAAI,EAAE,gBAAgB,EAAW,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAInF;AAkDD,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAKlE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,sBAAsB,CAEjF"}
@@ -0,0 +1,71 @@
1
+ import { readFileSync } from 'node:fs';
2
+ export class ProfileValidationError extends Error {
3
+ code;
4
+ path;
5
+ constructor(code, path, detail) {
6
+ super(`${code} at ${path}: ${detail}`);
7
+ this.code = code;
8
+ this.path = path;
9
+ this.name = 'ProfileValidationError';
10
+ }
11
+ }
12
+ // Validate against the shipped schema itself so the runtime and published contract stay aligned.
13
+ const schema = JSON.parse(readFileSync(new URL('../../schema/harness-profile.schema.json', import.meta.url), 'utf8'));
14
+ function validate(value, rule, path) {
15
+ if (rule.$ref)
16
+ return validate(value, schema.$defs[rule.$ref.split('/').at(-1)], path);
17
+ const invalid = (detail) => { throw new ProfileValidationError('INVALID_PROFILE', path, detail); };
18
+ if (rule.enum && !rule.enum.includes(value))
19
+ invalid(`expected one of ${rule.enum.join(', ')}`);
20
+ if (rule.type === 'object') {
21
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
22
+ invalid('expected an object');
23
+ const object = value;
24
+ for (const key of Object.keys(object)) {
25
+ if (rule.additionalProperties === false && !Object.hasOwn(rule.properties, key)) {
26
+ throw new ProfileValidationError('UNKNOWN_KEY', `${path}.${key}`, 'unknown profile key');
27
+ }
28
+ }
29
+ for (const key of rule.required ?? []) {
30
+ if (!Object.hasOwn(object, key))
31
+ invalid(`missing required key: ${key}`);
32
+ }
33
+ for (const [key, entry] of Object.entries(object))
34
+ validate(entry, rule.properties[key], `${path}.${key}`);
35
+ }
36
+ else if (rule.type === 'array') {
37
+ if (!Array.isArray(value))
38
+ invalid('expected an array');
39
+ value.forEach((entry, index) => validate(entry, rule.items, `${path}[${index}]`));
40
+ }
41
+ else if (rule.type === 'string') {
42
+ if (typeof value !== 'string')
43
+ invalid('expected a string');
44
+ const text = value;
45
+ if (text.length < (rule.minLength ?? 0))
46
+ invalid('expected a nonempty string');
47
+ if (rule.pattern && !new RegExp(rule.pattern).test(text))
48
+ invalid('invalid string format');
49
+ if (rule.format === 'regex') {
50
+ try {
51
+ new RegExp(text);
52
+ }
53
+ catch {
54
+ throw new ProfileValidationError('INVALID_REGEX', path, 'invalid ECMAScript regular expression');
55
+ }
56
+ }
57
+ }
58
+ else if (rule.type === 'boolean' && typeof value !== 'boolean')
59
+ invalid('expected a boolean');
60
+ }
61
+ /** Strict parser: rejects unknown keys at every level and never substitutes another profile. */
62
+ export function parseHarnessProfile(value) {
63
+ validate(value, schema, '$');
64
+ const document = value;
65
+ const { $schema: _schema, ...policy } = document;
66
+ return { ...policy, exceptionIdPattern: new RegExp(document.exceptionIdPattern) };
67
+ }
68
+ export function toProfileDocument(profile) {
69
+ return { ...profile, exceptionIdPattern: profile.exceptionIdPattern.source };
70
+ }
71
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/profile/document.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,22 @@ export interface HarnessProfile {
3
3
  id: string;
4
4
  /** Globs forbidden by default unless a BRANCH.md explicitly Allows them (C2). */
5
5
  forbiddenPathDefaults: string[];
6
+ /** Default scope buckets, used after explicit BRANCH.md scope declarations. */
7
+ allowedPathDefaults?: string[];
8
+ conditionalPathDefaults?: string[];
9
+ /** Optional repository-owned plan conventions (defaults retain the canonical parser). */
10
+ branchMd?: {
11
+ file: string;
12
+ allowedHeading: string;
13
+ forbiddenHeading: string;
14
+ conditionalHeading: string;
15
+ planHeading: string;
16
+ };
17
+ /** ECMAScript regex sources, checked only when a commit message is supplied. */
18
+ commitMessage?: {
19
+ requiredPattern?: string;
20
+ forbiddenPatterns: string[];
21
+ };
6
22
  /** Grammar of a valid scope-exception id in BRANCH.md (C2 conditional binding). */
7
23
  exceptionIdPattern: RegExp;
8
24
  /** When true, a Conditional path may be touched only if a matching exception id exists (C2). */
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mFAAmF;IACnF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gGAAgG;IAChG,4BAA4B,EAAE,OAAO,CAAC;IACtC,sEAAsE;IACtE,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;CACjC"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,yFAAyF;IACzF,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,gFAAgF;IAChF,aAAa,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC1E,mFAAmF;IACnF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gGAAgG;IAChG,4BAA4B,EAAE,OAAO,CAAC;IACtC,sEAAsE;IACtE,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;CACjC"}
@@ -0,0 +1,7 @@
1
+ import type { HarnessProfile } from './profile.js';
2
+ /** Works for ordinary repositories and worktrees (.git may be a file), without spawning git. */
3
+ export declare function findRepoRoot(cwd?: string): string;
4
+ export declare function loadProfileFile(path: string): HarnessProfile;
5
+ /** Resolve explicit built-in > explicit file > root discovery > sentropic. */
6
+ export declare function resolveProfile(flags: Record<string, unknown>, cwd?: string): HarnessProfile;
7
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/profile/resolve.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,GAAG,SAAgB,GAAG,MAAM,CAMxD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAQ5D;AASD,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,SAAgB,GAAG,cAAc,CAiBlG"}
@@ -0,0 +1,63 @@
1
+ import { existsSync, lstatSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { sentropicProfile } from './sentropic.js';
4
+ import { stubProfile } from './stub.js';
5
+ import { parseHarnessProfile, ProfileValidationError } from './document.js';
6
+ /** Works for ordinary repositories and worktrees (.git may be a file), without spawning git. */
7
+ export function findRepoRoot(cwd = process.cwd()) {
8
+ const start = resolve(cwd);
9
+ for (let directory = start;; directory = dirname(directory)) {
10
+ if (existsSync(join(directory, '.git')))
11
+ return directory;
12
+ if (dirname(directory) === directory)
13
+ return start;
14
+ }
15
+ }
16
+ export function loadProfileFile(path) {
17
+ let text;
18
+ try {
19
+ text = readFileSync(path, 'utf8');
20
+ }
21
+ catch {
22
+ throw new ProfileValidationError('PROFILE_READ', path, 'cannot read profile file');
23
+ }
24
+ let document;
25
+ try {
26
+ document = JSON.parse(text);
27
+ }
28
+ catch {
29
+ throw new ProfileValidationError('PROFILE_JSON', path, 'invalid JSON');
30
+ }
31
+ return parseHarnessProfile(document);
32
+ }
33
+ function flagValue(value, flag) {
34
+ if (typeof value !== 'string' || !value.trim()) {
35
+ throw new ProfileValidationError('INVALID_PROFILE', flag, 'expected a nonempty value');
36
+ }
37
+ return value;
38
+ }
39
+ /** Resolve explicit built-in > explicit file > root discovery > sentropic. */
40
+ export function resolveProfile(flags, cwd = process.cwd()) {
41
+ if (flags.profile !== undefined) {
42
+ const name = flagValue(flags.profile, '--profile');
43
+ if (name === 'sentropic')
44
+ return sentropicProfile;
45
+ if (name === 'stub')
46
+ return stubProfile;
47
+ throw new ProfileValidationError('UNKNOWN_PROFILE', '--profile', `unknown built-in profile: ${name}`);
48
+ }
49
+ if (flags['profile-file'] !== undefined) {
50
+ return loadProfileFile(resolve(cwd, flagValue(flags['profile-file'], '--profile-file')));
51
+ }
52
+ const path = join(findRepoRoot(cwd), 'harness.profile.json');
53
+ try {
54
+ lstatSync(path);
55
+ }
56
+ catch (error) {
57
+ if (error.code === 'ENOENT')
58
+ return sentropicProfile;
59
+ throw new ProfileValidationError('PROFILE_READ', path, 'cannot inspect profile file');
60
+ }
61
+ return loadProfileFile(path);
62
+ }
63
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/profile/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE5E,gGAAgG;AAChG,MAAM,UAAU,YAAY,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,KAAK,IAAI,SAAS,GAAG,KAAK,GAAI,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QAC1D,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QAAC,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IAC1C,MAAM,CAAC;QAAC,MAAM,IAAI,sBAAsB,CAAC,cAAc,EAAE,IAAI,EAAE,0BAA0B,CAAC,CAAC;IAAC,CAAC;IAC7F,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IACpC,MAAM,CAAC;QAAC,MAAM,IAAI,sBAAsB,CAAC,cAAc,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAAC,CAAC;IACjF,OAAO,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,SAAS,CAAC,KAAc,EAAE,IAAY;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,sBAAsB,CAAC,iBAAiB,EAAE,IAAI,EAAE,2BAA2B,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,KAA8B,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAChF,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACnD,IAAI,IAAI,KAAK,WAAW;YAAE,OAAO,gBAAgB,CAAC;QAClD,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,WAAW,CAAC;QACxC,MAAM,IAAI,sBAAsB,CAAC,iBAAiB,EAAE,WAAW,EAAE,6BAA6B,IAAI,EAAE,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC3F,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;IAC7D,IAAI,CAAC;QAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IACxB,OAAO,KAAK,EAAE,CAAC;QACb,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,gBAAgB,CAAC;QAChF,MAAM,IAAI,sBAAsB,CAAC,cAAc,EAAE,IAAI,EAAE,6BAA6B,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
@@ -14,7 +14,8 @@ export declare function matchGlob(glob: string, path: string): boolean;
14
14
  * forbidden globs (C2 scope-check core).
15
15
  *
16
16
  * Precedence (first match wins):
17
- * explicit allowed > explicit forbidden > explicit conditional > profile default-forbidden > unknown
17
+ * explicit allowed > explicit forbidden > explicit conditional >
18
+ * profile default-forbidden > profile default-conditional > profile default-allowed > unknown
18
19
  *
19
20
  * `allowed` wins over `forbidden` so an explicitly-granted subtree (e.g. `packages/harness/**`)
20
21
  * is `allowed` even when a broader `packages/**` is forbidden — the Allowed list is the granted
@@ -1 +1 @@
1
- {"version":3,"file":"scope-boundary.d.ts","sourceRoot":"","sources":["../../src/scope/scope-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AAE5E,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,cAAc,GACtB,SAAS,CAMX"}
1
+ {"version":3,"file":"scope-boundary.d.ts","sourceRoot":"","sources":["../../src/scope/scope-boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AAE5E,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,cAAc,GACtB,SAAS,CAQX"}
@@ -29,7 +29,8 @@ export function matchGlob(glob, path) {
29
29
  * forbidden globs (C2 scope-check core).
30
30
  *
31
31
  * Precedence (first match wins):
32
- * explicit allowed > explicit forbidden > explicit conditional > profile default-forbidden > unknown
32
+ * explicit allowed > explicit forbidden > explicit conditional >
33
+ * profile default-forbidden > profile default-conditional > profile default-allowed > unknown
33
34
  *
34
35
  * `allowed` wins over `forbidden` so an explicitly-granted subtree (e.g. `packages/harness/**`)
35
36
  * is `allowed` even when a broader `packages/**` is forbidden — the Allowed list is the granted
@@ -45,6 +46,10 @@ export function classifyPath(path, boundary, profile) {
45
46
  return 'conditional';
46
47
  if (profile.forbiddenPathDefaults.some((g) => matchGlob(g, path)))
47
48
  return 'forbidden';
49
+ if (profile.conditionalPathDefaults?.some((g) => matchGlob(g, path)))
50
+ return 'conditional';
51
+ if (profile.allowedPathDefaults?.some((g) => matchGlob(g, path)))
52
+ return 'allowed';
48
53
  return 'unknown';
49
54
  }
50
55
  //# sourceMappingURL=scope-boundary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scope-boundary.js","sourceRoot":"","sources":["../../src/scope/scope-boundary.ts"],"names":[],"mappings":"AAWA,iGAAiG;AACjG,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACxB,EAAE,IAAI,IAAI,CAAC;gBACX,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,EAAE,IAAI,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;aAAM,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IAClD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,QAAuB,EACvB,OAAuB;IAEvB,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACvE,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAC3E,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IAC/E,IAAI,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IACtF,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"scope-boundary.js","sourceRoot":"","sources":["../../src/scope/scope-boundary.ts"],"names":[],"mappings":"AAWA,iGAAiG;AACjG,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACxB,EAAE,IAAI,IAAI,CAAC;gBACX,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,EAAE,IAAI,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;aAAM,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IAClD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,QAAuB,EACvB,OAAuB;IAEvB,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACvE,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAC3E,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IAC/E,IAAI,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IACtF,IAAI,OAAO,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IAC3F,IAAI,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACnF,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentropic/harness",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Neutral, host-agnostic code-work / PR-workflow tooling for AI dev: a homogeneous `harness <verb>` method layer (branch/scope/verify/test/debug/review/brainstorm/plan), the native superpowers replacement. Tooling-only, zero product-runtime deps. (BR-42h)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,49 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/rhanka/sentropic/packages/harness/schema/harness-profile.schema.json",
4
+ "title": "Harness repository profile",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["id", "forbiddenPathDefaults", "exceptionIdPattern", "conditionalRequiresException", "branchMatch"],
8
+ "properties": {
9
+ "$schema": { "type": "string", "minLength": 1 },
10
+ "id": { "type": "string", "minLength": 1, "pattern": "\\S" },
11
+ "forbiddenPathDefaults": { "$ref": "#/$defs/globs" },
12
+ "allowedPathDefaults": { "$ref": "#/$defs/globs" },
13
+ "conditionalPathDefaults": { "$ref": "#/$defs/globs" },
14
+ "exceptionIdPattern": { "$ref": "#/$defs/regex" },
15
+ "conditionalRequiresException": { "type": "boolean" },
16
+ "branchMatch": { "enum": ["exact", "prefix"] },
17
+ "branchMd": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "required": ["file", "allowedHeading", "forbiddenHeading", "conditionalHeading", "planHeading"],
21
+ "properties": {
22
+ "file": { "$ref": "#/$defs/path" },
23
+ "allowedHeading": { "$ref": "#/$defs/heading" },
24
+ "forbiddenHeading": { "$ref": "#/$defs/heading" },
25
+ "conditionalHeading": { "$ref": "#/$defs/heading" },
26
+ "planHeading": { "$ref": "#/$defs/heading" }
27
+ }
28
+ },
29
+ "commitMessage": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["forbiddenPatterns"],
33
+ "properties": {
34
+ "requiredPattern": { "$ref": "#/$defs/regex" },
35
+ "forbiddenPatterns": { "type": "array", "items": { "$ref": "#/$defs/regex" } }
36
+ }
37
+ }
38
+ },
39
+ "$defs": {
40
+ "globs": { "type": "array", "items": { "$ref": "#/$defs/path" } },
41
+ "path": {
42
+ "type": "string",
43
+ "minLength": 1,
44
+ "pattern": "^(?!/)(?![A-Za-z]:)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\)\\S.*$"
45
+ },
46
+ "regex": { "type": "string", "minLength": 1, "format": "regex" },
47
+ "heading": { "type": "string", "minLength": 1, "pattern": "^[^\\r\\n]+$" }
48
+ }
49
+ }