@open-agent-toolkit/cli 0.1.37 → 0.1.39

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.
@@ -22,14 +22,14 @@ For the deep file-by-file reference, see:
22
22
  | -------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
23
23
  | Shared repo config | `.oat/config.json` | Repo-wide non-sync settings such as `projects.root`, `git.defaultBranch`, `documentation.*`, `archive.*`, `tools.*`, and shared `workflow.*` defaults | `oat config get/set/list/describe`, `oat gate` |
24
24
  | Repo-local config | `.oat/config.local.json` | Per-developer state for this checkout, such as `activeProject`, `lastPausedProject`, repo-local `activeIdea`, and local `workflow.*` overrides | `oat config get/set/list/describe`, `oat gate` |
25
- | User config | `~/.oat/config.json` | User-level state such as global `activeIdea` fallback and personal `workflow.*` defaults | `oat config describe`, `oat gate` |
26
- | Provider sync config | `.oat/sync/config.json` | Provider enablement and sync strategy settings | `oat providers set`, `oat config describe` |
25
+ | User config | `~/.oat/config.json` | User-level state such as global `activeIdea` fallback, personal `workflow.*` defaults, and personal known provider strays | `oat config describe`, `oat gate` |
26
+ | Provider sync config | `.oat/sync/config.json` | Provider enablement, sync strategy, and repo-level known stray settings | `oat providers set`, `oat config describe` |
27
27
 
28
28
  The main split is:
29
29
 
30
30
  - `.oat/config.json` for shared repo behavior
31
31
  - `.oat/config.local.json` for local developer state
32
- - `~/.oat/config.json` for user-scope fallback state
32
+ - `~/.oat/config.json` for user-scope fallback state and personal provider-sync exceptions
33
33
  - `.oat/sync/config.json` for provider sync only
34
34
 
35
35
  ## The fastest way to inspect config
@@ -398,6 +398,10 @@ Use:
398
398
  - `oat config describe ...` to understand sync keys
399
399
  - `oat providers set ...` to mutate sync/provider settings
400
400
 
401
+ Known provider strays are the narrow cross-surface exception: repo-wide
402
+ `knownStrays` entries live in `.oat/sync/config.json`, while personal
403
+ `knownStrays` entries can live in `~/.oat/config.json`.
404
+
401
405
  For the provider-sync schema details, use [Sync Config (`.oat/sync/config.json`)](../provider-sync/config.md).
402
406
 
403
407
  ## Recommended workflow
@@ -23,6 +23,7 @@ Discovery note:
23
23
  It is read by:
24
24
 
25
25
  - `oat init` (provider selection and defaults)
26
+ - `oat status` (known-stray suppression in drift reports and remediation)
26
27
  - `oat sync` (active provider resolution and mismatch handling)
27
28
  - `oat providers set` (explicit provider enable/disable updates)
28
29
 
@@ -32,6 +33,7 @@ It is read by:
32
33
  {
33
34
  "version": 1,
34
35
  "defaultStrategy": "auto",
36
+ "knownStrays": [".cursor/skills/cloud-environment-setup"],
35
37
  "providers": {
36
38
  "claude": {
37
39
  "enabled": true,
@@ -50,10 +52,41 @@ It is read by:
50
52
  | --------------------------- | ------------------------------------- | ---------------------------------------------------------- |
51
53
  | `version` | yes | Config schema version (currently `1`) |
52
54
  | `defaultStrategy` | yes | Global default sync strategy: `auto`, `symlink`, or `copy` |
55
+ | `knownStrays` | no | Exact provider paths to suppress from stray reporting |
53
56
  | `providers` | no (persisted), normalized at runtime | Provider-specific overrides keyed by adapter name |
54
57
  | `providers.<name>.enabled` | no | Explicit provider activation (`true` / `false`) |
55
58
  | `providers.<name>.strategy` | no | Per-provider strategy override (`auto`, `symlink`, `copy`) |
56
59
 
60
+ ### Known strays
61
+
62
+ Use `knownStrays` for provider-local files that should remain unmanaged by OAT.
63
+ Entries are exact provider-path matches after path normalization; they are not
64
+ globs and do not suppress sibling paths.
65
+
66
+ Project-level config in `.oat/sync/config.json` applies to everyone using the
67
+ repository:
68
+
69
+ ```json
70
+ {
71
+ "version": 1,
72
+ "defaultStrategy": "auto",
73
+ "knownStrays": [".cursor/skills/cloud-environment-setup"]
74
+ }
75
+ ```
76
+
77
+ User-level config in `~/.oat/config.json` is useful for personal provider-local
78
+ files that should not be committed to the repository:
79
+
80
+ ```json
81
+ {
82
+ "knownStrays": [".cursor/skills/cloud-environment-setup"]
83
+ }
84
+ ```
85
+
86
+ The common Cursor-only skill case is a good fit: the skill may intentionally
87
+ exist in `.cursor/skills/cloud-environment-setup` while remaining outside the
88
+ canonical `.agents/skills` inventory.
89
+
57
90
  ## Behavior notes
58
91
 
59
92
  - If `providers.<name>.enabled` is:
@@ -53,6 +53,12 @@ Rendered rule files participate in the same drift states as other managed copies
53
53
 
54
54
  Provider files ignored by Git are treated as intentionally local runtime files and are not reported as strays. This includes files covered by tracked `.gitignore`, repo-local `.git/info/exclude`, or other standard Git exclude mechanisms.
55
55
 
56
+ Provider files listed in sync config `knownStrays` are also omitted from stray
57
+ summaries and adoption prompts. Known strays can be configured at project scope
58
+ in `.oat/sync/config.json` or user scope in `~/.oat/config.json`; entries use
59
+ exact provider-path matching, so `.cursor/skills/cloud-environment-setup` does
60
+ not suppress `.cursor/skills/cloud-environment-setup-extra`.
61
+
56
62
  For rules, adoption maps provider-native files back into `.agents/rules/*.md`:
57
63
 
58
64
  - Claude: `.claude/rules/*.md`
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.1.37",
3
- "docs-config": "0.1.37",
4
- "docs-theme": "0.1.37",
5
- "docs-transforms": "0.1.37"
2
+ "cli": "0.1.39",
3
+ "docs-config": "0.1.39",
4
+ "docs-theme": "0.1.39",
5
+ "docs-transforms": "0.1.39"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-review-provide
3
- version: 1.2.1
3
+ version: 1.2.2
4
4
  description: Use when you need an ad-hoc review outside an active OAT project lifecycle. Reviews code or artifacts without project phase state, unlike oat-project-review-provide.
5
5
  argument-hint: '[unstaged|staged|base_branch=<branch>|base_sha=<sha>|<sha1>..<sha2>|--files <path1,path2,...>] [--output <path>] [--mode auto|local|tracked|inline]'
6
6
  disable-model-invocation: true
@@ -183,7 +183,7 @@ If the file already exists (same scope reviewed twice in one day), suffix with `
183
183
 
184
184
  Use the same severity model and checklist as project reviews:
185
185
 
186
- - Critical / Important / Minor findings
186
+ - Critical / Important / Medium / Minor findings
187
187
  - file:line references
188
188
  - actionable fix guidance
189
189
  - verification commands
@@ -23,19 +23,25 @@ oat_review_mode: ad_hoc
23
23
 
24
24
  {2-3 sentence summary}
25
25
 
26
+ Findings: {N} critical, {N} important, {N} medium, {N} minor
27
+
26
28
  ## Findings
27
29
 
28
30
  ### Critical
29
31
 
30
- {None or list}
32
+ {If none: "None"}
31
33
 
32
34
  ### Important
33
35
 
34
- {None or list}
36
+ {If none: "None"}
37
+
38
+ ### Medium
39
+
40
+ {If none: "None"}
35
41
 
36
42
  ### Minor
37
43
 
38
- {None or list}
44
+ {If none: "None"}
39
45
 
40
46
  ## Verification Commands
41
47
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAQL,KAAK,UAAU,EAIf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,UAAU,uBAAuB;IAC/B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,CACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA0CD,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACvD,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC7B;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,kBAAkB,GAAG,cAAc,GAAG,MAAM,CAAC;AAMlD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAyZD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAC9C,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,GAAG,IAAI,CAE3B;AA+wBD,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAwKT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAQL,KAAK,UAAU,EAIf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,UAAU,uBAAuB;IAC/B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,CACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA0CD,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACvD,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC7B;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,kBAAkB,GAAG,cAAc,GAAG,MAAM,CAAC;AAMlD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAyZD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAC9C,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,GAAG,IAAI,CAE3B;AAo6BD,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAwKT"}
@@ -10,7 +10,7 @@ import { resolveEffectiveConfig, resolveExecTargets, resolveGate, } from '../../
10
10
  import { dirExists, fileExists } from '../../fs/io.js';
11
11
  import { normalizeToPosixPath, resolveProjectRoot } from '../../fs/paths.js';
12
12
  import { Command } from 'commander';
13
- import { parseReviewGateVerdict, } from './review-verdict.js';
13
+ import { parseReviewGateVerdict, severityDisplayName, } from './review-verdict.js';
14
14
  const DEFAULT_DEPENDENCIES = {
15
15
  buildCommandContext,
16
16
  resolveProjectRoot,
@@ -40,7 +40,7 @@ const VALID_REVIEW_GATE_THRESHOLDS = [
40
40
  'medium',
41
41
  'minor',
42
42
  ];
43
- const REVIEW_GATE_CONTEXT_NOTE = 'This review is gate-originated. If you run `oat-project-review-provide`, set `oat_review_invocation: gate` in the review artifact.';
43
+ const REVIEW_GATE_CONTEXT_NOTE = 'This review is gate-originated. If you run `oat-project-review-provide`, set `oat_review_invocation: gate` in the review artifact. Write a canonical review artifact with `### Critical`, `### Important`, `### Medium`, and `### Minor` headings in that order, using `None` for empty sections.';
44
44
  function reviewGateProjectContext(projectPath) {
45
45
  return `Resolved OAT project path: ${projectPath}. Run the review for this project path.`;
46
46
  }
@@ -577,15 +577,83 @@ function reviewBlocksAtThreshold(verdict, threshold) {
577
577
  }
578
578
  return verdict.counts.minor > 0;
579
579
  }
580
+ function buildReviewGateHandoff(options) {
581
+ const receiveInstruction = `Run oat-project-review-receive for ${options.artifactPath} before treating this gate review as consumed.`;
582
+ const thresholdIndex = VALID_REVIEW_GATE_THRESHOLDS.indexOf(options.threshold);
583
+ const nonBlockingSeverities = VALID_REVIEW_GATE_THRESHOLDS.slice(thresholdIndex + 1).filter((severity) => options.verdict.counts[severity] > 0);
584
+ const hasFinalNonBlockingFindings = options.verdict.scope === 'final' &&
585
+ !options.blocking &&
586
+ nonBlockingSeverities.length > 0;
587
+ if (!hasFinalNonBlockingFindings) {
588
+ return receiveInstruction;
589
+ }
590
+ const counts = nonBlockingSeverities
591
+ .map((severity) => `${severity}=${options.verdict.counts[severity]}`)
592
+ .join(', ');
593
+ return `Gate passed at the ${options.threshold} threshold, but the final review still contains non-blocking findings (${counts}). Run oat-project-review-receive for ${options.artifactPath} to disposition them before marking the final review row passed.`;
594
+ }
595
+ function reviewGateOutcome(payload) {
596
+ if (payload.blocking) {
597
+ return 'review_completed_blocking_findings';
598
+ }
599
+ if (payload.normalization) {
600
+ return 'review_completed_artifact_normalized_gate_passed';
601
+ }
602
+ return 'review_completed_gate_passed';
603
+ }
580
604
  function writeReviewGateResult(context, payload) {
605
+ const outcome = reviewGateOutcome(payload);
581
606
  if (context.json) {
582
- context.logger.json(payload);
607
+ context.logger.json({ outcome, ...payload });
583
608
  return;
584
609
  }
610
+ if (outcome === 'review_completed_blocking_findings') {
611
+ context.logger.info('Review completed and found blocking issues.');
612
+ }
613
+ else if (outcome === 'review_completed_artifact_normalized_gate_passed') {
614
+ context.logger.info('Review completed, artifact was normalized, and gate passed.');
615
+ }
616
+ else {
617
+ context.logger.info('Review completed and gate passed.');
618
+ }
585
619
  context.logger.info(`Review artifact: ${payload.artifactPath}`);
620
+ if (payload.normalization) {
621
+ context.logger.info(`Artifact normalized: inserted ${payload.normalization.insertedSeverities.map((severity) => severityDisplayName(severity)).join(', ')} empty Findings section(s).`);
622
+ }
586
623
  context.logger.info(`Verdict: ${payload.status} (critical=${payload.counts.critical}, important=${payload.counts.important}, medium=${payload.counts.medium}, minor=${payload.counts.minor})`);
587
624
  context.logger.info(payload.handoff);
588
625
  }
626
+ function writeReviewGateExecutionFailure(context, payload) {
627
+ const message = `Review did not complete: target ${payload.target} exited with code ${payload.exitCode}.`;
628
+ if (context.json) {
629
+ context.logger.json({
630
+ status: 'review_failed',
631
+ outcome: 'review_did_not_complete',
632
+ target: payload.target,
633
+ project: payload.project,
634
+ exitCode: payload.exitCode,
635
+ message,
636
+ });
637
+ return;
638
+ }
639
+ context.logger.error(message);
640
+ }
641
+ function writeReviewGateArtifactValidationFailure(context, payload) {
642
+ if (context.json) {
643
+ context.logger.json({
644
+ status: 'artifact_validation_failed',
645
+ outcome: 'review_completed_artifact_validation_failed',
646
+ target: payload.target,
647
+ project: payload.project,
648
+ artifactPath: payload.artifactPath,
649
+ message: payload.message,
650
+ recovery: payload.recovery,
651
+ });
652
+ return;
653
+ }
654
+ context.logger.error(`Review completed but artifact validation failed: ${payload.message}`);
655
+ context.logger.error(payload.recovery);
656
+ }
589
657
  async function updateConfigLayer(context, layer, dependencies, mutate) {
590
658
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
591
659
  const userConfigDir = join(context.home, '.oat');
@@ -716,6 +784,11 @@ async function runReviewGate(prompt, options, context, dependencies) {
716
784
  ]);
717
785
  const childExitCode = await executeTarget(selected, [reviewPrompt], context, dependencies);
718
786
  if (childExitCode !== 0) {
787
+ writeReviewGateExecutionFailure(context, {
788
+ target: selected.id,
789
+ project: projectPath,
790
+ exitCode: childExitCode,
791
+ });
719
792
  process.exitCode = childExitCode;
720
793
  return;
721
794
  }
@@ -725,11 +798,41 @@ async function runReviewGate(prompt, options, context, dependencies) {
725
798
  });
726
799
  const producedArtifact = findProducedReviewArtifact(before, after);
727
800
  if (!producedArtifact) {
728
- throw new Error(`No new review artifact was detected for project ${projectPath}. Ensure the review provider wrote a project review artifact before the gate exits.`);
801
+ writeReviewGateArtifactValidationFailure(context, {
802
+ target: selected.id,
803
+ project: projectPath,
804
+ artifactPath: null,
805
+ message: `No new review artifact was detected for project ${projectPath}.`,
806
+ recovery: 'Ensure the review provider wrote a project review artifact. If it did, fix or attach that artifact and run oat-project-review-receive before treating the review as consumed.',
807
+ });
808
+ process.exitCode = 1;
809
+ return;
810
+ }
811
+ let verdict;
812
+ try {
813
+ verdict = await parseReviewGateVerdict(join(repoRoot, producedArtifact.path), {
814
+ normalizeMissingEmptySeveritySections: true,
815
+ });
816
+ }
817
+ catch (error) {
818
+ const detail = error instanceof Error ? error.message : String(error);
819
+ writeReviewGateArtifactValidationFailure(context, {
820
+ target: selected.id,
821
+ project: projectPath,
822
+ artifactPath: producedArtifact.path,
823
+ message: detail,
824
+ recovery: `The review artifact was created at ${producedArtifact.path} but could not be consumed. Fix the artifact format, then run oat-project-review-receive for ${producedArtifact.path}; if the only issue is a missing zero-count severity heading, rerun the gate to normalize the same artifact instead of creating a new review version.`,
825
+ });
826
+ process.exitCode = 1;
827
+ return;
729
828
  }
730
- const verdict = await parseReviewGateVerdict(join(repoRoot, producedArtifact.path));
731
829
  const blocking = reviewBlocksAtThreshold(verdict, threshold);
732
- const handoff = `Run oat-project-review-receive for ${producedArtifact.path} before treating this gate review as consumed.`;
830
+ const handoff = buildReviewGateHandoff({
831
+ artifactPath: producedArtifact.path,
832
+ verdict,
833
+ threshold,
834
+ blocking,
835
+ });
733
836
  writeReviewGateResult(context, {
734
837
  status: blocking ? 'blocked' : 'ok',
735
838
  target: selected.id,
@@ -741,6 +844,7 @@ async function runReviewGate(prompt, options, context, dependencies) {
741
844
  reviewType: verdict.reviewType,
742
845
  scope: verdict.scope,
743
846
  invocation: verdict.invocation,
847
+ normalization: verdict.normalization,
744
848
  handoff,
745
849
  });
746
850
  process.exitCode = blocking ? 1 : 0;
@@ -10,6 +10,14 @@ export interface ReviewGateVerdict {
10
10
  minor: number;
11
11
  };
12
12
  blocking: boolean;
13
+ normalization?: {
14
+ insertedSeverities: Severity[];
15
+ };
16
+ }
17
+ export type Severity = keyof ReviewGateVerdict['counts'];
18
+ export interface ParseReviewGateVerdictOptions {
19
+ normalizeMissingEmptySeveritySections?: boolean;
13
20
  }
14
- export declare function parseReviewGateVerdict(artifactPath: string): Promise<ReviewGateVerdict>;
21
+ export declare function severityDisplayName(severity: Severity): string;
22
+ export declare function parseReviewGateVerdict(artifactPath: string, options?: ParseReviewGateVerdictOptions): Promise<ReviewGateVerdict>;
15
23
  //# sourceMappingURL=review-verdict.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"review-verdict.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/review-verdict.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC;CACnB;AA2ND,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAmC5B"}
1
+ {"version":3,"file":"review-verdict.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/review-verdict.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE;QACd,kBAAkB,EAAE,QAAQ,EAAE,CAAC;KAChC,CAAC;CACH;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAEzD,MAAM,WAAW,6BAA6B;IAC5C,qCAAqC,CAAC,EAAE,OAAO,CAAC;CACjD;AAqID,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE9D;AAqRD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,iBAAiB,CAAC,CAsD5B"}
@@ -1,4 +1,4 @@
1
- import { readFile } from 'node:fs/promises';
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
2
  import { getFrontmatterBlock } from '../shared/frontmatter.js';
3
3
  import YAML from 'yaml';
4
4
  const SEVERITIES = [
@@ -89,6 +89,89 @@ function normalizeHeading(value) {
89
89
  }
90
90
  return null;
91
91
  }
92
+ export function severityDisplayName(severity) {
93
+ return severity.charAt(0).toUpperCase() + severity.slice(1);
94
+ }
95
+ function markdownLines(content) {
96
+ const lines = [];
97
+ let start = 0;
98
+ while (start < content.length) {
99
+ const newlineIndex = content.indexOf('\n', start);
100
+ const end = newlineIndex === -1 ? content.length : newlineIndex;
101
+ lines.push({
102
+ text: content.slice(start, end),
103
+ start,
104
+ });
105
+ start = newlineIndex === -1 ? content.length : newlineIndex + 1;
106
+ }
107
+ return lines;
108
+ }
109
+ function fenceMarker(line) {
110
+ const match = line.match(/^\s*(`{3,}|~{3,})/);
111
+ if (!match?.[1]) {
112
+ return null;
113
+ }
114
+ return {
115
+ marker: match[1].startsWith('`') ? '`' : '~',
116
+ length: match[1].length,
117
+ };
118
+ }
119
+ function linesOutsideFences(content) {
120
+ const outsideFenceLines = [];
121
+ let activeFence = null;
122
+ for (const line of markdownLines(content)) {
123
+ const marker = fenceMarker(line.text);
124
+ if (marker) {
125
+ if (!activeFence) {
126
+ activeFence = marker;
127
+ }
128
+ else if (marker.marker === activeFence.marker &&
129
+ marker.length >= activeFence.length) {
130
+ activeFence = null;
131
+ }
132
+ continue;
133
+ }
134
+ if (!activeFence) {
135
+ outsideFenceLines.push(line);
136
+ }
137
+ }
138
+ return outsideFenceLines;
139
+ }
140
+ function findFindingsSection(content) {
141
+ const lines = linesOutsideFences(content);
142
+ const findingsHeading = lines.find((line) => /^##\s+Findings\s*#*\s*$/i.test(line.text));
143
+ if (!findingsHeading) {
144
+ return null;
145
+ }
146
+ const start = findingsHeading.start + findingsHeading.text.length;
147
+ const nextPeerHeading = lines.find((line) => line.start > findingsHeading.start &&
148
+ /^#{1,2}\s+.+?\s*#*\s*$/.test(line.text));
149
+ const end = nextPeerHeading?.start ?? content.length;
150
+ return {
151
+ start,
152
+ end,
153
+ content: content.slice(start, end),
154
+ };
155
+ }
156
+ function findSeverityHeadings(content) {
157
+ const findingsSection = findFindingsSection(content);
158
+ const scanContent = findingsSection?.content ?? content;
159
+ const offset = findingsSection?.start ?? 0;
160
+ return linesOutsideFences(scanContent)
161
+ .map((line) => {
162
+ const match = line.text.match(/^#{3,6}\s+(.+?)\s*#*\s*$/);
163
+ return {
164
+ severity: normalizeHeading(match?.[1] ?? ''),
165
+ index: offset + line.start,
166
+ headingLength: line.text.length,
167
+ };
168
+ })
169
+ .filter((heading) => heading.severity !== null);
170
+ }
171
+ function missingSeverityHeadings(severityHeadings) {
172
+ const seenSeverities = new Set(severityHeadings.map((heading) => heading.severity));
173
+ return SEVERITIES.filter((severity) => !seenSeverities.has(severity));
174
+ }
92
175
  function parseFindingsSummaryCounts(content) {
93
176
  const match = content.match(/^Findings:\s*(\d+)\s+critical,\s*(\d+)\s+important,\s*(\d+)\s+medium,\s*(\d+)\s+minor\s*$/im);
94
177
  if (!match) {
@@ -102,19 +185,12 @@ function parseFindingsSummaryCounts(content) {
102
185
  };
103
186
  }
104
187
  function parseFindingsSectionCounts(content, artifactPath) {
105
- const headingMatches = [...content.matchAll(/^#{3,6}\s+(.+?)\s*#*\s*$/gm)];
106
- const severityHeadings = headingMatches
107
- .map((match) => ({
108
- severity: normalizeHeading(match[1] ?? ''),
109
- index: match.index ?? 0,
110
- headingLength: match[0].length,
111
- }))
112
- .filter((heading) => heading.severity !== null);
188
+ const findingsSection = findFindingsSection(content);
189
+ const severityHeadings = findSeverityHeadings(content);
113
190
  if (severityHeadings.length === 0) {
114
191
  return null;
115
192
  }
116
- const seenSeverities = new Set(severityHeadings.map((heading) => heading.severity));
117
- const missingSeverities = SEVERITIES.filter((severity) => !seenSeverities.has(severity));
193
+ const missingSeverities = missingSeverityHeadings(severityHeadings);
118
194
  if (missingSeverities.length > 0) {
119
195
  throw new Error(`Review artifact at ${artifactPath} has an incomplete Findings section; expected headings for Critical, Important, Medium, and Minor. Missing: ${missingSeverities.join(', ')}.`);
120
196
  }
@@ -127,7 +203,7 @@ function parseFindingsSectionCounts(content, artifactPath) {
127
203
  for (const [offset, heading] of severityHeadings.entries()) {
128
204
  const nextHeading = severityHeadings[offset + 1];
129
205
  const sectionStart = heading.index + heading.headingLength;
130
- const sectionEnd = nextHeading?.index ?? content.length;
206
+ const sectionEnd = nextHeading?.index ?? findingsSection?.end ?? content.length;
131
207
  counts[heading.severity] = countFindingsInSection(content.slice(sectionStart, sectionEnd));
132
208
  }
133
209
  return counts;
@@ -150,7 +226,54 @@ function parseFrontmatterObject(frontmatter, artifactPath) {
150
226
  function hasBlockingFindings(counts) {
151
227
  return counts.critical > 0 || counts.important > 0;
152
228
  }
153
- export async function parseReviewGateVerdict(artifactPath) {
229
+ function insertionTextForSeverity(severity) {
230
+ return `\n### ${severityDisplayName(severity)}\n\nNone\n`;
231
+ }
232
+ function insertionPointForMissingSeverity(content, missingSeverity) {
233
+ const findingsSection = findFindingsSection(content);
234
+ const sectionEnd = findingsSection?.end ?? content.length;
235
+ const severityHeadings = findSeverityHeadings(content);
236
+ const missingSeverityRank = SEVERITIES.indexOf(missingSeverity);
237
+ const nextHeading = severityHeadings.find((heading) => SEVERITIES.indexOf(heading.severity) > missingSeverityRank);
238
+ return nextHeading?.index ?? sectionEnd;
239
+ }
240
+ function insertMissingSeveritySection(content, severity) {
241
+ const insertionPoint = insertionPointForMissingSeverity(content, severity);
242
+ const insertion = insertionTextForSeverity(severity);
243
+ const suffix = content.slice(insertionPoint);
244
+ const needsTrailingBlank = suffix.length > 0 ? '\n' : '';
245
+ return `${content.slice(0, insertionPoint)}${insertion}${needsTrailingBlank}${suffix}`;
246
+ }
247
+ async function normalizeMissingEmptySeveritySections(artifactPath, content, counts) {
248
+ if (!findFindingsSection(content)) {
249
+ throw new Error(`Review artifact at ${artifactPath} does not contain a ## Findings section, so missing severity headings cannot be safely normalized.`);
250
+ }
251
+ let normalizedContent = content;
252
+ const insertedSeverities = [];
253
+ for (const severity of missingSeverityHeadings(findSeverityHeadings(content))) {
254
+ if (counts[severity] !== 0) {
255
+ throw new Error(`Review artifact at ${artifactPath} is missing the ${severityDisplayName(severity)} Findings section, but structured counts report ${counts[severity]} ${severity} finding(s). This cannot be safely normalized.`);
256
+ }
257
+ normalizedContent = insertMissingSeveritySection(normalizedContent, severity);
258
+ insertedSeverities.push(severity);
259
+ }
260
+ if (insertedSeverities.length > 0) {
261
+ await writeFile(artifactPath, normalizedContent, 'utf8');
262
+ }
263
+ return { content: normalizedContent, insertedSeverities };
264
+ }
265
+ function resolveCounts(content, frontmatter) {
266
+ const frontmatterCounts = readFrontmatterCounts(frontmatter);
267
+ if (frontmatterCounts) {
268
+ return frontmatterCounts;
269
+ }
270
+ const summaryCounts = parseFindingsSummaryCounts(content);
271
+ if (summaryCounts) {
272
+ return summaryCounts;
273
+ }
274
+ return null;
275
+ }
276
+ export async function parseReviewGateVerdict(artifactPath, options = {}) {
154
277
  let content;
155
278
  try {
156
279
  content = await readFile(artifactPath, 'utf8');
@@ -163,9 +286,16 @@ export async function parseReviewGateVerdict(artifactPath) {
163
286
  const frontmatter = frontmatterBlock
164
287
  ? parseFrontmatterObject(frontmatterBlock, artifactPath)
165
288
  : {};
166
- const counts = readFrontmatterCounts(frontmatter) ??
167
- parseFindingsSummaryCounts(content) ??
168
- parseFindingsSectionCounts(content, artifactPath);
289
+ let counts = resolveCounts(content, frontmatter);
290
+ let insertedSeverities = [];
291
+ if (counts && options.normalizeMissingEmptySeveritySections) {
292
+ const normalized = await normalizeMissingEmptySeveritySections(artifactPath, content, counts);
293
+ content = normalized.content;
294
+ insertedSeverities = normalized.insertedSeverities;
295
+ }
296
+ if (!counts) {
297
+ counts = parseFindingsSectionCounts(content, artifactPath);
298
+ }
169
299
  if (!counts) {
170
300
  throw new Error(`Review artifact at ${artifactPath} does not contain recognizable review findings or explicit verdict counts.`);
171
301
  }
@@ -176,5 +306,12 @@ export async function parseReviewGateVerdict(artifactPath) {
176
306
  invocation: stringOrNull(frontmatter['oat_review_invocation']),
177
307
  counts,
178
308
  blocking: hasBlockingFindings(counts),
309
+ ...(insertedSeverities.length > 0
310
+ ? {
311
+ normalization: {
312
+ insertedSeverities,
313
+ },
314
+ }
315
+ : {}),
179
316
  };
180
317
  }
@@ -2,7 +2,7 @@ import { type CommandContext, type GlobalOptions } from '../../app/command-conte
2
2
  import { type ApplyOatCoreResult } from '../init/gitignore.js';
3
3
  import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../shared/shared.prompts.js';
4
4
  import { type SyncConfig } from '../../config/index.js';
5
- import { type OatConfig } from '../../config/oat-config.js';
5
+ import { type OatConfig, type UserConfig } from '../../config/oat-config.js';
6
6
  import { type DriftReport } from '../../drift/index.js';
7
7
  import { type CanonicalEntry, type HookInstallInfo } from '../../engine/index.js';
8
8
  import type { Manifest } from '../../manifest/manifest.types.js';
@@ -42,6 +42,7 @@ interface InitDependencies {
42
42
  uninstallHook: (projectRoot: string) => Promise<void>;
43
43
  getAdapters: () => ProviderAdapter[];
44
44
  loadSyncConfig: (configPath: string) => Promise<SyncConfig>;
45
+ readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
45
46
  saveSyncConfig: (configPath: string, config: SyncConfig) => Promise<SyncConfig>;
46
47
  getConfigAwareAdapters: (adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig) => Promise<ConfigAwareAdaptersResult>;
47
48
  applyOatCoreGitignore: (repoRoot: string) => Promise<ApplyOatCoreResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,8 @@ import { withScopeOption } from '../shared/scope-option.js';
12
12
  import { confirmAction, inputWithDefault, selectManyWithAbort, selectWithAbort, } from '../shared/shared.prompts.js';
13
13
  import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
14
14
  import { DEFAULT_SYNC_CONFIG, loadSyncConfig, saveSyncConfig, } from '../../config/index.js';
15
- import { detectDefaultBranch, readOatConfig, resolveLocalPaths, writeOatConfig, } from '../../config/oat-config.js';
16
- import { detectStrays } from '../../drift/index.js';
15
+ import { detectDefaultBranch, readUserConfig, readOatConfig, resolveLocalPaths, writeOatConfig, } from '../../config/oat-config.js';
16
+ import { detectStrays, filterKnownStrays, } from '../../drift/index.js';
17
17
  import { configureLocalHooksPath, getHookInstallInfo, installHook, isHookInstalled, scanCanonical, uninstallHook, } from '../../engine/index.js';
18
18
  import { dirExists, fileExists } from '../../fs/io.js';
19
19
  import { resolveProjectRoot, resolveScopeRoot } from '../../fs/paths.js';
@@ -131,6 +131,7 @@ function createDependencies() {
131
131
  async loadSyncConfig(configPath) {
132
132
  return loadSyncConfig(configPath, DEFAULT_SYNC_CONFIG);
133
133
  },
134
+ readUserConfig,
134
135
  saveSyncConfig,
135
136
  getConfigAwareAdapters,
136
137
  applyOatCoreGitignore,
@@ -428,13 +429,16 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
428
429
  const scopeSummaries = [];
429
430
  for (const scope of scopes) {
430
431
  const scopeRoot = await dependencies.resolveScopeRoot(scope, context);
432
+ const syncConfigPath = join(scopeRoot, '.oat', 'sync', 'config.json');
433
+ const userConfigDir = join(context.home, '.oat');
434
+ let syncConfig = await dependencies.loadSyncConfig(syncConfigPath);
435
+ const userConfig = await dependencies.readUserConfig(userConfigDir);
431
436
  let activeAdaptersForStrays;
432
437
  if (scope === 'project') {
433
438
  projectRoot = scopeRoot;
434
439
  oatDirExistedBefore = await dependencies.dirExists(join(scopeRoot, '.oat'));
435
- const configPath = join(scopeRoot, '.oat', 'sync', 'config.json');
436
440
  const adapters = dependencies.getAdapters();
437
- let config = await dependencies.loadSyncConfig(configPath);
441
+ let config = syncConfig;
438
442
  let resolution = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, config);
439
443
  if (!context.interactive && !context.json) {
440
444
  context.logger.info(PROVIDER_CONFIG_REMEDIATION);
@@ -457,10 +461,11 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
457
461
  enabled: selectedProviderNames.has(adapter.name),
458
462
  };
459
463
  }
460
- config = await dependencies.saveSyncConfig(configPath, {
464
+ config = await dependencies.saveSyncConfig(syncConfigPath, {
461
465
  ...config,
462
466
  providers,
463
467
  });
468
+ syncConfig = config;
464
469
  }
465
470
  resolution = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, config);
466
471
  }
@@ -476,7 +481,15 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
476
481
  manifest = createEmptyManifest();
477
482
  }
478
483
  const canonicalEntries = await dependencies.scanCanonical(scopeRoot, scope);
479
- const strays = await dependencies.collectStrays(scopeRoot, scope, manifest, canonicalEntries, activeAdaptersForStrays);
484
+ const collectedStrays = await dependencies.collectStrays(scopeRoot, scope, manifest, canonicalEntries, activeAdaptersForStrays);
485
+ const { candidates: strays } = filterKnownStrays({
486
+ reports: collectedStrays.map((stray) => stray.report),
487
+ candidates: collectedStrays,
488
+ knownStrays: {
489
+ project: syncConfig.knownStrays,
490
+ user: userConfig.knownStrays,
491
+ },
492
+ });
480
493
  let straysAdopted = 0;
481
494
  if (!context.interactive && strays.length > 0) {
482
495
  context.logger.warn(ADOPT_REMEDIATION);
@@ -1,6 +1,8 @@
1
1
  import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
2
2
  import { type CodexRoleStray } from '../shared/codex-strays.js';
3
3
  import { type MultiSelectChoice, type PromptContext } from '../shared/shared.prompts.js';
4
+ import { type SyncConfig } from '../../config/index.js';
5
+ import { type UserConfig } from '../../config/oat-config.js';
4
6
  import { type CopyTransform, type DriftReport } from '../../drift/index.js';
5
7
  import { type CanonicalEntry } from '../../engine/index.js';
6
8
  import type { Manifest } from '../../manifest/index.js';
@@ -12,6 +14,8 @@ interface StatusDependencies {
12
14
  buildCommandContext: (options: GlobalOptions) => CommandContext;
13
15
  resolveScopeRoot: (scope: ConcreteScope, context: CommandContext) => Promise<string>;
14
16
  loadManifest: (manifestPath: string) => Promise<Manifest>;
17
+ loadSyncConfig: (configPath: string) => Promise<SyncConfig>;
18
+ readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
15
19
  saveManifest: (manifestPath: string, manifest: Manifest) => Promise<void>;
16
20
  scanCanonical: (scopeRoot: string, scope: ConcreteScope) => Promise<CanonicalEntry[]>;
17
21
  getAdapters: () => ProviderAdapter[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,9 @@ import { detectCodexRoleStrays, regenerateCodexAfterAdoption, } from '../shared/
5
5
  import { withScopeOption } from '../shared/scope-option.js';
6
6
  import { confirmAction, selectManyWithAbort, } from '../shared/shared.prompts.js';
7
7
  import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
8
- import { detectDrift, detectStrays, } from '../../drift/index.js';
8
+ import { DEFAULT_SYNC_CONFIG, loadSyncConfig, } from '../../config/index.js';
9
+ import { readUserConfig } from '../../config/oat-config.js';
10
+ import { detectDrift, detectStrays, filterKnownStrays, } from '../../drift/index.js';
9
11
  import { HOOK_DRIFT_WARNING, HOOK_STRAY_INFO, scanCanonical, } from '../../engine/index.js';
10
12
  import { normalizeToPosixPath, resolveProjectRoot, resolveScopeRoot, } from '../../fs/paths.js';
11
13
  import { loadManifest, saveManifest } from '../../manifest/manager.js';
@@ -29,6 +31,10 @@ const DEFAULT_DEPENDENCIES = {
29
31
  return resolveScopeRoot(scope, context.cwd, context.home);
30
32
  },
31
33
  loadManifest,
34
+ async loadSyncConfig(configPath) {
35
+ return loadSyncConfig(configPath, DEFAULT_SYNC_CONFIG);
36
+ },
37
+ readUserConfig,
32
38
  saveManifest,
33
39
  scanCanonical,
34
40
  getAdapters() {
@@ -113,8 +119,14 @@ function formatStrayChoiceLabel(scope, providerPath, provider) {
113
119
  async function collectScopeReports(scope, context, dependencies) {
114
120
  const scopeRoot = await dependencies.resolveScopeRoot(scope, context);
115
121
  const manifestPath = join(scopeRoot, '.oat', 'sync', 'manifest.json');
116
- const manifest = await dependencies.loadManifest(manifestPath);
117
- const canonicalEntries = await dependencies.scanCanonical(scopeRoot, scope);
122
+ const syncConfigPath = join(scopeRoot, '.oat', 'sync', 'config.json');
123
+ const userConfigDir = join(context.home, '.oat');
124
+ const [manifest, canonicalEntries, syncConfig, userConfig] = await Promise.all([
125
+ dependencies.loadManifest(manifestPath),
126
+ dependencies.scanCanonical(scopeRoot, scope),
127
+ dependencies.loadSyncConfig(syncConfigPath),
128
+ dependencies.readUserConfig(userConfigDir),
129
+ ]);
118
130
  const adapters = dependencies.getAdapters();
119
131
  const activeAdapters = await dependencies.getActiveAdapters(adapters, scopeRoot);
120
132
  const reports = [];
@@ -234,13 +246,21 @@ async function collectScopeReports(scope, context, dependencies) {
234
246
  });
235
247
  }
236
248
  }
249
+ const filtered = filterKnownStrays({
250
+ reports,
251
+ candidates: strayCandidates,
252
+ knownStrays: {
253
+ project: syncConfig.knownStrays,
254
+ user: userConfig.knownStrays,
255
+ },
256
+ });
237
257
  return {
238
258
  scope,
239
259
  scopeRoot,
240
260
  manifestPath,
241
261
  manifest,
242
- reports,
243
- strayCandidates,
262
+ reports: filtered.reports,
263
+ strayCandidates: filtered.candidates,
244
264
  };
245
265
  }
246
266
  async function runStatusCommand(context, dependencies, options = {}) {
@@ -98,6 +98,7 @@ export interface OatLocalConfig {
98
98
  export interface UserConfig {
99
99
  version: number;
100
100
  activeIdea?: string | null;
101
+ knownStrays?: string[];
101
102
  workflow?: OatWorkflowConfig;
102
103
  }
103
104
  export interface ActiveProjectResolution {
@@ -1 +1 @@
1
- {"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
@@ -260,6 +260,24 @@ function trimNonEmptyString(value) {
260
260
  const trimmed = value.trim();
261
261
  return trimmed.length > 0 ? trimmed : undefined;
262
262
  }
263
+ function normalizeKnownStrayPath(pathValue) {
264
+ const trimmed = pathValue.trim();
265
+ if (!trimmed) {
266
+ return undefined;
267
+ }
268
+ const normalized = trimPathValue(normalizeToPosixPath(trimmed));
269
+ return normalized && normalized !== '.' ? normalized : undefined;
270
+ }
271
+ function normalizeKnownStrays(value) {
272
+ if (!Array.isArray(value)) {
273
+ return undefined;
274
+ }
275
+ const normalized = value
276
+ .filter((pathValue) => typeof pathValue === 'string')
277
+ .map((pathValue) => normalizeKnownStrayPath(pathValue))
278
+ .filter((pathValue) => pathValue !== undefined);
279
+ return normalized.length > 0 ? [...new Set(normalized)].sort() : undefined;
280
+ }
263
281
  function normalizeProjectPath(repoRoot, pathValue) {
264
282
  if (pathValue == null) {
265
283
  return null;
@@ -523,6 +541,10 @@ function normalizeUserConfig(parsed) {
523
541
  ? parsed.activeIdea.trim()
524
542
  : null;
525
543
  }
544
+ const knownStrays = normalizeKnownStrays(parsed.knownStrays);
545
+ if (knownStrays) {
546
+ next.knownStrays = knownStrays;
547
+ }
526
548
  const workflow = normalizeWorkflowConfig(parsed.workflow);
527
549
  if (workflow) {
528
550
  next.workflow = workflow;
@@ -12,6 +12,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
12
12
  export declare const SyncConfigSchema: z.ZodObject<{
13
13
  version: z.ZodLiteral<1>;
14
14
  defaultStrategy: z.ZodEnum<["symlink", "copy", "auto"]>;
15
+ knownStrays: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
15
16
  providers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
16
17
  strategy: z.ZodOptional<z.ZodEnum<["symlink", "copy", "auto"]>>;
17
18
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -29,6 +30,7 @@ export declare const SyncConfigSchema: z.ZodObject<{
29
30
  strategy?: "symlink" | "copy" | "auto" | undefined;
30
31
  enabled?: boolean | undefined;
31
32
  }> | undefined;
33
+ knownStrays?: string[] | undefined;
32
34
  }, {
33
35
  version: 1;
34
36
  defaultStrategy: "symlink" | "copy" | "auto";
@@ -36,9 +38,11 @@ export declare const SyncConfigSchema: z.ZodObject<{
36
38
  strategy?: "symlink" | "copy" | "auto" | undefined;
37
39
  enabled?: boolean | undefined;
38
40
  }> | undefined;
41
+ knownStrays?: string[] | undefined;
39
42
  }>;
40
43
  export type ProviderSyncConfig = z.infer<typeof ProviderConfigSchema>;
41
44
  export type SyncConfig = z.infer<typeof SyncConfigSchema> & {
45
+ knownStrays: string[];
42
46
  providers: Record<string, ProviderSyncConfig>;
43
47
  };
44
48
  export declare const DEFAULT_SYNC_CONFIG: SyncConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-config.d.ts","sourceRoot":"","sources":["../../src/config/sync-config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,oBAAoB;;;;;;;;;EAGxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI3B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC1D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAIjC,CAAC;AAoDF,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,UAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CA4BrB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB"}
1
+ {"version":3,"file":"sync-config.d.ts","sourceRoot":"","sources":["../../src/config/sync-config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,oBAAoB;;;;;;;;;EAGxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK3B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC1D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAKjC,CAAC;AA6EF,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,UAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB"}
@@ -1,6 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { CliError } from '../errors/index.js';
3
3
  import { atomicWriteJson } from '../fs/io.js';
4
+ import { normalizeToPosixPath } from '../fs/paths.js';
4
5
  import { SyncStrategySchema } from '../shared/types.js';
5
6
  import { z } from 'zod';
6
7
  import { parseJsonConfig } from './json.js';
@@ -11,11 +12,13 @@ const ProviderConfigSchema = z.object({
11
12
  export const SyncConfigSchema = z.object({
12
13
  version: z.literal(1),
13
14
  defaultStrategy: SyncStrategySchema,
15
+ knownStrays: z.array(z.string()).optional(),
14
16
  providers: z.record(ProviderConfigSchema).optional(),
15
17
  });
16
18
  export const DEFAULT_SYNC_CONFIG = {
17
19
  version: 1,
18
20
  defaultStrategy: 'auto',
21
+ knownStrays: [],
19
22
  providers: {},
20
23
  };
21
24
  function mergeProviderConfigs(base, override) {
@@ -28,10 +31,30 @@ function mergeProviderConfigs(base, override) {
28
31
  }
29
32
  return merged;
30
33
  }
34
+ function normalizeKnownStrayPath(pathValue) {
35
+ const trimmed = pathValue.trim();
36
+ if (!trimmed) {
37
+ return undefined;
38
+ }
39
+ const normalized = normalizeToPosixPath(trimmed)
40
+ .replace(/\/+$/, '')
41
+ .replace(/^\.\//, '');
42
+ return normalized && normalized !== '.' ? normalized : undefined;
43
+ }
44
+ function normalizeKnownStrays(paths) {
45
+ const normalized = paths
46
+ ?.map((pathValue) => normalizeKnownStrayPath(pathValue))
47
+ .filter((pathValue) => pathValue !== undefined);
48
+ return [...new Set(normalized ?? [])].sort();
49
+ }
31
50
  function normalizeConfig(config, defaults) {
32
51
  return {
33
52
  version: 1,
34
53
  defaultStrategy: config.defaultStrategy ?? defaults.defaultStrategy,
54
+ knownStrays: normalizeKnownStrays([
55
+ ...defaults.knownStrays,
56
+ ...(config.knownStrays ?? []),
57
+ ]),
35
58
  providers: mergeProviderConfigs(defaults.providers, config.providers ?? {}),
36
59
  };
37
60
  }
@@ -61,6 +84,7 @@ export async function loadSyncConfig(configPath, defaults = DEFAULT_SYNC_CONFIG)
61
84
  error.code === 'ENOENT') {
62
85
  return {
63
86
  ...defaults,
87
+ knownStrays: [...defaults.knownStrays],
64
88
  providers: { ...defaults.providers },
65
89
  };
66
90
  }
@@ -1,5 +1,7 @@
1
1
  export { detectDrift } from './detector.js';
2
2
  export type { CopyTransform } from './detector.js';
3
3
  export type { DriftReport, DriftState } from './drift.types.js';
4
+ export { filterKnownStrays } from './known-strays.js';
5
+ export type { FilterKnownStraysOptions, FilterKnownStraysResult, KnownStrayCandidate, KnownStraySources, } from './known-strays.js';
4
6
  export { detectStrays } from './strays.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drift/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drift/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { detectDrift } from './detector.js';
2
+ export { filterKnownStrays } from './known-strays.js';
2
3
  export { detectStrays } from './strays.js';
@@ -0,0 +1,19 @@
1
+ import type { DriftReport } from './drift.types.js';
2
+ export interface KnownStraySources {
3
+ project?: readonly string[];
4
+ user?: readonly string[];
5
+ }
6
+ export interface KnownStrayCandidate {
7
+ report: DriftReport;
8
+ }
9
+ export interface FilterKnownStraysOptions<Candidate extends KnownStrayCandidate> {
10
+ reports: readonly DriftReport[];
11
+ candidates: readonly Candidate[];
12
+ knownStrays?: KnownStraySources;
13
+ }
14
+ export interface FilterKnownStraysResult<Candidate extends KnownStrayCandidate> {
15
+ reports: DriftReport[];
16
+ candidates: Candidate[];
17
+ }
18
+ export declare function filterKnownStrays<Candidate extends KnownStrayCandidate>(options: FilterKnownStraysOptions<Candidate>): FilterKnownStraysResult<Candidate>;
19
+ //# sourceMappingURL=known-strays.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"known-strays.d.ts","sourceRoot":"","sources":["../../src/drift/known-strays.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB,CACvC,SAAS,SAAS,mBAAmB;IAErC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB,CACtC,SAAS,SAAS,mBAAmB;IAErC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAuCD,wBAAgB,iBAAiB,CAAC,SAAS,SAAS,mBAAmB,EACrE,OAAO,EAAE,wBAAwB,CAAC,SAAS,CAAC,GAC3C,uBAAuB,CAAC,SAAS,CAAC,CAiBpC"}
@@ -0,0 +1,37 @@
1
+ import { normalizeToPosixPath } from '../fs/paths.js';
2
+ function normalizeProviderPath(pathValue) {
3
+ const trimmed = pathValue.trim();
4
+ if (!trimmed) {
5
+ return undefined;
6
+ }
7
+ const normalized = normalizeToPosixPath(trimmed)
8
+ .replace(/\/+$/, '')
9
+ .replace(/^\.\//, '');
10
+ return normalized && normalized !== '.' ? normalized : undefined;
11
+ }
12
+ function resolveKnownStrayPaths(knownStrays) {
13
+ const paths = [...(knownStrays?.project ?? []), ...(knownStrays?.user ?? [])];
14
+ return new Set(paths
15
+ .map((pathValue) => normalizeProviderPath(pathValue))
16
+ .filter((pathValue) => pathValue !== undefined));
17
+ }
18
+ function isKnownStrayReport(report, knownStrayPaths) {
19
+ if (report.state.status !== 'stray') {
20
+ return false;
21
+ }
22
+ const providerPath = normalizeProviderPath(report.providerPath);
23
+ return providerPath !== undefined && knownStrayPaths.has(providerPath);
24
+ }
25
+ export function filterKnownStrays(options) {
26
+ const knownStrayPaths = resolveKnownStrayPaths(options.knownStrays);
27
+ if (knownStrayPaths.size === 0) {
28
+ return {
29
+ reports: [...options.reports],
30
+ candidates: [...options.candidates],
31
+ };
32
+ }
33
+ return {
34
+ reports: options.reports.filter((report) => !isKnownStrayReport(report, knownStrayPaths)),
35
+ candidates: options.candidates.filter((candidate) => !isKnownStrayReport(candidate.report, knownStrayPaths)),
36
+ };
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "private": false,
5
5
  "description": "Open Agent Toolkit CLI",
6
6
  "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
@@ -34,7 +34,7 @@
34
34
  "ora": "^9.0.0",
35
35
  "yaml": "2.8.2",
36
36
  "zod": "^3.25.76",
37
- "@open-agent-toolkit/control-plane": "0.1.37"
37
+ "@open-agent-toolkit/control-plane": "0.1.39"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",