@open-agent-toolkit/cli 0.1.66 → 0.1.69

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 (37) hide show
  1. package/assets/agents/oat-reviewer.md +0 -1
  2. package/assets/docs/cli-utilities/workflow-gates.md +24 -5
  3. package/assets/docs/reference/cli-reference.md +1 -1
  4. package/assets/docs/workflows/projects/dispatch-ceiling.md +11 -3
  5. package/assets/docs/workflows/projects/pr-flow.md +12 -1
  6. package/assets/docs/workflows/projects/reviews.md +21 -1
  7. package/assets/public-package-versions.json +4 -4
  8. package/assets/skills/oat-project-autonomous/SKILL.md +1 -1
  9. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
  10. package/assets/skills/oat-project-complete/SKILL.md +20 -2
  11. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
  12. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  13. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +12 -1
  14. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +24 -9
  15. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
  16. package/assets/skills/oat-project-implement/references/phase-execution.md +5 -2
  17. package/assets/skills/oat-project-next/SKILL.md +21 -6
  18. package/assets/skills/oat-project-plan/SKILL.md +6 -1
  19. package/assets/skills/oat-project-plan-writing/SKILL.md +19 -2
  20. package/assets/skills/oat-project-pr-final/SKILL.md +20 -5
  21. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
  22. package/assets/skills/oat-project-pr-progress/SKILL.md +18 -3
  23. package/assets/skills/oat-project-progress/SKILL.md +4 -1
  24. package/assets/skills/oat-project-quick-start/SKILL.md +6 -1
  25. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
  26. package/assets/skills/oat-project-review-provide/SKILL.md +7 -2
  27. package/assets/skills/oat-project-review-receive/SKILL.md +46 -18
  28. package/assets/skills/oat-project-review-receive-remote/SKILL.md +41 -8
  29. package/dist/commands/cleanup/project/project.utils.d.ts.map +1 -1
  30. package/dist/commands/cleanup/project/project.utils.js +19 -1
  31. package/dist/commands/gate/index.d.ts +2 -0
  32. package/dist/commands/gate/index.d.ts.map +1 -1
  33. package/dist/commands/gate/index.js +29 -1
  34. package/dist/commands/review/latest.d.ts +1 -0
  35. package/dist/commands/review/latest.d.ts.map +1 -1
  36. package/dist/commands/review/latest.js +96 -22
  37. package/package.json +2 -2
@@ -77,9 +77,11 @@ async function readReviewCandidate(repoRoot, relativePath, kind, priority, archi
77
77
  return null;
78
78
  }
79
79
  const scope = getFrontmatterField(frontmatter, 'oat_review_scope') ?? '';
80
+ const reviewType = getFrontmatterField(frontmatter, 'oat_review_type') ?? 'code';
80
81
  return {
81
82
  path: relativePath,
82
83
  scope,
84
+ reviewType,
83
85
  generatedAt,
84
86
  kind,
85
87
  archived,
@@ -89,6 +91,62 @@ async function readReviewCandidate(repoRoot, relativePath, kind, priority, archi
89
91
  priority,
90
92
  };
91
93
  }
94
+ function parseReviewLedgerEvents(planContent) {
95
+ const heading = /^## Reviews[ \t]*\r?$/m.exec(planContent);
96
+ if (!heading) {
97
+ return [];
98
+ }
99
+ const remaining = planContent.slice(heading.index + heading[0].length);
100
+ const nextHeadingIndex = remaining.search(/^##(?!#)[ \t]+\S.*\r?$/m);
101
+ const section = nextHeadingIndex === -1 ? remaining : remaining.slice(0, nextHeadingIndex);
102
+ return section
103
+ .split('\n')
104
+ .filter((line) => line.trim().startsWith('|'))
105
+ .slice(2)
106
+ .map((line) => line
107
+ .split('|')
108
+ .slice(1, -1)
109
+ .map((cell) => cell.trim()))
110
+ .filter((cells) => cells.length === 5)
111
+ .map(([scope = '', type = '', status = '', , artifact = '']) => ({
112
+ scope,
113
+ type,
114
+ status,
115
+ artifact,
116
+ }));
117
+ }
118
+ async function correlateProjectActionability(repoRoot, projectPath, candidates) {
119
+ let planContent;
120
+ try {
121
+ planContent = await readFile(join(repoRoot, projectPath, 'plan.md'), 'utf8');
122
+ }
123
+ catch (error) {
124
+ if (typeof error === 'object' &&
125
+ error !== null &&
126
+ 'code' in error &&
127
+ error.code === 'ENOENT') {
128
+ return candidates;
129
+ }
130
+ throw error;
131
+ }
132
+ const events = parseReviewLedgerEvents(planContent);
133
+ if (events.length === 0) {
134
+ return candidates;
135
+ }
136
+ return candidates.map((candidate) => {
137
+ if (candidate.kind !== 'project' || candidate.archived) {
138
+ return candidate;
139
+ }
140
+ const artifact = normalizeToPosixPath(relative(projectPath, candidate.path));
141
+ const matchingEvent = events.find((event) => event.scope.toLowerCase() === candidate.scope.toLowerCase() &&
142
+ event.type.toLowerCase() === candidate.reviewType.toLowerCase() &&
143
+ normalizeToPosixPath(event.artifact) === artifact);
144
+ return {
145
+ ...candidate,
146
+ actionable: matchingEvent?.status.toLowerCase() === 'received',
147
+ };
148
+ });
149
+ }
92
150
  function sortReviewCandidates(a, b) {
93
151
  if (a.generatedTime !== b.generatedTime) {
94
152
  return b.generatedTime - a.generatedTime;
@@ -116,34 +174,45 @@ export async function findLatestReview(options) {
116
174
  priority: 0,
117
175
  archived: false,
118
176
  actionable: true,
177
+ });
178
+ if (!options.actionableProjectOnly) {
179
+ scanTargets.push({
180
+ dir: `${projectPath}/reviews/archived`,
181
+ kind: 'project',
182
+ priority: 1,
183
+ archived: true,
184
+ actionable: false,
185
+ });
186
+ }
187
+ }
188
+ if (!options.actionableProjectOnly) {
189
+ scanTargets.push({
190
+ dir: '.oat/repo/reviews',
191
+ kind: 'adhoc',
192
+ priority: 2,
193
+ archived: false,
194
+ actionable: true,
119
195
  }, {
120
- dir: `${projectPath}/reviews/archived`,
121
- kind: 'project',
122
- priority: 1,
123
- archived: true,
124
- actionable: false,
196
+ dir: '.oat/projects/local/orphan-reviews',
197
+ kind: 'adhoc',
198
+ priority: 3,
199
+ archived: false,
200
+ actionable: true,
125
201
  });
126
202
  }
127
- scanTargets.push({
128
- dir: '.oat/repo/reviews',
129
- kind: 'adhoc',
130
- priority: 2,
131
- archived: false,
132
- actionable: true,
133
- }, {
134
- dir: '.oat/projects/local/orphan-reviews',
135
- kind: 'adhoc',
136
- priority: 3,
137
- archived: false,
138
- actionable: true,
139
- });
140
- const candidates = (await Promise.all(scanTargets.map(async (target) => {
203
+ let candidates = (await Promise.all(scanTargets.map(async (target) => {
141
204
  const files = await listMarkdownFiles(options.repoRoot, target.dir);
142
205
  return Promise.all(files.map((file) => readReviewCandidate(options.repoRoot, file, target.kind, target.priority, target.archived, target.actionable)));
143
206
  })))
144
207
  .flat()
145
- .filter((candidate) => candidate !== null)
146
- .sort(sortReviewCandidates);
208
+ .filter((candidate) => candidate !== null);
209
+ if (projectPath) {
210
+ candidates = await correlateProjectActionability(options.repoRoot, projectPath, candidates);
211
+ }
212
+ if (options.actionableProjectOnly) {
213
+ candidates = candidates.filter((candidate) => candidate.actionable);
214
+ }
215
+ candidates.sort(sortReviewCandidates);
147
216
  const latest = candidates[0];
148
217
  if (!latest) {
149
218
  return null;
@@ -168,7 +237,11 @@ async function runReviewLatest(context, options, dependencies) {
168
237
  try {
169
238
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
170
239
  const projectPath = await resolveProjectPath(repoRoot, options.project, dependencies);
171
- const result = await findLatestReview({ repoRoot, projectPath });
240
+ const result = await findLatestReview({
241
+ repoRoot,
242
+ projectPath,
243
+ actionableProjectOnly: options.actionableProject,
244
+ });
172
245
  if (context.json) {
173
246
  context.logger.json(result ?? EMPTY_RESULT);
174
247
  }
@@ -196,6 +269,7 @@ export function createReviewLatestCommand(overrides = {}) {
196
269
  return new Command('latest')
197
270
  .description('Find the most recent OAT review artifact')
198
271
  .option('--project <path>', 'Project path to scan in addition to ad-hoc review locations')
272
+ .option('--actionable-project', 'Scan only active project reviews, excluding archived and ad-hoc history')
199
273
  .action(async (options, command) => {
200
274
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
201
275
  await runReviewLatest(context, options, dependencies);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.1.66",
3
+ "version": "0.1.69",
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.66"
37
+ "@open-agent-toolkit/control-plane": "0.1.69"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",