@open-agent-toolkit/cli 0.1.34 → 0.1.36

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 (88) hide show
  1. package/assets/agents/oat-reviewer.md +22 -2
  2. package/assets/docs/cli-utilities/config-and-local-state.md +11 -5
  3. package/assets/docs/cli-utilities/tool-packs.md +1 -1
  4. package/assets/docs/cli-utilities/workflow-gates.md +103 -19
  5. package/assets/docs/contributing/design-principles.md +1 -1
  6. package/assets/docs/reference/cli-reference.md +4 -3
  7. package/assets/public-package-versions.json +4 -4
  8. package/assets/skills/oat-project-implement/SKILL.md +7 -3
  9. package/assets/skills/oat-project-import-plan/SKILL.md +53 -9
  10. package/assets/skills/oat-project-plan/SKILL.md +7 -3
  11. package/assets/skills/oat-project-quick-start/SKILL.md +37 -9
  12. package/assets/skills/oat-project-review-provide/SKILL.md +12 -4
  13. package/assets/skills/oat-project-review-receive/SKILL.md +3 -1
  14. package/dist/app/create-program.d.ts.map +1 -1
  15. package/dist/app/create-program.js +3 -6
  16. package/dist/app/help-config.d.ts +12 -0
  17. package/dist/app/help-config.d.ts.map +1 -0
  18. package/dist/app/help-config.js +15 -0
  19. package/dist/commands/doctor/index.d.ts.map +1 -1
  20. package/dist/commands/doctor/index.js +2 -1
  21. package/dist/commands/gate/index.d.ts.map +1 -1
  22. package/dist/commands/gate/index.js +352 -16
  23. package/dist/commands/gate/review-verdict.d.ts +15 -0
  24. package/dist/commands/gate/review-verdict.d.ts.map +1 -0
  25. package/dist/commands/gate/review-verdict.js +180 -0
  26. package/dist/commands/index.d.ts.map +1 -1
  27. package/dist/commands/index.js +4 -0
  28. package/dist/commands/init/index.d.ts.map +1 -1
  29. package/dist/commands/init/index.js +2 -1
  30. package/dist/commands/init/tools/brainstorm/index.d.ts.map +1 -1
  31. package/dist/commands/init/tools/brainstorm/index.js +2 -1
  32. package/dist/commands/init/tools/core/index.d.ts.map +1 -1
  33. package/dist/commands/init/tools/core/index.js +18 -0
  34. package/dist/commands/init/tools/docs/index.d.ts.map +1 -1
  35. package/dist/commands/init/tools/docs/index.js +2 -1
  36. package/dist/commands/init/tools/ideas/index.d.ts.map +1 -1
  37. package/dist/commands/init/tools/ideas/index.js +2 -1
  38. package/dist/commands/init/tools/project-management/index.d.ts.map +1 -1
  39. package/dist/commands/init/tools/project-management/index.js +19 -0
  40. package/dist/commands/init/tools/research/index.d.ts.map +1 -1
  41. package/dist/commands/init/tools/research/index.js +2 -1
  42. package/dist/commands/init/tools/utility/index.d.ts.map +1 -1
  43. package/dist/commands/init/tools/utility/index.js +2 -1
  44. package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
  45. package/dist/commands/init/tools/workflows/index.js +2 -1
  46. package/dist/commands/project/split/evaluate-signals.d.ts.map +1 -1
  47. package/dist/commands/project/split/evaluate-signals.js +11 -1
  48. package/dist/commands/project/split/run.d.ts.map +1 -1
  49. package/dist/commands/project/split/run.js +14 -0
  50. package/dist/commands/project/split/validate-plan.d.ts.map +1 -1
  51. package/dist/commands/project/split/validate-plan.js +30 -6
  52. package/dist/commands/project/validate-plan/index.d.ts +6 -1
  53. package/dist/commands/project/validate-plan/index.d.ts.map +1 -1
  54. package/dist/commands/project/validate-plan/index.js +36 -9
  55. package/dist/commands/providers/inspect/inspect.d.ts.map +1 -1
  56. package/dist/commands/providers/inspect/inspect.js +2 -1
  57. package/dist/commands/providers/list/list.d.ts.map +1 -1
  58. package/dist/commands/providers/list/list.js +2 -1
  59. package/dist/commands/providers/set/index.d.ts.map +1 -1
  60. package/dist/commands/providers/set/index.js +6 -2
  61. package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
  62. package/dist/commands/remove/skill/remove-skill.js +2 -1
  63. package/dist/commands/remove/skills/remove-skills.d.ts.map +1 -1
  64. package/dist/commands/remove/skills/remove-skills.js +2 -1
  65. package/dist/commands/repo/pr-comments/triage-collection/triage-comments.d.ts +1 -0
  66. package/dist/commands/repo/pr-comments/triage-collection/triage-comments.d.ts.map +1 -1
  67. package/dist/commands/repo/pr-comments/triage-collection/triage-comments.js +25 -13
  68. package/dist/commands/shared/scope-option.d.ts +21 -0
  69. package/dist/commands/shared/scope-option.d.ts.map +1 -0
  70. package/dist/commands/shared/scope-option.js +24 -0
  71. package/dist/commands/status/index.d.ts.map +1 -1
  72. package/dist/commands/status/index.js +2 -1
  73. package/dist/commands/sync/index.d.ts.map +1 -1
  74. package/dist/commands/sync/index.js +2 -1
  75. package/dist/commands/tools/info/index.d.ts.map +1 -1
  76. package/dist/commands/tools/info/index.js +2 -1
  77. package/dist/commands/tools/install/index.d.ts.map +1 -1
  78. package/dist/commands/tools/install/index.js +2 -0
  79. package/dist/commands/tools/list/index.d.ts.map +1 -1
  80. package/dist/commands/tools/list/index.js +2 -1
  81. package/dist/commands/tools/outdated/index.d.ts.map +1 -1
  82. package/dist/commands/tools/outdated/index.js +2 -1
  83. package/dist/commands/tools/remove/index.d.ts.map +1 -1
  84. package/dist/commands/tools/remove/index.js +2 -1
  85. package/dist/commands/tools/update/index.d.ts.map +1 -1
  86. package/dist/commands/tools/update/index.js +6 -2
  87. package/dist/config/oat-config.js +1 -1
  88. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"create-program.d.ts","sourceRoot":"","sources":["../../src/app/create-program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAO5C,wBAAgB,aAAa,IAAI,OAAO,CAavC"}
1
+ {"version":3,"file":"create-program.d.ts","sourceRoot":"","sources":["../../src/app/create-program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,aAAa,IAAI,OAAO,CASvC"}
@@ -1,8 +1,7 @@
1
1
  import { OAT_VERSION } from '../shared/oat-version.js';
2
- import { Command, Option } from 'commander';
2
+ import { Command } from 'commander';
3
3
  const PROGRAM_NAME = 'oat';
4
4
  const PROGRAM_DESCRIPTION = 'Open Agent Toolkit CLI for provider interoperability';
5
- const SCOPE_CHOICES = ['project', 'user', 'all'];
6
5
  export function createProgram() {
7
6
  return new Command()
8
7
  .name(PROGRAM_NAME)
@@ -10,8 +9,6 @@ export function createProgram() {
10
9
  .version(OAT_VERSION)
11
10
  .option('--json', 'Output a single JSON document')
12
11
  .option('--verbose', 'Enable verbose debug output')
13
- .addOption(new Option('--scope <scope>', 'Limit execution scope')
14
- .choices([...SCOPE_CHOICES])
15
- .default('all'))
16
- .option('--cwd <path>', 'Override working directory');
12
+ .option('--cwd <path>', 'Override working directory')
13
+ .configureHelp({ showGlobalOptions: true });
17
14
  }
@@ -0,0 +1,12 @@
1
+ import type { Command } from 'commander';
2
+ /**
3
+ * Commander's `.addCommand()` does not inherit the parent's help configuration.
4
+ * This recursive helper applies `showGlobalOptions: true` to every node in the
5
+ * command tree after registration, so that each subcommand's `--help` output
6
+ * includes a "Global Options" section showing `--json`, `--verbose`, and `--cwd`.
7
+ *
8
+ * Must be called once at the end of `registerCommands(program)` after all
9
+ * subcommands have been added via `.addCommand()`.
10
+ */
11
+ export declare function applyHelpConfiguration(command: Command): void;
12
+ //# sourceMappingURL=help-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-config.d.ts","sourceRoot":"","sources":["../../src/app/help-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK7D"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Commander's `.addCommand()` does not inherit the parent's help configuration.
3
+ * This recursive helper applies `showGlobalOptions: true` to every node in the
4
+ * command tree after registration, so that each subcommand's `--help` output
5
+ * includes a "Global Options" section showing `--json`, `--verbose`, and `--cwd`.
6
+ *
7
+ * Must be called once at the end of `registerCommands(program)` after all
8
+ * subcommands have been added via `.addCommand()`.
9
+ */
10
+ export function applyHelpConfiguration(command) {
11
+ command.configureHelp({ showGlobalOptions: true });
12
+ for (const sub of command.commands) {
13
+ applyHelpConfiguration(sub);
14
+ }
15
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAInE,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,KACd,OAAO,CACV,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CACnE,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClC;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,cAAc,EAAE,oBAAoB,EAAE,CAAC;CACxC;AAsbD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC1C,OAAO,CAcT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAInE,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,KACd,OAAO,CACV,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CACnE,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClC;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,cAAc,EAAE,oBAAoB,EAAE,CAAC;CACxC;AAsbD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC1C,OAAO,CAcT"}
@@ -5,6 +5,7 @@ import { buildCommandContext, } from '../../app/command-context.js';
5
5
  import { compareVersions } from '../init/tools/shared/version.js';
6
6
  import { createPjmDisabledCheck, runPjmDoctorChecks, } from '../pjm/doctor.js';
7
7
  import { getSkillVersion } from '../shared/frontmatter.js';
8
+ import { withScopeOption } from '../shared/scope-option.js';
8
9
  import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
9
10
  import { readOatConfig } from '../../config/oat-config.js';
10
11
  import { resolveAssetsRoot } from '../../fs/assets.js';
@@ -379,7 +380,7 @@ export function createDoctorCommand(overrides = {}) {
379
380
  ...createDependencies(),
380
381
  ...overrides,
381
382
  };
382
- return new Command('doctor')
383
+ return withScopeOption(new Command('doctor'))
383
384
  .description('Run environment and setup diagnostics')
384
385
  .action(async (_options, command) => {
385
386
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,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;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,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;AAmCD,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;AAKlD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAmWD,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;AA2SD,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAoIT"}
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;AAkZD,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,11 +1,16 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { join } from 'node:path';
2
+ import { createHash } from 'node:crypto';
3
+ import { readdir, readFile } from 'node:fs/promises';
4
+ import { basename, isAbsolute, join, relative } from 'node:path';
3
5
  import { buildCommandContext, } from '../../app/command-context.js';
6
+ import { getFrontmatterBlock, getFrontmatterField, } from '../shared/frontmatter.js';
4
7
  import { readGlobalOptions } from '../shared/shared.utils.js';
5
8
  import { BUILTIN_EXEC_TARGETS, readOatConfig, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
6
9
  import { resolveEffectiveConfig, resolveExecTargets, resolveGate, } from '../../config/resolve.js';
7
- import { resolveProjectRoot } from '../../fs/paths.js';
10
+ import { dirExists, fileExists } from '../../fs/io.js';
11
+ import { normalizeToPosixPath, resolveProjectRoot } from '../../fs/paths.js';
8
12
  import { Command } from 'commander';
13
+ import { parseReviewGateVerdict, } from './review-verdict.js';
9
14
  const DEFAULT_DEPENDENCIES = {
10
15
  buildCommandContext,
11
16
  resolveProjectRoot,
@@ -29,6 +34,16 @@ const VALID_CROSS_PROVIDER_AVOIDS = [
29
34
  'same-runtime',
30
35
  'none',
31
36
  ];
37
+ const VALID_REVIEW_GATE_THRESHOLDS = [
38
+ 'critical',
39
+ 'important',
40
+ 'medium',
41
+ 'minor',
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.';
44
+ function reviewGateProjectContext(projectPath) {
45
+ return `Resolved OAT project path: ${projectPath}. Run the review for this project path.`;
46
+ }
32
47
  async function runChildProcess(command, args, options) {
33
48
  return new Promise((resolve, reject) => {
34
49
  const child = spawn(command, args, {
@@ -90,6 +105,13 @@ function parseCrossProviderAvoid(value) {
90
105
  }
91
106
  return avoid;
92
107
  }
108
+ function parseReviewGateThreshold(value) {
109
+ const threshold = value?.trim() || 'important';
110
+ if (!VALID_REVIEW_GATE_THRESHOLDS.includes(threshold)) {
111
+ throw new Error('--exit-nonzero-on must be one of critical | important | medium | minor.');
112
+ }
113
+ return threshold;
114
+ }
93
115
  function parseOnFailure(value) {
94
116
  if (!value || !VALID_ON_FAILURE.includes(value)) {
95
117
  throw new Error('--on-failure must be one of block | prompt | warn.');
@@ -149,6 +171,15 @@ function parseGateConfig(options) {
149
171
  : {}),
150
172
  };
151
173
  }
174
+ function detectDevBuildGateCommandWarnings(command) {
175
+ const normalized = command.trim();
176
+ if (!/^node\s+(?:"[^"]*\/packages\/cli\/dist\/index\.js"|'[^']*\/packages\/cli\/dist\/index\.js'|\S*\/packages\/cli\/dist\/index\.js)\s+gate(?:\s|$)/.test(normalized)) {
177
+ return [];
178
+ }
179
+ return [
180
+ 'Durable docs/config should reference `oat gate ...`; absolute dev-build paths are reserved for local development of unmerged behavior.',
181
+ ];
182
+ }
152
183
  function parseExecTargetConfig(options) {
153
184
  if (options.disable) {
154
185
  return null;
@@ -299,6 +330,23 @@ async function selectAvailableExecTarget(registry, currentRuntime, avoid, contex
299
330
  }
300
331
  return null;
301
332
  }
333
+ async function resolveSelectedExecTarget(targets, options, context, dependencies) {
334
+ const explicitTarget = options.target?.trim();
335
+ if (explicitTarget) {
336
+ const target = targets[explicitTarget];
337
+ if (!target) {
338
+ throw new Error(`Unknown exec target "${explicitTarget}".`);
339
+ }
340
+ return { id: explicitTarget, target: cloneExecTarget(target) };
341
+ }
342
+ const avoid = parseCrossProviderAvoid(options.avoid);
343
+ const currentRuntime = await resolveCurrentRuntime(options.currentRuntime, context, dependencies);
344
+ const selected = await selectAvailableExecTarget(targets, currentRuntime, avoid, context, dependencies);
345
+ if (!selected) {
346
+ throw new Error(noEligibleTargetMessage(currentRuntime, avoid));
347
+ }
348
+ return selected;
349
+ }
302
350
  async function executeTarget(selected, prompt, context, dependencies) {
303
351
  const [command, baseArgs] = argvHead(selected.target.baseCommand);
304
352
  if (!command) {
@@ -321,6 +369,217 @@ async function executeTarget(selected, prompt, context, dependencies) {
321
369
  function noEligibleTargetMessage(currentRuntime, avoid) {
322
370
  return `No eligible gate exec target found for current runtime "${currentRuntime}" with --avoid ${avoid}. Install or configure an alternate runtime, rerun with --avoid none, or pin a target with --target <id>.`;
323
371
  }
372
+ function normalizeRepoRelativeProjectPath(repoRoot, pathValue) {
373
+ const trimmed = pathValue.trim().replace(/\/+$/, '');
374
+ const withoutState = trimmed.endsWith('/state.md')
375
+ ? trimmed.slice(0, -'/state.md'.length)
376
+ : trimmed;
377
+ const repoRelative = isAbsolute(withoutState)
378
+ ? relative(repoRoot, withoutState)
379
+ : withoutState;
380
+ const normalized = normalizeToPosixPath(repoRelative).replace(/^\.\//, '');
381
+ if (normalized === '..' || normalized.startsWith('../')) {
382
+ throw new Error(`Project path must resolve inside the current repository: ${pathValue}`);
383
+ }
384
+ return normalized;
385
+ }
386
+ async function listProjectCandidates(repoRoot, projectsRoot) {
387
+ const normalizedProjectsRoot = normalizeRepoRelativeProjectPath(repoRoot, projectsRoot);
388
+ const absoluteProjectsRoot = join(repoRoot, normalizedProjectsRoot);
389
+ let scopeEntries;
390
+ try {
391
+ scopeEntries = await readdir(absoluteProjectsRoot, { withFileTypes: true });
392
+ }
393
+ catch (error) {
394
+ if (typeof error === 'object' &&
395
+ error !== null &&
396
+ 'code' in error &&
397
+ error.code === 'ENOENT') {
398
+ return [];
399
+ }
400
+ throw error;
401
+ }
402
+ const candidates = (await Promise.all(scopeEntries
403
+ .filter((entry) => entry.isDirectory())
404
+ .map(async (scopeEntry) => {
405
+ const directProjectPath = normalizeToPosixPath(join(normalizedProjectsRoot, scopeEntry.name));
406
+ if (await fileExists(join(repoRoot, directProjectPath, 'state.md'))) {
407
+ return [directProjectPath];
408
+ }
409
+ const scopePath = join(absoluteProjectsRoot, scopeEntry.name);
410
+ const projectEntries = await readdir(scopePath, {
411
+ withFileTypes: true,
412
+ });
413
+ return Promise.all(projectEntries
414
+ .filter((entry) => entry.isDirectory())
415
+ .map(async (projectEntry) => {
416
+ const projectPath = normalizeToPosixPath(join(normalizedProjectsRoot, scopeEntry.name, projectEntry.name));
417
+ return (await fileExists(join(repoRoot, projectPath, 'state.md')))
418
+ ? projectPath
419
+ : null;
420
+ }));
421
+ })))
422
+ .flat()
423
+ .filter((candidate) => candidate !== null)
424
+ .sort();
425
+ return candidates;
426
+ }
427
+ async function assertProjectPath(repoRoot, projectPath, source) {
428
+ const normalizedPath = normalizeRepoRelativeProjectPath(repoRoot, projectPath);
429
+ const absolutePath = join(repoRoot, normalizedPath);
430
+ if (!(await dirExists(absolutePath)) ||
431
+ !(await fileExists(join(absolutePath, 'state.md')))) {
432
+ throw new Error(`${source} project "${projectPath}" does not resolve to a project directory containing state.md.`);
433
+ }
434
+ return normalizedPath;
435
+ }
436
+ async function resolveExplicitReviewProject(repoRoot, projectsRoot, projectValue) {
437
+ const trimmed = projectValue.trim();
438
+ if (!trimmed) {
439
+ throw new Error('--project must be a non-empty project path or name.');
440
+ }
441
+ const looksLikePath = trimmed.includes('/') || trimmed.startsWith('.') || isAbsolute(trimmed);
442
+ if (looksLikePath) {
443
+ return assertProjectPath(repoRoot, trimmed, '--project');
444
+ }
445
+ const candidates = await listProjectCandidates(repoRoot, projectsRoot);
446
+ const matches = candidates.filter((candidate) => basename(candidate) === trimmed);
447
+ if (matches.length === 1) {
448
+ return matches[0];
449
+ }
450
+ if (matches.length > 1) {
451
+ throw new Error(`Multiple OAT projects match --project "${trimmed}": ${matches.join(', ')}. Pass a full project path instead.`);
452
+ }
453
+ return assertProjectPath(repoRoot, `${projectsRoot}/${trimmed}`, '--project');
454
+ }
455
+ async function resolveReviewProject(options) {
456
+ const projectsRoot = String(options.effective.resolved['projects.root']?.value ??
457
+ options.effective.shared.projects?.root ??
458
+ '.oat/projects/shared');
459
+ if (options.project !== undefined) {
460
+ return resolveExplicitReviewProject(options.repoRoot, projectsRoot, options.project);
461
+ }
462
+ const activeProject = options.effective.local.activeProject?.trim();
463
+ if (activeProject) {
464
+ return assertProjectPath(options.repoRoot, activeProject, 'Active');
465
+ }
466
+ const candidates = await listProjectCandidates(options.repoRoot, projectsRoot);
467
+ if (candidates.length === 0) {
468
+ throw new Error('No OAT project could be resolved for gate review. Set an active project or pass --project <path-or-name>.');
469
+ }
470
+ if (candidates.length > 1) {
471
+ throw new Error(`Multiple OAT projects could be resolved for gate review: ${candidates.join(', ')}. Pass --project <path-or-name>.`);
472
+ }
473
+ return candidates[0];
474
+ }
475
+ function reviewGateLifecycleRank(scope) {
476
+ const normalizedScope = scope.trim().toLowerCase();
477
+ if (normalizedScope === 'final') {
478
+ return Number.MAX_SAFE_INTEGER;
479
+ }
480
+ const phases = [...normalizedScope.matchAll(/p(\d+)/g)].map((match) => Number.parseInt(match[1] ?? '0', 10));
481
+ if (phases.length === 0) {
482
+ return 0;
483
+ }
484
+ const tasks = [...normalizedScope.matchAll(/(?:^|[-_])t(\d+)/g)].map((match) => Number.parseInt(match[1] ?? '0', 10));
485
+ const latestPhase = Math.max(...phases);
486
+ const latestTask = tasks.length > 0 ? Math.max(...tasks) : 9999;
487
+ return latestPhase * 10_000 + latestTask;
488
+ }
489
+ async function readReviewGateArtifactCandidate(repoRoot, relativePath) {
490
+ const content = await readFile(join(repoRoot, relativePath), 'utf8');
491
+ const frontmatter = getFrontmatterBlock(content);
492
+ if (!frontmatter) {
493
+ return null;
494
+ }
495
+ const generatedAt = getFrontmatterField(frontmatter, 'oat_generated_at');
496
+ if (!generatedAt) {
497
+ return null;
498
+ }
499
+ const generatedTime = Date.parse(generatedAt);
500
+ if (Number.isNaN(generatedTime)) {
501
+ return null;
502
+ }
503
+ const scope = getFrontmatterField(frontmatter, 'oat_review_scope') ?? '';
504
+ return {
505
+ path: relativePath,
506
+ scope,
507
+ generatedAt,
508
+ kind: 'project',
509
+ archived: false,
510
+ actionable: true,
511
+ generatedTime,
512
+ lifecycleRank: reviewGateLifecycleRank(scope),
513
+ signature: createHash('sha256').update(content).digest('hex'),
514
+ };
515
+ }
516
+ function sortReviewGateArtifacts(left, right) {
517
+ if (left.generatedTime !== right.generatedTime) {
518
+ return right.generatedTime - left.generatedTime;
519
+ }
520
+ if (left.lifecycleRank !== right.lifecycleRank) {
521
+ return right.lifecycleRank - left.lifecycleRank;
522
+ }
523
+ return left.path.localeCompare(right.path);
524
+ }
525
+ async function listActiveProjectReviewCandidates(options) {
526
+ const projectPath = normalizeRepoRelativeProjectPath(options.repoRoot, options.projectPath);
527
+ const reviewsDir = `${projectPath}/reviews`;
528
+ let entries;
529
+ try {
530
+ entries = await readdir(join(options.repoRoot, reviewsDir), {
531
+ withFileTypes: true,
532
+ });
533
+ }
534
+ catch (error) {
535
+ if (typeof error === 'object' &&
536
+ error !== null &&
537
+ 'code' in error &&
538
+ error.code === 'ENOENT') {
539
+ return [];
540
+ }
541
+ throw error;
542
+ }
543
+ return (await Promise.all(entries
544
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.md'))
545
+ .map((entry) => readReviewGateArtifactCandidate(options.repoRoot, normalizeToPosixPath(join(reviewsDir, entry.name))))))
546
+ .filter((candidate) => candidate !== null)
547
+ .sort(sortReviewGateArtifacts);
548
+ }
549
+ function findProducedReviewArtifact(before, after) {
550
+ const beforeSignatures = new Map(before.map((candidate) => [candidate.path, candidate.signature]));
551
+ return (after.find((candidate) => beforeSignatures.get(candidate.path) !== candidate.signature) ?? null);
552
+ }
553
+ function reviewBlocksAtThreshold(verdict, threshold) {
554
+ if (verdict.counts.critical > 0) {
555
+ return true;
556
+ }
557
+ if (threshold === 'critical') {
558
+ return false;
559
+ }
560
+ if (verdict.counts.important > 0) {
561
+ return true;
562
+ }
563
+ if (threshold === 'important') {
564
+ return false;
565
+ }
566
+ if (verdict.counts.medium > 0) {
567
+ return true;
568
+ }
569
+ if (threshold === 'medium') {
570
+ return false;
571
+ }
572
+ return verdict.counts.minor > 0;
573
+ }
574
+ function writeReviewGateResult(context, payload) {
575
+ if (context.json) {
576
+ context.logger.json(payload);
577
+ return;
578
+ }
579
+ context.logger.info(`Review artifact: ${payload.artifactPath}`);
580
+ context.logger.info(`Verdict: ${payload.status} (critical=${payload.counts.critical}, important=${payload.counts.important}, medium=${payload.counts.medium}, minor=${payload.counts.minor})`);
581
+ context.logger.info(payload.handoff);
582
+ }
324
583
  async function updateConfigLayer(context, layer, dependencies, mutate) {
325
584
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
326
585
  const userConfigDir = join(context.home, '.oat');
@@ -352,8 +611,21 @@ async function runGateSet(skillName, options, context, dependencies) {
352
611
  const layer = parseLayer(options.layer);
353
612
  const normalizedSkill = trimRequired(skillName, '<skill>');
354
613
  const gate = parseGateConfig(options);
614
+ const warnings = gate
615
+ ? detectDevBuildGateCommandWarnings(gate.command)
616
+ : [];
355
617
  await updateConfigLayer(context, layer, dependencies, (config) => setSkillGate(config, normalizedSkill, gate));
356
- writeSuccess(context, { layer, skill: normalizedSkill, gate });
618
+ if (!context.json) {
619
+ for (const warning of warnings) {
620
+ context.logger.warn(warning);
621
+ }
622
+ }
623
+ writeSuccess(context, {
624
+ layer,
625
+ skill: normalizedSkill,
626
+ gate,
627
+ ...(warnings.length > 0 ? { warnings } : {}),
628
+ });
357
629
  process.exitCode = 0;
358
630
  }
359
631
  catch (error) {
@@ -401,22 +673,71 @@ async function runCrossProviderExec(prompt, options, context, dependencies) {
401
673
  try {
402
674
  const effective = await readEffectiveConfig(context, dependencies);
403
675
  const targets = resolveExecTargets(effective);
404
- const explicitTarget = options.target?.trim();
405
- if (explicitTarget) {
406
- const target = targets[explicitTarget];
407
- if (!target) {
408
- throw new Error(`Unknown exec target "${explicitTarget}".`);
409
- }
410
- process.exitCode = await executeTarget({ id: explicitTarget, target: cloneExecTarget(target) }, prompt, context, dependencies);
676
+ const selected = await resolveSelectedExecTarget(targets, options, context, dependencies);
677
+ process.exitCode = await executeTarget(selected, prompt, context, dependencies);
678
+ }
679
+ catch (error) {
680
+ writeError(context, error);
681
+ }
682
+ }
683
+ async function runReviewGate(prompt, options, context, dependencies) {
684
+ try {
685
+ const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
686
+ const userConfigDir = join(context.home, '.oat');
687
+ const effective = await dependencies.resolveEffectiveConfig(repoRoot, userConfigDir, dependencies.processEnv);
688
+ const projectPath = await resolveReviewProject({
689
+ repoRoot,
690
+ effective,
691
+ project: options.project,
692
+ });
693
+ const targets = resolveExecTargets(effective);
694
+ const selected = await resolveSelectedExecTarget(targets, options, context, dependencies);
695
+ const threshold = parseReviewGateThreshold(options.exitNonzeroOn);
696
+ const before = await listActiveProjectReviewCandidates({
697
+ repoRoot,
698
+ projectPath,
699
+ });
700
+ const reviewPrompt = [
701
+ REVIEW_GATE_CONTEXT_NOTE,
702
+ reviewGateProjectContext(projectPath),
703
+ ...(options.reviewType?.trim()
704
+ ? [`Review type: ${options.reviewType.trim()}.`]
705
+ : []),
706
+ ...(options.reviewScope?.trim()
707
+ ? [`Review scope: ${options.reviewScope.trim()}.`]
708
+ : []),
709
+ ...prompt,
710
+ ];
711
+ const childExitCode = await executeTarget(selected, reviewPrompt, context, dependencies);
712
+ if (childExitCode !== 0) {
713
+ process.exitCode = childExitCode;
411
714
  return;
412
715
  }
413
- const avoid = parseCrossProviderAvoid(options.avoid);
414
- const currentRuntime = await resolveCurrentRuntime(options.currentRuntime, context, dependencies);
415
- const selected = await selectAvailableExecTarget(targets, currentRuntime, avoid, context, dependencies);
416
- if (!selected) {
417
- throw new Error(noEligibleTargetMessage(currentRuntime, avoid));
716
+ const after = await listActiveProjectReviewCandidates({
717
+ repoRoot,
718
+ projectPath,
719
+ });
720
+ const producedArtifact = findProducedReviewArtifact(before, after);
721
+ if (!producedArtifact) {
722
+ 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.`);
418
723
  }
419
- process.exitCode = await executeTarget(selected, prompt, context, dependencies);
724
+ const verdict = await parseReviewGateVerdict(join(repoRoot, producedArtifact.path));
725
+ const blocking = reviewBlocksAtThreshold(verdict, threshold);
726
+ const handoff = `Run oat-project-review-receive for ${producedArtifact.path} before treating this gate review as consumed.`;
727
+ writeReviewGateResult(context, {
728
+ status: blocking ? 'blocked' : 'ok',
729
+ target: selected.id,
730
+ project: projectPath,
731
+ artifactPath: producedArtifact.path,
732
+ threshold,
733
+ blocking,
734
+ counts: verdict.counts,
735
+ reviewType: verdict.reviewType,
736
+ scope: verdict.scope,
737
+ invocation: verdict.invocation,
738
+ handoff,
739
+ });
740
+ process.exitCode = blocking ? 1 : 0;
420
741
  }
421
742
  catch (error) {
422
743
  writeError(context, error);
@@ -470,6 +791,21 @@ export function createGateCommand(overrides = {}) {
470
791
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
471
792
  await runCrossProviderExec(prompt, options, context, dependencies);
472
793
  });
794
+ cmd
795
+ .command('review')
796
+ .description('Run a review gate and map review findings to exit status')
797
+ .option('--target <id>', 'Run this exact exec target')
798
+ .option('--avoid <mode>', 'Avoidance mode: same-runtime or none')
799
+ .option('--current-runtime <runtime>', 'Override detected runtime for testing or manual routing')
800
+ .option('--project <path-or-name>', 'Project path or name to review; defaults to the active project')
801
+ .option('--review-scope <scope>', 'Review scope hint for the provider')
802
+ .option('--review-type <type>', 'Review type hint for the provider')
803
+ .option('--exit-nonzero-on <severity>', 'Lowest severity that exits nonzero: critical, important, medium, or minor')
804
+ .argument('<prompt...>', 'Review prompt arguments appended to the target command')
805
+ .action(async (prompt, options, command) => {
806
+ const context = dependencies.buildCommandContext(readGlobalOptions(command));
807
+ await runReviewGate(prompt, options, context, dependencies);
808
+ });
473
809
  const target = new Command('target').description('Manage gate execution targets');
474
810
  target
475
811
  .command('set')
@@ -0,0 +1,15 @@
1
+ export interface ReviewGateVerdict {
2
+ artifactPath: string;
3
+ reviewType: 'code' | 'artifact' | 'unknown';
4
+ scope: string | null;
5
+ invocation: string | null;
6
+ counts: {
7
+ critical: number;
8
+ important: number;
9
+ medium: number;
10
+ minor: number;
11
+ };
12
+ blocking: boolean;
13
+ }
14
+ export declare function parseReviewGateVerdict(artifactPath: string): Promise<ReviewGateVerdict>;
15
+ //# sourceMappingURL=review-verdict.d.ts.map
@@ -0,0 +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"}