@open-agent-toolkit/cli 0.0.31 → 0.0.33

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 (31) hide show
  1. package/README.md +7 -0
  2. package/assets/docs/cli-utilities/config-and-local-state.md +12 -4
  3. package/assets/docs/provider-sync/commands.md +13 -6
  4. package/assets/docs/provider-sync/index.md +2 -0
  5. package/assets/docs/provider-sync/instruction-sync.md +146 -0
  6. package/assets/docs/provider-sync/scope-and-surface.md +2 -2
  7. package/assets/docs/reference/cli-reference.md +1 -0
  8. package/assets/docs/reference/troubleshooting.md +10 -5
  9. package/assets/public-package-versions.json +4 -4
  10. package/assets/skills/oat-project-complete/SKILL.md +8 -30
  11. package/dist/commands/instructions/instructions.types.d.ts +17 -4
  12. package/dist/commands/instructions/instructions.types.d.ts.map +1 -1
  13. package/dist/commands/instructions/instructions.types.js +5 -1
  14. package/dist/commands/instructions/instructions.utils.d.ts +4 -2
  15. package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
  16. package/dist/commands/instructions/instructions.utils.js +238 -25
  17. package/dist/commands/instructions/sync/sync.d.ts +3 -1
  18. package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
  19. package/dist/commands/instructions/sync/sync.js +176 -16
  20. package/dist/commands/instructions/validate/validate.d.ts +1 -1
  21. package/dist/commands/instructions/validate/validate.d.ts.map +1 -1
  22. package/dist/commands/instructions/validate/validate.js +16 -6
  23. package/dist/commands/project/complete-state/index.d.ts +16 -0
  24. package/dist/commands/project/complete-state/index.d.ts.map +1 -0
  25. package/dist/commands/project/complete-state/index.js +78 -0
  26. package/dist/commands/project/complete-state/state-utils.d.ts +7 -0
  27. package/dist/commands/project/complete-state/state-utils.d.ts.map +1 -0
  28. package/dist/commands/project/complete-state/state-utils.js +72 -0
  29. package/dist/commands/project/index.d.ts.map +1 -1
  30. package/dist/commands/project/index.js +2 -0
  31. package/package.json +2 -2
@@ -1,9 +1,10 @@
1
1
  import { buildCommandContext } from '../../../app/command-context.js';
2
- import { buildInstructionsPayload, formatInstructionsReport, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
2
+ import { INSTRUCTION_SYNC_STRATEGIES, } from '../../instructions/instructions.types.js';
3
+ import { buildInstructionsPayload, DEFAULT_INSTRUCTION_SYNC_STRATEGY, formatInstructionsReport, resolveInstructionSyncStrategy, scanInstructionFiles, } from '../../instructions/instructions.utils.js';
3
4
  import { readGlobalOptions } from '../../shared/shared.utils.js';
4
5
  import { CliError } from '../../../errors/cli-error.js';
5
6
  import { resolveProjectRoot } from '../../../fs/paths.js';
6
- import { Command } from 'commander';
7
+ import { Command, Option } from 'commander';
7
8
  function defaultDependencies() {
8
9
  return {
9
10
  buildCommandContext,
@@ -17,12 +18,18 @@ export function createInstructionsValidateCommand(overrides = {}) {
17
18
  ...overrides,
18
19
  };
19
20
  return new Command('validate')
20
- .description('Validate AGENTS.md to CLAUDE.md pointer integrity')
21
- .action(async (_options, command) => {
21
+ .description('Validate AGENTS.md/CLAUDE.md sync integrity for the selected strategy')
22
+ .addOption(new Option('--strategy <strategy>', 'Sync strategy')
23
+ .choices([...INSTRUCTION_SYNC_STRATEGIES])
24
+ .default(DEFAULT_INSTRUCTION_SYNC_STRATEGY))
25
+ .action(async (options, command) => {
22
26
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
27
+ const strategy = resolveInstructionSyncStrategy(options.strategy);
23
28
  try {
24
29
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
25
- const entries = await dependencies.scanInstructionFiles(repoRoot);
30
+ const entries = await dependencies.scanInstructionFiles(repoRoot, {
31
+ strategy,
32
+ });
26
33
  const payload = buildInstructionsPayload({
27
34
  mode: 'validate',
28
35
  entries,
@@ -34,7 +41,10 @@ export function createInstructionsValidateCommand(overrides = {}) {
34
41
  else {
35
42
  context.logger.info(formatInstructionsReport(payload, repoRoot));
36
43
  if (payload.status === 'drift') {
37
- context.logger.info('Fix with: oat instructions sync');
44
+ const fixCommand = strategy === DEFAULT_INSTRUCTION_SYNC_STRATEGY
45
+ ? 'Fix with: oat instructions sync'
46
+ : `Fix with: oat instructions sync --strategy ${strategy}`;
47
+ context.logger.info(fixCommand);
38
48
  }
39
49
  }
40
50
  process.exitCode = payload.status === 'ok' ? 0 : 1;
@@ -0,0 +1,16 @@
1
+ import { readFile as defaultReadFile, writeFile as defaultWriteFile } from 'node:fs/promises';
2
+ import { buildCommandContext, type CommandContext } from '../../../app/command-context.js';
3
+ import { dirExists, fileExists } from '../../../fs/io.js';
4
+ import { Command } from 'commander';
5
+ interface ProjectCompleteStateDependencies {
6
+ buildCommandContext: (options: Parameters<typeof buildCommandContext>[0]) => CommandContext;
7
+ resolveProjectRoot: (cwd: string) => Promise<string>;
8
+ readFile: typeof defaultReadFile;
9
+ writeFile: typeof defaultWriteFile;
10
+ dirExists: typeof dirExists;
11
+ fileExists: typeof fileExists;
12
+ now: () => Date;
13
+ }
14
+ export declare function createProjectCompleteStateCommand(overrides?: Partial<ProjectCompleteStateDependencies>): Command;
15
+ export {};
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/complete-state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,IAAI,eAAe,EAC3B,SAAS,IAAI,gBAAgB,EAC9B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,UAAU,gCAAgC;IACxC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,SAAS,EAAE,OAAO,gBAAgB,CAAC;IACnC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAsED,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,gCAAgC,CAAM,GACxD,OAAO,CA2BT"}
@@ -0,0 +1,78 @@
1
+ import { readFile as defaultReadFile, writeFile as defaultWriteFile, } from 'node:fs/promises';
2
+ import { isAbsolute, join } from 'node:path';
3
+ import { buildCommandContext } from '../../../app/command-context.js';
4
+ import { readGlobalOptions } from '../../shared/shared.utils.js';
5
+ import { CliError } from '../../../errors/cli-error.js';
6
+ import { dirExists, fileExists } from '../../../fs/io.js';
7
+ import { resolveProjectRoot } from '../../../fs/paths.js';
8
+ import { Command } from 'commander';
9
+ import { renderCompletedProjectState } from './state-utils.js';
10
+ const DEFAULT_DEPENDENCIES = {
11
+ buildCommandContext,
12
+ resolveProjectRoot,
13
+ readFile: defaultReadFile,
14
+ writeFile: defaultWriteFile,
15
+ dirExists,
16
+ fileExists,
17
+ now: () => new Date(),
18
+ };
19
+ function resolveTargetProjectPath(repoRoot, projectPath) {
20
+ return isAbsolute(projectPath) ? projectPath : join(repoRoot, projectPath);
21
+ }
22
+ async function runProjectCompleteState(projectPath, options, context, dependencies) {
23
+ try {
24
+ const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
25
+ const targetProjectPath = resolveTargetProjectPath(repoRoot, projectPath);
26
+ if (!(await dependencies.dirExists(targetProjectPath))) {
27
+ throw new CliError(`Project not found: ${projectPath}`, 1);
28
+ }
29
+ const statePath = join(targetProjectPath, 'state.md');
30
+ if (!(await dependencies.fileExists(statePath))) {
31
+ throw new CliError(`Project state.md not found: ${statePath}`, 1);
32
+ }
33
+ const now = dependencies.now();
34
+ const content = await dependencies.readFile(statePath, 'utf8');
35
+ const updatedContent = renderCompletedProjectState(content, {
36
+ archived: options.archived ?? false,
37
+ nowUtc: now.toISOString(),
38
+ today: now.toISOString().slice(0, 10),
39
+ });
40
+ await dependencies.writeFile(statePath, updatedContent, 'utf8');
41
+ if (context.json) {
42
+ context.logger.json({
43
+ status: 'ok',
44
+ projectPath,
45
+ statePath,
46
+ archived: options.archived ?? false,
47
+ });
48
+ }
49
+ else {
50
+ context.logger.info(`Updated completed project state: ${projectPath}`);
51
+ }
52
+ process.exitCode = 0;
53
+ }
54
+ catch (error) {
55
+ const message = error instanceof Error ? error.message : String(error);
56
+ if (context.json) {
57
+ context.logger.json({ status: 'error', message });
58
+ }
59
+ else {
60
+ context.logger.error(message);
61
+ }
62
+ process.exitCode = error instanceof CliError ? error.exitCode : 1;
63
+ }
64
+ }
65
+ export function createProjectCompleteStateCommand(overrides = {}) {
66
+ const dependencies = {
67
+ ...DEFAULT_DEPENDENCIES,
68
+ ...overrides,
69
+ };
70
+ return new Command('complete-state')
71
+ .description('Update a project state.md to the completed lifecycle shape')
72
+ .argument('<project-path>', 'Project path to update')
73
+ .option('--archived', 'Mark the completed project as archived locally')
74
+ .action(async (projectPath, options, command) => {
75
+ const context = dependencies.buildCommandContext(readGlobalOptions(command));
76
+ await runProjectCompleteState(projectPath, options, context, dependencies);
77
+ });
78
+ }
@@ -0,0 +1,7 @@
1
+ export interface CompleteProjectStateOptions {
2
+ archived: boolean;
3
+ nowUtc: string;
4
+ today: string;
5
+ }
6
+ export declare function renderCompletedProjectState(content: string, options: CompleteProjectStateOptions): string;
7
+ //# sourceMappingURL=state-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-utils.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/complete-state/state-utils.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAoED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,2BAA2B,GACnC,MAAM,CA8DR"}
@@ -0,0 +1,72 @@
1
+ import { getFrontmatterBlock, getFrontmatterField, } from '../../shared/frontmatter.js';
2
+ import { replaceFrontmatter, upsertFrontmatterField, } from '../../shared/frontmatter-write.js';
3
+ function replaceLine(content, pattern, nextLine) {
4
+ return pattern.test(content) ? content.replace(pattern, nextLine) : content;
5
+ }
6
+ function findSectionBounds(content, heading) {
7
+ const marker = `## ${heading}\n\n`;
8
+ const start = content.indexOf(marker);
9
+ if (start === -1) {
10
+ return null;
11
+ }
12
+ const bodyStart = start + marker.length;
13
+ const nextHeading = content.indexOf('\n## ', bodyStart);
14
+ return {
15
+ start,
16
+ bodyStart,
17
+ end: nextHeading === -1 ? content.length : nextHeading,
18
+ };
19
+ }
20
+ function readSectionBody(content, heading) {
21
+ const bounds = findSectionBounds(content, heading);
22
+ if (!bounds) {
23
+ return '';
24
+ }
25
+ return content.slice(bounds.bodyStart, bounds.end).trim();
26
+ }
27
+ function replaceSection(content, heading, body) {
28
+ const bounds = findSectionBounds(content, heading);
29
+ if (!bounds) {
30
+ return content;
31
+ }
32
+ return [
33
+ content.slice(0, bounds.start),
34
+ `## ${heading}\n\n${body.trim()}\n`,
35
+ content.slice(bounds.end),
36
+ ].join('');
37
+ }
38
+ function renderCompletedProgress(content) {
39
+ const existingLines = readSectionBody(content, 'Progress')
40
+ .split('\n')
41
+ .map((line) => line.trim())
42
+ .filter((line) => line.length > 0 && line.startsWith('- ✓'));
43
+ if (!existingLines.includes('- ✓ Project lifecycle complete')) {
44
+ existingLines.push('- ✓ Project lifecycle complete');
45
+ }
46
+ return existingLines.join('\n');
47
+ }
48
+ export function renderCompletedProjectState(content, options) {
49
+ const frontmatter = getFrontmatterBlock(content);
50
+ if (!frontmatter) {
51
+ throw new Error('state.md is missing frontmatter');
52
+ }
53
+ let nextBlock = upsertFrontmatterField(frontmatter, 'oat_lifecycle', 'complete', true).nextBlock;
54
+ nextBlock = upsertFrontmatterField(nextBlock, 'oat_project_completed', `"${options.nowUtc}"`, true).nextBlock;
55
+ nextBlock = upsertFrontmatterField(nextBlock, 'oat_project_state_updated', `"${options.nowUtc}"`, true).nextBlock;
56
+ let nextContent = nextBlock === frontmatter
57
+ ? content
58
+ : replaceFrontmatter(content, nextBlock);
59
+ nextContent = replaceLine(nextContent, /^\*\*Status:\*\*.*$/m, '**Status:** Complete');
60
+ nextContent = replaceLine(nextContent, /^\*\*Last Updated:\*\*.*$/m, `**Last Updated:** ${options.today}`);
61
+ const currentPhase = options.archived
62
+ ? 'Lifecycle complete; archived locally'
63
+ : 'Lifecycle complete';
64
+ nextContent = replaceSection(nextContent, 'Current Phase', currentPhase);
65
+ nextContent = replaceSection(nextContent, 'Progress', renderCompletedProgress(nextContent));
66
+ nextContent = replaceSection(nextContent, 'Next Milestone', 'None. Project complete.');
67
+ const currentLifecycle = getFrontmatterField(nextBlock, 'oat_lifecycle');
68
+ if (currentLifecycle !== 'complete') {
69
+ throw new Error('Failed to set oat_lifecycle: complete');
70
+ }
71
+ return nextContent;
72
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,oBAAoB,IAAI,OAAO,CAU9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,oBAAoB,IAAI,OAAO,CAW9C"}
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  import { createProjectArchiveCommand } from './archive/index.js';
3
+ import { createProjectCompleteStateCommand } from './complete-state/index.js';
3
4
  import { createProjectListCommand } from './list.js';
4
5
  import { createProjectNewCommand } from './new/index.js';
5
6
  import { createProjectOpenCommand } from './open/index.js';
@@ -10,6 +11,7 @@ export function createProjectCommand() {
10
11
  return new Command('project')
11
12
  .description('Manage OAT project workflows')
12
13
  .addCommand(createProjectArchiveCommand())
14
+ .addCommand(createProjectCompleteStateCommand())
13
15
  .addCommand(createProjectListCommand())
14
16
  .addCommand(createProjectNewCommand())
15
17
  .addCommand(createProjectOpenCommand())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
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",
@@ -33,7 +33,7 @@
33
33
  "ora": "^9.0.0",
34
34
  "yaml": "2.8.2",
35
35
  "zod": "^3.25.76",
36
- "@open-agent-toolkit/control-plane": "0.0.31"
36
+ "@open-agent-toolkit/control-plane": "0.0.33"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.10.0",