@aopslabs/aops 0.2.0

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 (171) hide show
  1. package/LICENSE +19 -0
  2. package/NOTICE +7 -0
  3. package/README.md +203 -0
  4. package/assets/agent-assets/core/SKILL.md +49 -0
  5. package/assets/agent-assets/core/references/agentspace/SKILL.md +78 -0
  6. package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +108 -0
  7. package/assets/agent-assets/core/references/chatv3/SKILL.md +48 -0
  8. package/assets/agent-assets/core/references/collaborative-work/SKILL.md +85 -0
  9. package/assets/agent-assets/core/references/discuss/SKILL.md +66 -0
  10. package/assets/agent-assets/core/references/docman/SKILL.md +69 -0
  11. package/assets/agent-assets/core/references/hosted-chat/SKILL.md +64 -0
  12. package/assets/agent-assets/core/references/mission/SKILL.md +54 -0
  13. package/assets/agent-assets/core/references/projectman/SKILL.md +86 -0
  14. package/assets/agent-assets/core/references/sys/SKILL.md +36 -0
  15. package/assets/agent-assets/core/references/view/SKILL.md +58 -0
  16. package/assets/agent-assets/core/references/working-disciplines/SKILL.md +69 -0
  17. package/assets/agent-assets/core/user-guides/agent-assets.md +81 -0
  18. package/assets/agent-assets/core/user-guides/agentspace.md +1098 -0
  19. package/assets/agent-assets/core/user-guides/aops-cli.md +1107 -0
  20. package/assets/agent-assets/core/user-guides/aops-system.md +63 -0
  21. package/assets/agent-assets/core/user-guides/chatv3.md +113 -0
  22. package/assets/agent-assets/core/user-guides/docman.md +162 -0
  23. package/assets/agent-assets/core/user-guides/projectman.md +212 -0
  24. package/assets/agent-assets/core/user-guides/sys.md +94 -0
  25. package/assets/agent-assets/core/user-guides/working-disciplines.md +588 -0
  26. package/assets/agent-assets/gateway/aops/SKILL.md +14 -0
  27. package/assets/r6-remote-session-baseline.json +19 -0
  28. package/assets/skills/aops-install/SKILL.md +231 -0
  29. package/assets/skills/aops-install/agents/openai.yaml +4 -0
  30. package/dist/commands/activity.js +352 -0
  31. package/dist/commands/agent-profile.js +653 -0
  32. package/dist/commands/agent.js +710 -0
  33. package/dist/commands/agents-md.js +125 -0
  34. package/dist/commands/api.js +84 -0
  35. package/dist/commands/archive.js +873 -0
  36. package/dist/commands/artifact.js +535 -0
  37. package/dist/commands/assets.js +1414 -0
  38. package/dist/commands/auth/device-login.js +1 -0
  39. package/dist/commands/auth/legacy-export.js +177 -0
  40. package/dist/commands/auth/login.js +426 -0
  41. package/dist/commands/chat.js +1363 -0
  42. package/dist/commands/chatv3.js +1684 -0
  43. package/dist/commands/checkpoint.js +549 -0
  44. package/dist/commands/commercial-artifact.js +475 -0
  45. package/dist/commands/commercial-license.js +594 -0
  46. package/dist/commands/community-auth.js +62 -0
  47. package/dist/commands/community-cockpit.js +185 -0
  48. package/dist/commands/community-console.js +109 -0
  49. package/dist/commands/community-doctor.js +335 -0
  50. package/dist/commands/community-server.js +2062 -0
  51. package/dist/commands/community-setup.js +284 -0
  52. package/dist/commands/discuss.js +1448 -0
  53. package/dist/commands/doc.js +5219 -0
  54. package/dist/commands/experience.js +922 -0
  55. package/dist/commands/host.js +1127 -0
  56. package/dist/commands/init.js +118 -0
  57. package/dist/commands/memory.js +3129 -0
  58. package/dist/commands/mission.js +562 -0
  59. package/dist/commands/official-catalog.js +134 -0
  60. package/dist/commands/plan.js +84 -0
  61. package/dist/commands/playbook.js +415 -0
  62. package/dist/commands/pm/context.js +6 -0
  63. package/dist/commands/pm/index.js +701 -0
  64. package/dist/commands/pm/projectman.js +6266 -0
  65. package/dist/commands/project.js +1080 -0
  66. package/dist/commands/prompt.js +1024 -0
  67. package/dist/commands/repo-sync.js +1907 -0
  68. package/dist/commands/resource.js +527 -0
  69. package/dist/commands/skill.js +1211 -0
  70. package/dist/commands/start-disciplines.js +510 -0
  71. package/dist/commands/start.js +1343 -0
  72. package/dist/commands/target.js +309 -0
  73. package/dist/commands/version.js +42 -0
  74. package/dist/commands/view.js +1852 -0
  75. package/dist/launchers/cockpit.js +28 -0
  76. package/dist/launchers/options.js +74 -0
  77. package/dist/launchers/server.js +41 -0
  78. package/dist/lib/agent-assets/envelope.js +83 -0
  79. package/dist/lib/agent-assets/gateway.js +15 -0
  80. package/dist/lib/agent-assets/guards.js +23 -0
  81. package/dist/lib/agent-assets/hosted-discovery.js +148 -0
  82. package/dist/lib/agent-assets/hosted-package-input.js +154 -0
  83. package/dist/lib/agent-assets/legacy-pointer-migration.js +677 -0
  84. package/dist/lib/agent-assets/native-fs.js +589 -0
  85. package/dist/lib/agent-assets/package-manifest.js +324 -0
  86. package/dist/lib/agent-assets/portable-path.js +67 -0
  87. package/dist/lib/agent-assets/release-input.js +177 -0
  88. package/dist/lib/agent-assets/roots.js +45 -0
  89. package/dist/lib/agent-assets/runtime-binding-reader.js +545 -0
  90. package/dist/lib/agent-assets/runtime-targets.js +50 -0
  91. package/dist/lib/agent-assets/store-reader.js +1212 -0
  92. package/dist/lib/agent-assets/store-types.js +1 -0
  93. package/dist/lib/agent-assets/store-writer.js +1484 -0
  94. package/dist/lib/agent-assets/types.js +1 -0
  95. package/dist/lib/agent-assets/unicode-case-folding-v15-1.generated.js +1548 -0
  96. package/dist/lib/commercial-final-readiness.js +504 -0
  97. package/dist/lib/commercial-lifecycle-smoke-isolation.js +236 -0
  98. package/dist/lib/commercial-managed-postgres-docker-adapter.js +274 -0
  99. package/dist/lib/commercial-setup-readiness-adapter.js +179 -0
  100. package/dist/lib/community-client-contract.js +164 -0
  101. package/dist/lib/community-cockpit-lifecycle.js +601 -0
  102. package/dist/lib/community-command-abort.js +59 -0
  103. package/dist/lib/community-diagnostic.js +237 -0
  104. package/dist/lib/community-docker-adapter.js +498 -0
  105. package/dist/lib/community-home.js +31 -0
  106. package/dist/lib/community-instance-contract.js +148 -0
  107. package/dist/lib/community-instance-layout.js +97 -0
  108. package/dist/lib/community-lifecycle.js +1631 -0
  109. package/dist/lib/community-migration-snapshot.js +770 -0
  110. package/dist/lib/community-native-application-recovery.js +425 -0
  111. package/dist/lib/community-native-child.js +240 -0
  112. package/dist/lib/community-native-database-recovery.js +456 -0
  113. package/dist/lib/community-native-lifecycle.js +2458 -0
  114. package/dist/lib/community-native-migration.js +339 -0
  115. package/dist/lib/community-native-postgres.js +596 -0
  116. package/dist/lib/community-operation-journal.js +773 -0
  117. package/dist/lib/community-operation-lock.js +596 -0
  118. package/dist/lib/community-release-resolver.js +291 -0
  119. package/dist/lib/community-release-verifier.js +475 -0
  120. package/dist/lib/community-repo-discovery.js +252 -0
  121. package/dist/lib/community-setup-server-env.js +203 -0
  122. package/dist/lib/external-url.js +110 -0
  123. package/dist/lib/official-catalog-gateway.js +108 -0
  124. package/dist/lib/official-catalog.js +364 -0
  125. package/dist/lib/server-bootstrap.js +240 -0
  126. package/dist/lib/setup-agent-assets-bridge.js +176 -0
  127. package/dist/lib/setup-agent-assets-release.js +52 -0
  128. package/dist/lib/setup-external-postgres.js +108 -0
  129. package/dist/lib/setup-init-orchestrator.js +990 -0
  130. package/dist/lib/setup-install-guide.js +52 -0
  131. package/dist/lib/setup-installer-release.js +47 -0
  132. package/dist/lib/setup-local-postgres.js +329 -0
  133. package/dist/lib/setup-official-catalog-bridge.js +148 -0
  134. package/dist/lib/setup-readiness.js +888 -0
  135. package/dist/lib/tui-launcher.js +59 -0
  136. package/dist/main.js +150 -0
  137. package/dist/seeds/agents-md.js +54 -0
  138. package/dist/utils/agent-gateway.js +275 -0
  139. package/dist/utils/agents-md.js +281 -0
  140. package/dist/utils/api.js +255 -0
  141. package/dist/utils/chatv3-session-store.js +185 -0
  142. package/dist/utils/command.js +67 -0
  143. package/dist/utils/community-host-runtime.js +376 -0
  144. package/dist/utils/config.js +1015 -0
  145. package/dist/utils/discussion-workspace.js +552 -0
  146. package/dist/utils/experience-workspace.js +326 -0
  147. package/dist/utils/guide-paths.js +67 -0
  148. package/dist/utils/hosted-sugar.js +56 -0
  149. package/dist/utils/hosted-workspace.js +229 -0
  150. package/dist/utils/memory-workspace.js +537 -0
  151. package/dist/utils/operator-runtime.js +199 -0
  152. package/dist/utils/password-crypto.js +39 -0
  153. package/dist/utils/playbook-workspace.js +479 -0
  154. package/dist/utils/project-context.js +255 -0
  155. package/dist/utils/prompts.js +70 -0
  156. package/dist/utils/refresh-race.js +28 -0
  157. package/dist/utils/repo-config.js +109 -0
  158. package/dist/utils/repo-first-projectman.js +194 -0
  159. package/dist/utils/repo-first-storage.js +13 -0
  160. package/dist/utils/repo-first-view.js +305 -0
  161. package/dist/utils/session-guidance.js +278 -0
  162. package/dist/utils/session-state.js +137 -0
  163. package/dist/utils/table.js +39 -0
  164. package/dist/utils/transient-fs.js +49 -0
  165. package/dist/utils/workspace-root.js +1 -0
  166. package/launchers/aops-cockpit.ps1 +15 -0
  167. package/launchers/aops-cockpit.sh +16 -0
  168. package/launchers/aops-server.ps1 +15 -0
  169. package/launchers/aops-server.sh +16 -0
  170. package/native/tui/win32-x64/aops-tui.exe +0 -0
  171. package/package.json +81 -0
@@ -0,0 +1,701 @@
1
+ import { Command } from 'commander';
2
+ import { applyCommonOptions } from '../../utils/command.js';
3
+ import { buildOperatorCookbook } from '../../utils/hosted-sugar.js';
4
+ import { GUIDE_PATHS } from '../../utils/guide-paths.js';
5
+ import { collectRepeatedOption, runPmBoardArchive, runPmBoardCreate, runPmBoardCloseout, runPmBoardDelete, runPmBoardBootstrapGet, runPmBoardBootstrapSet, runPmBoardGet, runPmBoardKickoff, runPmBoardList, runPmBoardResume, runPmBoardUnarchive, runPmFeedbackCreate, runPmFeedbackDelete, runPmFeedbackGet, runPmFeedbackList, runPmFeedbackUpdate, runPmResumeBrief, runPmReviewRequestCreate, runPmReviewRequestDelete, runPmReviewRequestGet, runPmReviewRequestList, runPmReviewRequestResult, runPmReviewRequestUpdate, runPmUtaskCreate, runPmUtaskDelete, runPmUtaskSetStatus, runPmUtaskUpdate, runPmIssueCreate, runPmIssueDelete, runPmIssueGet, runPmIssueList, runPmIssueUpdate, runPmSprintCreate, runPmSprintDelete, runPmSprintGet, runPmSprintArchive, runPmSprintList, runPmSprintSetStatus, runPmSprintUnarchive, runPmSprintUpdatePlan, runPmStatusAudit, runPmStatusReconcile, runPmTaskCreate, runPmTaskDelete, runPmTaskGet, runPmTaskList, runPmTaskSetStatus, runPmHandoffResume, runPmHandoffWrite, } from './projectman.js';
6
+ function applyPmContextOptions(cmd) {
7
+ applyCommonOptions(cmd, { withProject: false });
8
+ cmd.option('--scope-id <id>', 'Canonical owner scope override');
9
+ cmd.option('--project-id <id>', 'Project id used to resolve the canonical owner scope');
10
+ cmd.option('--project-name <name>', 'Project name override for repo-aware scope resolution');
11
+ cmd.option('--project-slug <slug>', 'Project slug from repo project registry; hosted-only links write through the hosted gateway');
12
+ cmd.option('--tenant-id <id>', 'Tenant id header (x-tenant-id)');
13
+ cmd.option('--locale <locale>', 'Locale header (x-locale)');
14
+ cmd.option('--fallback-locale <locale>', 'Fallback locale header (x-fallback-locale)');
15
+ cmd.addHelpText('after', `\nGuide:\n ${GUIDE_PATHS.projectman}\n\nBroader Projectman overview:\n aops-cli pm --help\n`);
16
+ return cmd;
17
+ }
18
+ function applyWriteOptions(cmd, params = {}) {
19
+ cmd.option('--preview', 'Return a validated preflight summary without executing the tool');
20
+ cmd.option('--apply', 'Explicitly allow guarded write operations');
21
+ if (params.destructive) {
22
+ cmd.option('--confirm', 'Explicitly confirm destructive operations');
23
+ }
24
+ cmd.option('--idempotency-key <key>', 'Optional guarded-write idempotency key');
25
+ return cmd;
26
+ }
27
+ function applyMemoryCadenceOptions(cmd) {
28
+ cmd.option('--write-memory', 'Write an opt-in local memory side-effect after the main Projectman operation succeeds');
29
+ cmd.option('--memory-mode <mode>', 'Memory mode override: kickoff, resume, decision, blocker, closeout, rule');
30
+ cmd.option('--memory-content <text>', 'Optional explicit memory content override');
31
+ cmd.option('--memory-next-action <text>', 'Optional next action for the memory side-effect');
32
+ cmd.option('--memory-validation-state <text>', 'Optional validation state for the memory side-effect');
33
+ return cmd;
34
+ }
35
+ function addTaskCommands(cmd) {
36
+ const task = cmd.command('ktask').alias('task').description('Projectman kanban task commands');
37
+ applyPmContextOptions(applyMemoryCadenceOptions(applyWriteOptions(task
38
+ .command('create')
39
+ .description('Create a Projectman kanban task')
40
+ .requiredOption('--title <title>', 'Task title')
41
+ .requiredOption('--board <value>', 'Board id, exact board name, or board slug')
42
+ .requiredOption('--column <value>', 'Board-column placement id, exact column name, or column slug on the selected board')
43
+ .option('--description <text>', 'Task description')
44
+ .option('--position <index>', 'Optional position override', (value) => Number.parseInt(String(value), 10)), { destructive: false })).action(async (options) => {
45
+ await runPmTaskCreate(options);
46
+ }));
47
+ applyPmContextOptions(task
48
+ .command('list')
49
+ .description('List Projectman kanban tasks')
50
+ .option('--board <value>', 'Board id, exact board name, or board slug')
51
+ .option('--column <value>', 'Board-column placement id, exact column name, or column slug on the selected board')
52
+ .option('--sprint <id>', 'Optional sprint id filter')
53
+ .action(async (options) => {
54
+ await runPmTaskList(options);
55
+ }));
56
+ applyPmContextOptions(task
57
+ .command('get')
58
+ .description('Get a Projectman kanban task by selector')
59
+ .requiredOption('--id <id>', 'Task selector: full id, 8+ id prefix, slug, or exact title')
60
+ .action(async (options) => {
61
+ await runPmTaskGet(options);
62
+ }));
63
+ applyPmContextOptions(applyWriteOptions(task
64
+ .command('set-status')
65
+ .description('Move a kanban task to the workflow column matching the requested status')
66
+ .requiredOption('--id <id>', 'Task id')
67
+ .requiredOption('--status <value>', 'Target workflow status or exact board column slug/name')
68
+ .option('--position <index>', 'Optional target position inside the destination column', (value) => Number.parseInt(String(value), 10)), { destructive: false }).addHelpText('after', '\nNotes:\n' +
69
+ ' Default workflow aliases: backlog, todo, doing, done.\n' +
70
+ ' `completed` maps to `done`; `in_progress` maps to `doing`.\n' +
71
+ ' Custom boards can also accept an exact board column name or slug.\n').action(async (options) => {
72
+ await runPmTaskSetStatus(options);
73
+ }));
74
+ applyPmContextOptions(applyWriteOptions(task
75
+ .command('delete')
76
+ .description('Delete a Projectman kanban task')
77
+ .requiredOption('--id <id>', 'Task id'), { destructive: true }).action(async (options) => {
78
+ await runPmTaskDelete(options);
79
+ }));
80
+ }
81
+ function addStatusCommands(cmd) {
82
+ const status = cmd.command('status').description('Read-only Projectman status audit commands');
83
+ applyPmContextOptions(status
84
+ .command('audit')
85
+ .description('Read-only audit for kanban task and sprint completion drift')
86
+ .option('--board <value>', 'Optional board id, exact board name, or board slug filter')
87
+ .option('--task <value>', 'Optional task selector: full id, 8+ id prefix, slug, or exact title')
88
+ .option('--sprint <value>', 'Optional sprint selector: full id, 8+ id prefix, slug, or exact name')
89
+ .action(async (options) => {
90
+ await runPmStatusAudit(options);
91
+ }));
92
+ applyPmContextOptions(applyWriteOptions(status
93
+ .command('reconcile')
94
+ .description('Preview or explicitly apply one guarded PM status reconciliation')
95
+ .requiredOption('--task <value>', 'Task selector: full id, 8+ id prefix, slug, or exact title')
96
+ .option('--board <value>', 'Optional board id, exact board name, or board slug used to scope task selection'), { destructive: false }).addHelpText('after', '\nNotes:\n' +
97
+ ' Default is preview/dry-run; no mutation occurs unless --apply is provided.\n' +
98
+ ' Reconcile is item-scoped: --task is required and board-wide/bulk mutation is not supported.\n' +
99
+ ' Safe task->Done applies only when every linked sprint is completed and has no open microtasks.\n').action(async (options) => {
100
+ await runPmStatusReconcile(options);
101
+ }));
102
+ }
103
+ function addBoardCommands(cmd) {
104
+ const board = cmd.command('board').description('Projectman kanban board commands');
105
+ const bootstrap = board.command('bootstrap').description('Board-slug bootstrap registry commands');
106
+ applyPmContextOptions(board
107
+ .command('list')
108
+ .description('List Projectman boards')
109
+ .option('--name <name>', 'Optional exact board name filter')
110
+ .option('--slug <slug>', 'Optional exact board slug filter')
111
+ .option('--include-archived', 'Include boards with archivedAt set')
112
+ .action(async (options) => {
113
+ await runPmBoardList(options);
114
+ }));
115
+ applyPmContextOptions(board
116
+ .command('get')
117
+ .description('Get a Projectman board by id, exact name, or slug')
118
+ .option('--id <id>', 'Board id')
119
+ .option('--name <name>', 'Exact board name')
120
+ .option('--slug <slug>', 'Exact board slug')
121
+ .action(async (options) => {
122
+ await runPmBoardGet(options);
123
+ }));
124
+ applyPmContextOptions(applyWriteOptions(board
125
+ .command('archive')
126
+ .description('Soft-archive a Projectman board by setting archivedAt on the board record')
127
+ .option('--id <id>', 'Board id or 8+ id prefix')
128
+ .option('--name <name>', 'Exact board name')
129
+ .option('--slug <slug>', 'Exact board slug'), { destructive: false }).addHelpText('after', '\nNotes:\n' +
130
+ ' This is a reversible metadata mark: linked tasks/sprints are not changed.\n' +
131
+ ' The board file stays in place; this command does not write under .aops/archive/**.\n').action(async (options) => {
132
+ await runPmBoardArchive(options);
133
+ }));
134
+ applyPmContextOptions(applyWriteOptions(board
135
+ .command('unarchive')
136
+ .description('Restore a soft-archived Projectman board by clearing archivedAt')
137
+ .option('--id <id>', 'Board id or 8+ id prefix')
138
+ .option('--name <name>', 'Exact board name')
139
+ .option('--slug <slug>', 'Exact board slug'), { destructive: false }).addHelpText('after', '\nNotes:\n' +
140
+ ' This only clears the board archivedAt marker; linked tasks/sprints are not changed.\n' +
141
+ ' The board file stays in place; this command does not write under .aops/archive/**.\n').action(async (options) => {
142
+ await runPmBoardUnarchive(options);
143
+ }));
144
+ applyPmContextOptions(applyWriteOptions(bootstrap
145
+ .command('set')
146
+ .description('Create or update the board bootstrap registry')
147
+ .requiredOption('--board <value>', 'Board id, exact board name, or board slug')
148
+ .option('--title <text>', 'Optional bootstrap title/label')
149
+ .option('--doc-id <id>', 'Canonical Docman document id')
150
+ .option('--doc-version-id <id>', 'Canonical Docman document version id')
151
+ .option('--prompt-id <id>', 'Canonical prompt id')
152
+ .option('--prompt-version-id <id>', 'Canonical prompt version id')
153
+ .option('--task-id <id>', 'Active umbrella kanban task id')
154
+ .option('--sprint-id <id>', 'Active umbrella sprint id')
155
+ .option('--reference <value>', 'Repeatable reference pointer stored in the bootstrap registry', collectRepeatedOption, [])
156
+ .option('--notes <text>', 'Optional operator notes for this board bootstrap'), { destructive: false }).action(async (options) => {
157
+ await runPmBoardBootstrapSet(options);
158
+ }));
159
+ applyPmContextOptions(bootstrap
160
+ .command('get')
161
+ .description('Read the canonical board bootstrap registry for a board slug/id/name')
162
+ .requiredOption('--board <value>', 'Board id, exact board name, or board slug')
163
+ .action(async (options) => {
164
+ await runPmBoardBootstrapGet(options);
165
+ }));
166
+ applyPmContextOptions(board
167
+ .command('resume')
168
+ .description('Resolve board bootstrap, active window, and resume context for a board slug/id/name')
169
+ .requiredOption('--board <value>', 'Board id, exact board name, or board slug')
170
+ .option('--depth <mode>', 'Resume depth: light or deep', 'light')
171
+ .option('--limit <count>', 'Result limit', (value) => Number.parseInt(String(value), 10))
172
+ .option('--candidate-limit <count>', 'Candidate fetch limit', (value) => Number.parseInt(String(value), 10))
173
+ .action(async (options) => {
174
+ await runPmBoardResume(options);
175
+ }));
176
+ applyPmContextOptions(applyWriteOptions(board
177
+ .command('kickoff')
178
+ .description('Create or reuse the active task+sprint window for a board and refresh its bootstrap registry')
179
+ .requiredOption('--board <value>', 'Board id, exact board name, or board slug')
180
+ .requiredOption('--title <title>', 'Kanban task title')
181
+ .requiredOption('--goal <text>', 'Sprint goal')
182
+ .option('--column <value>', 'Target board column when a new task is created', 'Todo')
183
+ .option('--description <text>', 'Optional kanban task description')
184
+ .option('--sprint-name <text>', 'Optional sprint name override; defaults to the task title')
185
+ .option('--reference <value>', 'Repeatable sprint reference', collectRepeatedOption, [])
186
+ .option('--scope-item <value>', 'Repeatable sprint scope item', collectRepeatedOption, [])
187
+ .option('--validation-item <value>', 'Repeatable sprint validation item', collectRepeatedOption, [])
188
+ .option('--notes <text>', 'Optional sprint notes')
189
+ .option('--memory-content <text>', 'Optional explicit kickoff/resume memory content override')
190
+ .option('--memory-next-action <text>', 'Optional next action for the memory side-effect')
191
+ .option('--memory-validation-state <text>', 'Optional validation state for the memory side-effect'), { destructive: false }).action(async (options) => {
192
+ await runPmBoardKickoff(options);
193
+ }));
194
+ applyPmContextOptions(applyWriteOptions(board
195
+ .command('create')
196
+ .description('Create a Projectman board bootstrap')
197
+ .requiredOption('--name <name>', 'Board name')
198
+ .option('--slug <slug>', 'Optional board slug override; defaults to a shortened slug from the board name')
199
+ .option('--description <text>', 'Board description')
200
+ .option('--column <name>', 'Repeatable board column name; when present it replaces the default bootstrap columns', collectRepeatedOption, [])
201
+ .option('--append-column <name>', 'Repeatable extra column name added after the default Backlog, Todo, Doing, Done flow', collectRepeatedOption, []), { destructive: false }).addHelpText('after', '\nNotes:\n' +
202
+ ' When neither --column nor --append-column is supplied, the board flow bootstraps Backlog, Todo, Doing, Done.\n' +
203
+ ' --column replaces the default bootstrap columns; --append-column adds to them.\n' +
204
+ ' When --slug is omitted, the CLI derives a lowercase hyphenated slug from the board name and shortens it when needed.\n' +
205
+ ' Board and column local flows generate board-owned column slugs like ui-gelistirme-todo.\n').action(async (options) => {
206
+ await runPmBoardCreate(options);
207
+ }));
208
+ applyPmContextOptions(applyWriteOptions(board
209
+ .command('closeout')
210
+ .description('Operator-approved only: atomically close the active board window, write closeout memory, move task to Done, and clear bootstrap active refs')
211
+ .requiredOption('--board <value>', 'Board id, exact board name, or board slug')
212
+ .option('--task <id>', 'Explicit active task id for manual closeout when no kickoff registry exists')
213
+ .option('--sprint <id>', 'Explicit active sprint id for manual closeout memory linkage when no kickoff registry exists')
214
+ .option('--content <text>', 'Closeout memory content', 'Board closeout completed.')
215
+ .option('--next-action <text>', 'Optional next action for the closeout memory')
216
+ .option('--validation-state <text>', 'Optional validation state for the closeout memory')
217
+ .option('--skip-memory', 'Skip writing the closeout memory item'), { destructive: false }).action(async (options) => {
218
+ await runPmBoardCloseout(options);
219
+ }).addHelpText('after', '\nNotes:\n' +
220
+ ' Operator-approved final closeout only; for ordinary stop points use `pm handoff write` or `mem write --mode resume`.\n' +
221
+ ' If the board was not opened with `pm board kickoff`, closeout runs in manual fallback mode; pass --task/--sprint to bind explicit active refs.\n'));
222
+ applyPmContextOptions(applyWriteOptions(board
223
+ .command('delete')
224
+ .description('Delete a Projectman board')
225
+ .requiredOption('--id <id>', 'Board id'), { destructive: true }).action(async (options) => {
226
+ await runPmBoardDelete(options);
227
+ }));
228
+ board.addHelpText('after', '\nBoard quick paths:\n' +
229
+ ' `pm board bootstrap --help` shows the board bootstrap subcommands.\n' +
230
+ ' `pm board bootstrap get --board ui --json` reads the canonical board bootstrap registry.\n' +
231
+ ' `pm board resume --board ui --json` resolves the active board window and returns scoped resume context.\n' +
232
+ ' `pm board kickoff --board ui --title "UI slice" --goal "Ship the next UI window" --apply --json` reuses or opens the active tracked window.\n' +
233
+ ' `pm board closeout --board ui --content "Completed all tasks" --apply --json` operator-approved only; atomically closes the active board window.\n' +
234
+ '\nBoard bootstrap notes:\n' +
235
+ ' `pm board bootstrap set` writes the board bootstrap registry.\n' +
236
+ ' `pm board resume` reads that registry, resolves the active task/sprint window, and returns a single resume packet.\n' +
237
+ ' `pm board kickoff` reuses an open active window when available; otherwise it creates a new task+sprint pair and refreshes the registry.\n' +
238
+ ' `pm board closeout` writes closeout memory, moves the active task to Done, and clears the bootstrap active refs in a single command; run it only after explicit operator approval.\n');
239
+ }
240
+ function addUtaskCommands(cmd) {
241
+ const utask = cmd.command('utask').description('Projectman sprint-bound microtask commands');
242
+ applyPmContextOptions(applyMemoryCadenceOptions(applyWriteOptions(utask
243
+ .command('create')
244
+ .description('Create a sprint-bound utask')
245
+ .requiredOption('--sprint <id>', 'Sprint id')
246
+ .option('--phase <value>', 'Phase id or exact phase name', 'Main')
247
+ .requiredOption('--title <title>', 'Utask title')
248
+ .option('--status <value>', 'Initial utask status', 'todo')
249
+ .option('--notes <text>', 'Optional utask notes')
250
+ .option('--position <index>', 'Optional position override', (value) => Number.parseInt(String(value), 10)), { destructive: false })).action(async (options) => {
251
+ await runPmUtaskCreate(options);
252
+ }));
253
+ applyPmContextOptions(applyMemoryCadenceOptions(applyWriteOptions(utask
254
+ .command('update')
255
+ .description('Patch a sprint-bound utask without replacing the full sprint plan')
256
+ .requiredOption('--sprint <id>', 'Sprint id')
257
+ .requiredOption('--id <id>', 'Utask id')
258
+ .option('--title <title>', 'Updated utask title')
259
+ .option('--status <value>', 'Updated utask status')
260
+ .option('--notes <text>', 'Updated utask notes')
261
+ .option('--position <index>', 'Optional position override', (value) => Number.parseInt(String(value), 10)), { destructive: false })).action(async (options) => {
262
+ await runPmUtaskUpdate(options);
263
+ }));
264
+ applyPmContextOptions(applyWriteOptions(utask
265
+ .command('set-status')
266
+ .description('Update only the lifecycle status of a sprint-bound utask')
267
+ .requiredOption('--sprint <id>', 'Sprint id')
268
+ .requiredOption('--id <id>', 'Utask id')
269
+ .requiredOption('--status <value>', 'Updated utask status'), { destructive: false }).action(async (options) => {
270
+ await runPmUtaskSetStatus(options);
271
+ }));
272
+ applyPmContextOptions(applyWriteOptions(utask
273
+ .command('delete')
274
+ .description('Delete a sprint-bound utask')
275
+ .requiredOption('--sprint <id>', 'Sprint id')
276
+ .requiredOption('--id <id>', 'Utask id'), { destructive: true }).action(async (options) => {
277
+ await runPmUtaskDelete(options);
278
+ }));
279
+ }
280
+ function addSprintCommands(cmd) {
281
+ const sprint = cmd.command('sprint').description('Projectman sprint commands');
282
+ applyPmContextOptions(applyMemoryCadenceOptions(applyWriteOptions(sprint
283
+ .command('create')
284
+ .description('Create a Projectman sprint execution document')
285
+ .requiredOption('--task <id>', 'Kanban task id')
286
+ .requiredOption('--name <name>', 'Sprint name')
287
+ .requiredOption('--goal <text>', 'Sprint goal')
288
+ .option('--reference <value>', 'Repeatable reference item', collectRepeatedOption, [])
289
+ .option('--scope-item <value>', 'Repeatable scope item', collectRepeatedOption, [])
290
+ .option('--validation-item <value>', 'Repeatable validation item', collectRepeatedOption, [])
291
+ .option('--notes <text>', 'Optional notes'), { destructive: false })).action(async (options) => {
292
+ await runPmSprintCreate(options);
293
+ }));
294
+ applyPmContextOptions(applyMemoryCadenceOptions(applyWriteOptions(sprint
295
+ .command('update-plan')
296
+ .description('Patch a sprint plan, including phases and microtasks')
297
+ .requiredOption('--id <id>', 'Sprint id')
298
+ .option('--name <name>', 'Updated sprint name')
299
+ .option('--goal <text>', 'Updated sprint goal')
300
+ .option('--reference <value>', 'Repeatable reference item patch', collectRepeatedOption, [])
301
+ .option('--scope-item <value>', 'Repeatable scope item patch', collectRepeatedOption, [])
302
+ .option('--validation-item <value>', 'Repeatable validation item patch', collectRepeatedOption, [])
303
+ .option('--notes <text>', 'Updated sprint notes')
304
+ .option('--phases-json <json-or-@file>', 'JSON array or @file.json array for the nested phase+microtask plan; quote @file values in PowerShell')
305
+ .option('--expected-updated-at <timestamp>', 'Optional optimistic concurrency timestamp from a previous sprint snapshot'), { destructive: false })).action(async (options) => {
306
+ await runPmSprintUpdatePlan(options);
307
+ }));
308
+ applyPmContextOptions(sprint
309
+ .command('list')
310
+ .description('List Projectman sprint execution documents')
311
+ .option('--task <id>', 'Optional kanban task id filter')
312
+ .option('--name <name>', 'Optional sprint name filter')
313
+ .option('--status <value>', 'Optional sprint status filter')
314
+ .option('--limit <n>', 'Maximum records to return after filtering')
315
+ .option('--summary', 'Return compact sprint rows instead of full sprint plans')
316
+ .option('--include-archived', 'Include sprints with archivedAt set')
317
+ .action(async (options) => {
318
+ await runPmSprintList(options);
319
+ }));
320
+ applyPmContextOptions(sprint
321
+ .command('get')
322
+ .description('Get a Projectman sprint execution document by selector')
323
+ .requiredOption('--id <id>', 'Sprint selector: full id, 8+ id prefix, slug, or exact name/title')
324
+ .action(async (options) => {
325
+ await runPmSprintGet(options);
326
+ }));
327
+ applyPmContextOptions(applyWriteOptions(sprint
328
+ .command('archive')
329
+ .description('Soft-archive a Projectman sprint by setting archivedAt on the sprint record')
330
+ .requiredOption('--id <id>', 'Sprint selector: full id, 8+ id prefix, slug, or exact name/title'), { destructive: false }).addHelpText('after', '\nNotes:\n' +
331
+ ' This is a reversible metadata mark: linked tasks, phases, and microtasks are not changed.\n' +
332
+ ' The sprint file stays in place; this command does not write under .aops/archive/**.\n').action(async (options) => {
333
+ await runPmSprintArchive(options);
334
+ }));
335
+ applyPmContextOptions(applyWriteOptions(sprint
336
+ .command('unarchive')
337
+ .description('Restore a soft-archived Projectman sprint by clearing archivedAt')
338
+ .requiredOption('--id <id>', 'Sprint selector: full id, 8+ id prefix, slug, or exact name/title'), { destructive: false }).addHelpText('after', '\nNotes:\n' +
339
+ ' This only clears the sprint archivedAt marker; linked tasks, phases, and microtasks are not changed.\n' +
340
+ ' The sprint file stays in place; this command does not write under .aops/archive/**.\n').action(async (options) => {
341
+ await runPmSprintUnarchive(options);
342
+ }));
343
+ applyPmContextOptions(applyWriteOptions(sprint
344
+ .command('set-status')
345
+ .description('Set all microtask statuses in a sprint to the target status, deriving the sprint-level status')
346
+ .requiredOption('--id <id>', 'Sprint id')
347
+ .requiredOption('--status <value>', 'Target status: todo, doing, completed, done, cancelled, paused, blocked, postponed, in_review'), { destructive: false }).action(async (options) => {
348
+ await runPmSprintSetStatus(options);
349
+ }));
350
+ applyPmContextOptions(applyWriteOptions(sprint
351
+ .command('delete')
352
+ .description('Delete a Projectman sprint execution document')
353
+ .requiredOption('--id <id>', 'Sprint id'), { destructive: true }).action(async (options) => {
354
+ await runPmSprintDelete(options);
355
+ }));
356
+ }
357
+ function addIssueCommands(cmd) {
358
+ const issue = cmd.command('issue').description('Projectman issue commands');
359
+ applyPmContextOptions(issue
360
+ .command('list')
361
+ .description('List Projectman issues')
362
+ .option('--task <id>', 'Optional kanban task id filter')
363
+ .option('--sprint <id>', 'Optional sprint id filter')
364
+ .option('--utask <id>', 'Optional sprint microtask id filter')
365
+ .option('--review-request <id>', 'Optional source review-request id filter')
366
+ .option('--status <value>', 'Optional issue status filter')
367
+ .option('--severity <value>', 'Optional issue severity filter')
368
+ .option('--source <value>', 'Optional issue source filter')
369
+ .option('--tag <value>', 'Repeatable issue tag filter', collectRepeatedOption, [])
370
+ .action(async (options) => {
371
+ await runPmIssueList(options);
372
+ }));
373
+ applyPmContextOptions(issue
374
+ .command('get')
375
+ .description('Get a Projectman issue by id')
376
+ .requiredOption('--id <id>', 'Issue id')
377
+ .action(async (options) => {
378
+ await runPmIssueGet(options);
379
+ }));
380
+ applyPmContextOptions(applyWriteOptions(issue
381
+ .command('create')
382
+ .description('Create a Projectman issue')
383
+ .requiredOption('--title <title>', 'Issue title')
384
+ .option('--description <text>', 'Issue description')
385
+ .option('--status <value>', 'Initial issue status')
386
+ .option('--severity <value>', 'Issue severity')
387
+ .option('--source <value>', 'Issue source')
388
+ .option('--task <id>', 'Linked kanban task id')
389
+ .option('--sprint <id>', 'Linked sprint id')
390
+ .option('--utask <id>', 'Linked sprint microtask id')
391
+ .option('--review-request <id>', 'Linked Projectman review-request id; use with --source review for material findings')
392
+ .option('--notes <text>', 'Optional issue notes')
393
+ .option('--tag <value>', 'Repeatable issue tag', collectRepeatedOption, []), { destructive: false }).action(async (options) => {
394
+ await runPmIssueCreate(options);
395
+ }));
396
+ applyPmContextOptions(applyWriteOptions(issue
397
+ .command('update')
398
+ .description('Patch a Projectman issue')
399
+ .requiredOption('--id <id>', 'Issue id')
400
+ .option('--title <title>', 'Updated issue title')
401
+ .option('--description <text>', 'Updated issue description')
402
+ .option('--status <value>', 'Updated issue status')
403
+ .option('--severity <value>', 'Updated issue severity')
404
+ .option('--source <value>', 'Updated issue source')
405
+ .option('--task <id>', 'Updated kanban task id link')
406
+ .option('--sprint <id>', 'Updated sprint id link')
407
+ .option('--utask <id>', 'Updated sprint microtask id link')
408
+ .option('--review-request <id>', 'Updated Projectman review-request id link')
409
+ .option('--notes <text>', 'Updated issue notes')
410
+ .option('--tag <value>', 'Repeatable issue tag patch', collectRepeatedOption, []), { destructive: false }).action(async (options) => {
411
+ await runPmIssueUpdate(options);
412
+ }));
413
+ applyPmContextOptions(applyWriteOptions(issue
414
+ .command('delete')
415
+ .description('Delete a Projectman issue')
416
+ .requiredOption('--id <id>', 'Issue id'), { destructive: true }).action(async (options) => {
417
+ await runPmIssueDelete(options);
418
+ }));
419
+ }
420
+ function addFeedbackCommands(cmd) {
421
+ const feedback = cmd.command('feedback').description('Projectman feedback commands');
422
+ applyPmContextOptions(feedback
423
+ .command('list')
424
+ .description('List Projectman feedback items')
425
+ .option('--task <id>', 'Optional kanban task id filter')
426
+ .option('--sprint <id>', 'Optional sprint id filter')
427
+ .option('--utask <id>', 'Optional sprint microtask id filter')
428
+ .option('--status <value>', 'Optional feedback status filter')
429
+ .option('--type <value>', 'Optional feedback type filter')
430
+ .option('--severity <value>', 'Optional feedback severity filter')
431
+ .option('--source <value>', 'Optional feedback source filter')
432
+ .option('--tag <value>', 'Repeatable feedback tag filter', collectRepeatedOption, [])
433
+ .action(async (options) => {
434
+ await runPmFeedbackList(options);
435
+ }));
436
+ applyPmContextOptions(feedback
437
+ .command('get')
438
+ .description('Get a Projectman feedback item by id')
439
+ .requiredOption('--id <id>', 'Feedback id')
440
+ .action(async (options) => {
441
+ await runPmFeedbackGet(options);
442
+ }));
443
+ applyPmContextOptions(applyWriteOptions(feedback
444
+ .command('create')
445
+ .description('Create a Projectman feedback item')
446
+ .requiredOption('--title <title>', 'Feedback title')
447
+ .option('--description <text>', 'Feedback description')
448
+ .option('--status <value>', 'Initial feedback status')
449
+ .option('--type <value>', 'Feedback type')
450
+ .option('--severity <value>', 'Feedback severity')
451
+ .option('--source <value>', 'Feedback source')
452
+ .option('--task <id>', 'Linked kanban task id')
453
+ .option('--sprint <id>', 'Linked sprint id')
454
+ .option('--utask <id>', 'Linked sprint microtask id')
455
+ .option('--suggestion <text>', 'Optional suggestion text')
456
+ .option('--notes <text>', 'Optional feedback notes')
457
+ .option('--tag <value>', 'Repeatable feedback tag', collectRepeatedOption, []), { destructive: false }).action(async (options) => {
458
+ await runPmFeedbackCreate(options);
459
+ }));
460
+ applyPmContextOptions(applyWriteOptions(feedback
461
+ .command('update')
462
+ .description('Patch a Projectman feedback item')
463
+ .requiredOption('--id <id>', 'Feedback id')
464
+ .option('--title <title>', 'Updated feedback title')
465
+ .option('--description <text>', 'Updated feedback description')
466
+ .option('--status <value>', 'Updated feedback status')
467
+ .option('--type <value>', 'Updated feedback type')
468
+ .option('--severity <value>', 'Updated feedback severity')
469
+ .option('--source <value>', 'Updated feedback source')
470
+ .option('--task <id>', 'Updated kanban task id link')
471
+ .option('--sprint <id>', 'Updated sprint id link')
472
+ .option('--utask <id>', 'Updated sprint microtask id link')
473
+ .option('--suggestion <text>', 'Updated suggestion text')
474
+ .option('--notes <text>', 'Updated feedback notes')
475
+ .option('--tag <value>', 'Repeatable feedback tag patch', collectRepeatedOption, []), { destructive: false }).action(async (options) => {
476
+ await runPmFeedbackUpdate(options);
477
+ }));
478
+ applyPmContextOptions(applyWriteOptions(feedback
479
+ .command('delete')
480
+ .description('Delete a Projectman feedback item')
481
+ .requiredOption('--id <id>', 'Feedback id'), { destructive: true }).action(async (options) => {
482
+ await runPmFeedbackDelete(options);
483
+ }));
484
+ }
485
+ function addReviewRequestCommands(cmd) {
486
+ const rr = cmd.command('review-request')
487
+ .alias('rr')
488
+ .description('Projectman review request commands; canonical RR/RRR owner');
489
+ rr.addHelpText('after', '\nNotes:\n' +
490
+ ' RR is projectman.review-request. Results are append-only RRR entries on the same record.\n' +
491
+ ' Re-review is a new child RR: use `pm review-request create --parent <rr-id>`.\n' +
492
+ ' Material findings are explicit issues: `pm issue create --source review --review-request <rr-id> ...`.\n');
493
+ applyPmContextOptions(rr
494
+ .command('list')
495
+ .description('List Projectman review requests')
496
+ .option('--task <id>', 'Optional kanban task id filter')
497
+ .option('--sprint <id>', 'Optional sprint id filter')
498
+ .option('--utask <id>', 'Optional sprint microtask id filter')
499
+ .option('--status <value>', 'Optional review-request status filter')
500
+ .option('--priority <value>', 'Optional review-request priority filter')
501
+ .option('--source <value>', 'Optional review-request source filter')
502
+ .option('--target-agent <id>', 'Optional reviewer agent filter')
503
+ .option('--target-slot <slot>', 'Optional reviewer role slot filter')
504
+ .option('--parent <id>', 'Optional parent review-request id filter')
505
+ .option('--root <id>', 'Optional root review-request id filter')
506
+ .option('--tag <value>', 'Repeatable review-request tag filter', collectRepeatedOption, [])
507
+ .action(async (options) => {
508
+ await runPmReviewRequestList(options);
509
+ }));
510
+ applyPmContextOptions(rr
511
+ .command('get')
512
+ .description('Get a Projectman review request by id')
513
+ .requiredOption('--id <id>', 'Review-request id')
514
+ .action(async (options) => {
515
+ await runPmReviewRequestGet(options);
516
+ }));
517
+ applyPmContextOptions(applyWriteOptions(rr
518
+ .command('create')
519
+ .description('Create a Projectman review request; --parent opens a child re-review gate')
520
+ .requiredOption('--title <title>', 'Review-request title')
521
+ .option('--description <text>', 'Review-request description')
522
+ .option('--review-scope <text>', 'Canonical scope grammar: sprint:<id>, sprint-phase:<id>/<phase-label>, task:<id>, files:<glob> (also events:1-42 for event seq ranges)')
523
+ .option('--instructions <text>', 'Reviewer instructions')
524
+ .option('--reference <value>', 'Repeatable reference pointer', collectRepeatedOption, [])
525
+ .option('--status <value>', 'Initial status: requested, in_review, responded, accepted, changes_requested, closed, cancelled')
526
+ .option('--priority <value>', 'Priority: low, medium, high, critical (default medium)')
527
+ .option('--source <value>', 'Source: agent, operator, collab, sync, import, manual')
528
+ .option('--task <id>', 'Linked kanban task id')
529
+ .option('--sprint <id>', 'Linked sprint id')
530
+ .option('--utask <id>', 'Linked sprint microtask id')
531
+ .option('--parent <id>', 'Parent review-request id for re-review')
532
+ .option('--root <id>', 'Root review-request id override')
533
+ .option('--requested-by <id>', 'Requesting agent/operator id')
534
+ .option('--target-agent <id>', 'Target reviewer agent id')
535
+ .option('--target-slot <slot>', 'Target reviewer role slot')
536
+ .option('--tag <value>', 'Repeatable review-request tag', collectRepeatedOption, [])
537
+ .option('--notify-room <room-id>', 'Best-effort: after the RR is created (--apply only), post a "REVIEW READY" wake into this hosted chat room. Requires --ping-from. Failure does not fail the command.')
538
+ .option('--ping-from <agent-id>', 'Agent id the --notify-room wake message is posted as (required when --notify-room is set)'), { destructive: false }).action(async (options) => {
539
+ await runPmReviewRequestCreate(options);
540
+ }));
541
+ applyPmContextOptions(applyWriteOptions(rr
542
+ .command('update')
543
+ .description('Patch Projectman review-request metadata')
544
+ .requiredOption('--id <id>', 'Review-request id')
545
+ .option('--title <title>', 'Updated review-request title')
546
+ .option('--description <text>', 'Updated review-request description')
547
+ .option('--review-scope <text>', 'Updated review scope')
548
+ .option('--instructions <text>', 'Updated reviewer instructions')
549
+ .option('--reference <value>', 'Repeatable reference pointer patch', collectRepeatedOption, [])
550
+ .option('--priority <value>', 'Updated priority')
551
+ .option('--source <value>', 'Updated source')
552
+ .option('--task <id>', 'Updated kanban task id link')
553
+ .option('--sprint <id>', 'Updated sprint id link')
554
+ .option('--utask <id>', 'Updated sprint microtask id link')
555
+ .option('--requested-by <id>', 'Updated requester id')
556
+ .option('--target-agent <id>', 'Updated target reviewer agent id')
557
+ .option('--target-slot <slot>', 'Updated target reviewer role slot')
558
+ .option('--tag <value>', 'Repeatable review-request tag patch', collectRepeatedOption, []), { destructive: false }).action(async (options) => {
559
+ await runPmReviewRequestUpdate(options);
560
+ }));
561
+ applyPmContextOptions(applyWriteOptions(rr
562
+ .command('result')
563
+ .alias('add-result')
564
+ .description('Append an immutable review result (RRR) to a Projectman review request')
565
+ .requiredOption('--id <id>', 'Review-request id')
566
+ .requiredOption('--reviewer <id>', 'Reviewer agent/operator id')
567
+ .requiredOption('--outcome <value>', 'Outcome: approved, changes_requested, commented, blocked')
568
+ .requiredOption('--summary <text>', 'Review result summary')
569
+ .option('--positive <text>', 'Repeatable positive point', collectRepeatedOption, [])
570
+ .option('--concern <text>', 'Repeatable concern', collectRepeatedOption, [])
571
+ .option('--objection <text>', 'Repeatable objection', collectRepeatedOption, [])
572
+ .option('--reference <value>', 'Repeatable reference pointer', collectRepeatedOption, [])
573
+ .option('--issue <id>', 'Repeatable linked Projectman issue id', collectRepeatedOption, [])
574
+ .option('--based-on-seq-range <json>', 'Seq-range basis as JSON object or @file.json, e.g. {"from":1,"to":42}'), { destructive: false }).action(async (options) => {
575
+ await runPmReviewRequestResult(options);
576
+ }));
577
+ applyPmContextOptions(applyWriteOptions(rr
578
+ .command('delete')
579
+ .description('Delete a Projectman review request')
580
+ .requiredOption('--id <id>', 'Review-request id'), { destructive: true }).action(async (options) => {
581
+ await runPmReviewRequestDelete(options);
582
+ }));
583
+ }
584
+ function addHandoffCommands(cmd) {
585
+ applyPmContextOptions(cmd
586
+ .command('resume')
587
+ .description('Composed paste-ready resume brief: active sprint windows, review queue for an agent, open issues/feedback, durable memory, optional hosted chat unread')
588
+ .requiredOption('--for <agent-id>', 'Agent the brief is for')
589
+ .option('--limit <count>', 'Max rows per section', (value) => Number.parseInt(String(value), 10))
590
+ .option('--with-chat', 'Include hosted chat unread summary (single hosted call; degrades gracefully when the server is unavailable)')
591
+ .action(async (options) => {
592
+ await runPmResumeBrief(options);
593
+ }));
594
+ const handoff = cmd.command('handoff').description('Projectman-aware memory resume and write commands');
595
+ applyPmContextOptions(handoff
596
+ .command('resume')
597
+ .description('Build a subject-aware resume pack for a Projectman entity')
598
+ .requiredOption('--subject <kind>', 'Subject kind: project, ktask, sprint, phase, utask, issue, feedback')
599
+ .option('--id <id>', 'Subject id (optional for project; defaults to current project id)')
600
+ .option('--label <text>', 'Optional subject title/label')
601
+ .option('--task-id <id>', 'Linked kanban task id')
602
+ .option('--sprint-id <id>', 'Linked sprint id')
603
+ .option('--phase-id <id>', 'Linked phase id')
604
+ .option('--utask-id <id>', 'Linked utask id')
605
+ .option('--issue-id <id>', 'Linked issue id')
606
+ .option('--feedback-id <id>', 'Linked feedback id')
607
+ .option('--tag <value>', 'Repeatable retrieval tag', collectRepeatedOption, [])
608
+ .option('--query <text>', 'Optional explicit resume query override')
609
+ .option('--goal <text>', 'Optional goal hint')
610
+ .option('--depth <mode>', 'Resume depth: light or deep', 'light')
611
+ .option('--limit <count>', 'Result limit', (value) => Number.parseInt(String(value), 10))
612
+ .option('--candidate-limit <count>', 'Candidate fetch limit', (value) => Number.parseInt(String(value), 10))
613
+ .option('--strict-subject', 'Return only memory linked to the requested subject or explicit linked ids')
614
+ .action(async (options) => {
615
+ await runPmHandoffResume(options);
616
+ }));
617
+ applyPmContextOptions(applyWriteOptions(handoff
618
+ .command('write')
619
+ .description('Write subject-aware Projectman-linked memory for kickoff/resume/decision/blocker/closeout/rule')
620
+ .requiredOption('--mode <mode>', 'Memory mode: kickoff, resume, decision, blocker, closeout, rule')
621
+ .requiredOption('--subject <kind>', 'Subject kind: project, ktask, sprint, phase, utask, issue, feedback')
622
+ .option('--id <id>', 'Subject id (optional for project; defaults to current project id)')
623
+ .option('--label <text>', 'Optional subject title/label')
624
+ .requiredOption('--content <text>', 'Memory content')
625
+ .option('--horizon <value>', 'Optional horizon override: short, medium, long')
626
+ .option('--importance <value>', 'Importance score (0-100)', (value) => Number.parseInt(String(value), 10))
627
+ .option('--task-id <id>', 'Linked kanban task id')
628
+ .option('--sprint-id <id>', 'Linked sprint id')
629
+ .option('--phase-id <id>', 'Linked phase id')
630
+ .option('--utask-id <id>', 'Linked utask id')
631
+ .option('--issue-id <id>', 'Linked issue id')
632
+ .option('--feedback-id <id>', 'Linked feedback id')
633
+ .option('--next-action <text>', 'Recommended next action')
634
+ .option('--next-read-ref <value>', 'Repeatable next read ref (string or JSON object)', collectRepeatedOption, [])
635
+ .option('--source-ref <value>', 'Repeatable source ref (string or JSON object)', collectRepeatedOption, [])
636
+ .option('--validation-state <text>', 'Validation state summary')
637
+ .option('--pattern-name <text>', 'Reusable rule/pattern name')
638
+ .option('--pattern-when <text>', 'When the rule applies')
639
+ .option('--pattern-why <text>', 'Why the rule matters')
640
+ .option('--pattern-evidence <text>', 'Pattern evidence or notes')
641
+ .option('--tag <value>', 'Repeatable extra tag', collectRepeatedOption, []), { destructive: false }).addHelpText('after', '\nNotes:\n' +
642
+ ' AI/automation default should stay on short memory while PM execution is in progress.\n' +
643
+ ' Durable `note` and sticky `rule` are operator-controlled and should be written only on explicit human request.\n' +
644
+ ' `pm handoff write` links memory to an existing PM subject, but it does not create that sprint/task/phase/issue record.\n').action(async (options) => {
645
+ await runPmHandoffWrite(options);
646
+ }));
647
+ }
648
+ export function makePmCommand() {
649
+ const cmd = new Command('pm').description('Projectman authoring commands (hosted server-first)');
650
+ addBoardCommands(cmd);
651
+ addTaskCommands(cmd);
652
+ addSprintCommands(cmd);
653
+ addUtaskCommands(cmd);
654
+ addStatusCommands(cmd);
655
+ addIssueCommands(cmd);
656
+ addFeedbackCommands(cmd);
657
+ addReviewRequestCommands(cmd);
658
+ addHandoffCommands(cmd);
659
+ cmd.addHelpText('after', buildOperatorCookbook({
660
+ examples: [
661
+ 'aops-cli pm board create --project-id <project-id> --name "Engineering" --apply --json',
662
+ 'aops-cli pm board create --project-id <project-id> --name "Platform Delivery Coordination" --append-column "Review" --append-column "Blocked" --apply --json',
663
+ 'aops-cli pm board bootstrap set --project-id <project-id> --board engineering --doc-id <doc-id> --doc-version-id <docver-id> --prompt-id <prompt-id> --prompt-version-id <promptver-id> --task-id <task-id> --sprint-id <sprint-id> --apply --json',
664
+ 'aops-cli pm board resume --project-id <project-id> --board engineering --json',
665
+ 'aops-cli pm board kickoff --project-id <project-id> --board engineering --title "Sprint 3 polish" --goal "Register ve detail hizasini toparla" --apply --json',
666
+ 'aops-cli pm board list --project-id <project-id> --slug engineering --json',
667
+ 'aops-cli pm ktask list --project-id <project-id> --json',
668
+ 'aops-cli pm status audit --project-id <project-id> --board engineering --json',
669
+ 'aops-cli pm status reconcile --project-id <project-id> --task <task-id> --apply --json',
670
+ 'aops-cli pm sprint create --scope-id <scope-id> --task <task-id> --name "Sugar PoC" --goal "CLI facade" --reference /docs/aops.md --write-memory --apply --json',
671
+ 'aops-cli pm sprint update-plan --scope-id <scope-id> --id <sprint-id> --phases-json \'@/tmp/sprint-plan.json\' --apply --json',
672
+ 'aops-cli pm utask update --scope-id <scope-id> --sprint <sprint-id> --id <utask-id> --status doing --write-memory --memory-next-action "Bir sonraki validasyonu tamamla." --apply --json',
673
+ 'aops-cli pm issue create --project-id <project-id> --title "Sync push failure" --severity high --source agent --apply --json',
674
+ 'aops-cli pm review-request create --project-id <project-id> --title "Check my implementation" --target-agent claude --review-scope sprint:<sprint-id> --instructions "Focus on regressions and missing tests" --apply --json',
675
+ 'aops-cli pm review-request result --project-id <project-id> --id <rr-id> --reviewer claude --outcome changes_requested --summary "One blocker found" --issue <issue-id> --apply --json',
676
+ 'aops-cli pm issue create --project-id <project-id> --source review --review-request <rr-id> --title "Review finding" --apply --json',
677
+ 'aops-cli pm feedback list --project-id <project-id> --status new --json',
678
+ 'aops-cli pm handoff write --project-id <project-id> --mode kickoff --subject sprint --id <sprint-id> --content "Bugun burada basliyoruz." --apply --json',
679
+ 'aops-cli pm handoff resume --project-id <project-id> --subject sprint --id <sprint-id> --json',
680
+ ],
681
+ guide: GUIDE_PATHS.projectman,
682
+ notes: [
683
+ 'pm board create uses the hosted board flow; --column replaces the default columns, --append-column extends them, and omitting both bootstraps Backlog, Todo, Doing, Done.',
684
+ 'pm board bootstrap set/get keep a board-slug registry in hosted metadata so agents can discover the canonical doc/prompt/task/sprint chain later.',
685
+ 'pm board resume composes board registry + active task/sprint + memory into one sugar response for agent handoff.',
686
+ 'pm board kickoff reuses the current active task/sprint window when it is still open; otherwise it creates a fresh tracked window and refreshes the board registry.',
687
+ 'Board-owned column slugs are generated as board-slug + column-slug, for example ui-gelistirme-todo.',
688
+ 'pm board list/get/delete expose hosted board records directly; board id, exact name, and slug selectors are supported by sugar.',
689
+ 'pm sprint update-plan accepts --phases-json as inline JSON or @file.json so rich nested sprint demos do not require raw agent invoke; PowerShell users should quote @file values, e.g. --phases-json \'@tmp/sprint-plan.json\'.',
690
+ 'Phase status is derived from nested microtask statuses; do not send phase.status inside --phases-json.',
691
+ '--write-memory writes an opt-in memory side-effect only after the main PM mutation succeeds; AI defaults should stay short.',
692
+ 'pm handoff write stores PM-linked memory for kickoff/resume/decision/blocker/closeout/rule flows.',
693
+ 'Durable `note` ve sticky `rule` operator/human kontrolundedir; agent execution sirasinda default olarak yazilmaz.',
694
+ 'pm handoff resume reads from an existing tracked Projectman subject such as a real sprint, task, issue, or feedback.',
695
+ 'pm review-request is the canonical RR/RRR surface for review-request/result and re-review.',
696
+ 'pm handoff write stores memory, but it does not create the Projectman sprint/task/phase record itself.',
697
+ 'Phase is still a sprint-nested execution grouping surface, not a standalone pm CRUD family.',
698
+ ],
699
+ }));
700
+ return cmd;
701
+ }