arkgate 4.8.16 → 4.8.17

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.
@@ -271,7 +271,8 @@ export function checkUsageAll() {
271
271
  'This merge profile never depends on an editor/agent hook.',
272
272
  'When a Git merge base is available, --strict-merge classifies the ark.config.json',
273
273
  'transition. Weakening or judgment-required findings fail unless --policy-ack names',
274
- 'every finding and is bound to both policy hashes. Use --policy-base/--policy-base-ref',
274
+ 'every finding, is bound to both policy hashes, and adrPath points at a short note',
275
+ 'under docs/adr/ or docs/decisions/. Use --policy-base/--policy-base-ref',
275
276
  'for an explicit comparison; ARK_POLICY_BASE_REF is the CI environment equivalent.',
276
277
  'The same merge profile blocks new UI business-rule files (domain-logic-in-ui) created',
277
278
  'versus that base; leftover design on existing files stays green. Missing base skips',
@@ -9,6 +9,7 @@ import {
9
9
  loadInvariantCoverageInputs,
10
10
  } from './invariant-coverage-io.mjs';
11
11
  import { evaluateInvariantCoverage } from './invariant-coverage.mjs';
12
+ import { attachPolicyAdrNote } from './adr-path.mjs';
12
13
 
13
14
  function readJsonFile(filePath, label) {
14
15
  if (!fs.existsSync(filePath)) throw new Error(`${label} not found: ${filePath}`);
@@ -196,14 +197,22 @@ export function analyzePolicyTransition({
196
197
  candidateInvariantCoverage = evaluated.coverage;
197
198
  }
198
199
 
199
- return analyzePolicyDelta({
200
- baseConfig: base.config,
201
- candidateConfig,
202
- acknowledgement: readPolicyAcknowledgement(root, acknowledgementPath),
203
- baseSource: base.source,
204
- candidateSource: path.isAbsolute(configPath) ? configPath : path.join(root, configPath),
205
- ...(baseArkRules ? { baseArkRules } : {}),
206
- candidateArkRules,
207
- ...(candidateInvariantCoverage ? { candidateInvariantCoverage } : {}),
208
- });
200
+ const acknowledgement = readPolicyAcknowledgement(root, acknowledgementPath);
201
+ return attachPolicyAdrNote(
202
+ analyzePolicyDelta({
203
+ baseConfig: base.config,
204
+ candidateConfig,
205
+ acknowledgement,
206
+ baseSource: base.source,
207
+ candidateSource: path.isAbsolute(configPath) ? configPath : path.join(root, configPath),
208
+ ...(baseArkRules ? { baseArkRules } : {}),
209
+ candidateArkRules,
210
+ ...(candidateInvariantCoverage ? { candidateInvariantCoverage } : {}),
211
+ }),
212
+ {
213
+ root,
214
+ acknowledgement,
215
+ failClosed: Boolean(strictMerge || acknowledgementPath),
216
+ }
217
+ );
209
218
  }
@@ -392,7 +392,7 @@ declare function createAdapterResult(input: {
392
392
  }): CurrentAdapterResult;
393
393
 
394
394
  /** ArkGate library version — single source of truth. */
395
- declare const version = "4.8.16";
395
+ declare const version = "4.8.17";
396
396
 
397
397
  /**
398
398
  * AI Code Gate (basic).
@@ -1971,6 +1971,12 @@ type PolicyDeltaAcknowledgement = {
1971
1971
  candidatePolicyHash: string;
1972
1972
  findingIds: readonly string[];
1973
1973
  reason: string;
1974
+ /**
1975
+ * Relative decision-note path under a conventional home (`docs/adr/`,
1976
+ * `docs/decisions/`, or the AP01 single-file homes). Tooling checks the file.
1977
+ * Hash matching does not require it.
1978
+ */
1979
+ adrPath?: string;
1974
1980
  };
1975
1981
  type ClassifyArkPolicyDeltaOptions = {
1976
1982
  baseArkRules?: EffectiveArkRules;