pm-orchestrator-runner 1.0.6 → 1.0.8

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 (105) hide show
  1. package/README.md +20 -10
  2. package/dist/cli/index.js +36 -1
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/config/index.d.ts +9 -0
  5. package/dist/config/index.d.ts.map +1 -0
  6. package/dist/config/index.js +19 -0
  7. package/dist/config/index.js.map +1 -0
  8. package/dist/config/namespace.d.ts +86 -0
  9. package/dist/config/namespace.d.ts.map +1 -0
  10. package/dist/config/namespace.js +150 -0
  11. package/dist/config/namespace.js.map +1 -0
  12. package/dist/core/runner-core.d.ts +19 -0
  13. package/dist/core/runner-core.d.ts.map +1 -1
  14. package/dist/core/runner-core.js +67 -4
  15. package/dist/core/runner-core.js.map +1 -1
  16. package/dist/executor/claude-code-executor.d.ts +28 -0
  17. package/dist/executor/claude-code-executor.d.ts.map +1 -1
  18. package/dist/executor/claude-code-executor.js +184 -1
  19. package/dist/executor/claude-code-executor.js.map +1 -1
  20. package/dist/executor/deterministic-executor.d.ts +2 -1
  21. package/dist/executor/deterministic-executor.d.ts.map +1 -1
  22. package/dist/executor/deterministic-executor.js +7 -0
  23. package/dist/executor/deterministic-executor.js.map +1 -1
  24. package/dist/executor/recovery-executor.d.ts +2 -1
  25. package/dist/executor/recovery-executor.d.ts.map +1 -1
  26. package/dist/executor/recovery-executor.js +7 -0
  27. package/dist/executor/recovery-executor.js.map +1 -1
  28. package/dist/logging/task-log-manager.d.ts +17 -2
  29. package/dist/logging/task-log-manager.d.ts.map +1 -1
  30. package/dist/logging/task-log-manager.js +153 -63
  31. package/dist/logging/task-log-manager.js.map +1 -1
  32. package/dist/models/enums.d.ts +54 -0
  33. package/dist/models/enums.d.ts.map +1 -1
  34. package/dist/models/enums.js +59 -1
  35. package/dist/models/enums.js.map +1 -1
  36. package/dist/models/index.d.ts +4 -1
  37. package/dist/models/index.d.ts.map +1 -1
  38. package/dist/models/index.js +50 -2
  39. package/dist/models/index.js.map +1 -1
  40. package/dist/models/repl/task-log.d.ts +9 -0
  41. package/dist/models/repl/task-log.d.ts.map +1 -1
  42. package/dist/models/repl/task-log.js.map +1 -1
  43. package/dist/models/run.d.ts +82 -0
  44. package/dist/models/run.d.ts.map +1 -0
  45. package/dist/models/run.js +161 -0
  46. package/dist/models/run.js.map +1 -0
  47. package/dist/models/task-group.d.ts +164 -0
  48. package/dist/models/task-group.d.ts.map +1 -0
  49. package/dist/models/task-group.js +246 -0
  50. package/dist/models/task-group.js.map +1 -0
  51. package/dist/models/task.d.ts +7 -0
  52. package/dist/models/task.d.ts.map +1 -1
  53. package/dist/models/task.js.map +1 -1
  54. package/dist/models/thread.d.ts +53 -0
  55. package/dist/models/thread.d.ts.map +1 -0
  56. package/dist/models/thread.js +92 -0
  57. package/dist/models/thread.js.map +1 -0
  58. package/dist/pool/agent-pool.d.ts.map +1 -1
  59. package/dist/pool/agent-pool.js +2 -3
  60. package/dist/pool/agent-pool.js.map +1 -1
  61. package/dist/prompt/index.d.ts +8 -0
  62. package/dist/prompt/index.d.ts.map +1 -0
  63. package/dist/prompt/index.js +13 -0
  64. package/dist/prompt/index.js.map +1 -0
  65. package/dist/prompt/prompt-assembler.d.ts +145 -0
  66. package/dist/prompt/prompt-assembler.d.ts.map +1 -0
  67. package/dist/prompt/prompt-assembler.js +242 -0
  68. package/dist/prompt/prompt-assembler.js.map +1 -0
  69. package/dist/queue/index.d.ts +41 -0
  70. package/dist/queue/index.d.ts.map +1 -0
  71. package/dist/queue/index.js +42 -0
  72. package/dist/queue/index.js.map +1 -0
  73. package/dist/queue/queue-poller.d.ts +107 -0
  74. package/dist/queue/queue-poller.d.ts.map +1 -0
  75. package/dist/queue/queue-poller.js +181 -0
  76. package/dist/queue/queue-poller.js.map +1 -0
  77. package/dist/queue/queue-store.d.ts +163 -0
  78. package/dist/queue/queue-store.d.ts.map +1 -0
  79. package/dist/queue/queue-store.js +421 -0
  80. package/dist/queue/queue-store.js.map +1 -0
  81. package/dist/repl/commands/logs.d.ts +3 -1
  82. package/dist/repl/commands/logs.d.ts.map +1 -1
  83. package/dist/repl/commands/logs.js +23 -3
  84. package/dist/repl/commands/logs.js.map +1 -1
  85. package/dist/repl/index.d.ts +1 -0
  86. package/dist/repl/index.d.ts.map +1 -1
  87. package/dist/repl/index.js +3 -1
  88. package/dist/repl/index.js.map +1 -1
  89. package/dist/repl/repl-interface.d.ts +94 -6
  90. package/dist/repl/repl-interface.d.ts.map +1 -1
  91. package/dist/repl/repl-interface.js +350 -54
  92. package/dist/repl/repl-interface.js.map +1 -1
  93. package/dist/repl/two-pane-renderer.d.ts +148 -0
  94. package/dist/repl/two-pane-renderer.d.ts.map +1 -0
  95. package/dist/repl/two-pane-renderer.js +239 -0
  96. package/dist/repl/two-pane-renderer.js.map +1 -0
  97. package/dist/web/index.d.ts +45 -0
  98. package/dist/web/index.d.ts.map +1 -0
  99. package/dist/web/index.js +47 -0
  100. package/dist/web/index.js.map +1 -0
  101. package/dist/web/server.d.ts +71 -0
  102. package/dist/web/server.d.ts.map +1 -0
  103. package/dist/web/server.js +329 -0
  104. package/dist/web/server.js.map +1 -0
  105. package/package.json +12 -3
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Queue Store - DynamoDB Local implementation
3
+ * Per spec/20_QUEUE_STORE.md
4
+ *
5
+ * Provides queue operations with:
6
+ * - Atomic QUEUED -> RUNNING transitions (conditional update)
7
+ * - Double execution prevention
8
+ * - Fail-closed error handling
9
+ */
10
+ /**
11
+ * Queue Item status
12
+ * Per spec/20: QUEUED / RUNNING / COMPLETE / ERROR
13
+ */
14
+ export type QueueItemStatus = 'QUEUED' | 'RUNNING' | 'COMPLETE' | 'ERROR';
15
+ /**
16
+ * Queue Item schema
17
+ * Per spec/20_QUEUE_STORE.md
18
+ */
19
+ export interface QueueItem {
20
+ task_id: string;
21
+ task_group_id: string;
22
+ session_id: string;
23
+ status: QueueItemStatus;
24
+ prompt: string;
25
+ created_at: string;
26
+ updated_at: string;
27
+ error_message?: string;
28
+ }
29
+ /**
30
+ * Queue Store configuration
31
+ */
32
+ export interface QueueStoreConfig {
33
+ /** DynamoDB endpoint (default: http://localhost:8000) */
34
+ endpoint?: string;
35
+ /** Table name (default: pm-runner-queue) */
36
+ tableName?: string;
37
+ /** AWS region (default: local) */
38
+ region?: string;
39
+ }
40
+ /**
41
+ * Claim result
42
+ */
43
+ export interface ClaimResult {
44
+ success: boolean;
45
+ item?: QueueItem;
46
+ error?: string;
47
+ }
48
+ /**
49
+ * Task Group summary for listing
50
+ * Per spec/19_WEB_UI.md: task group list view
51
+ */
52
+ export interface TaskGroupSummary {
53
+ task_group_id: string;
54
+ task_count: number;
55
+ created_at: string;
56
+ latest_updated_at: string;
57
+ }
58
+ /**
59
+ * Queue Store
60
+ * Manages task queue with DynamoDB Local
61
+ */
62
+ export declare class QueueStore {
63
+ private readonly client;
64
+ private readonly docClient;
65
+ private readonly tableName;
66
+ private readonly endpoint;
67
+ constructor(config?: QueueStoreConfig);
68
+ /**
69
+ * Get table name
70
+ */
71
+ getTableName(): string;
72
+ /**
73
+ * Get endpoint
74
+ */
75
+ getEndpoint(): string;
76
+ /**
77
+ * Check if table exists
78
+ */
79
+ tableExists(): Promise<boolean>;
80
+ /**
81
+ * Create table with required GSIs
82
+ * Per spec/20_QUEUE_STORE.md table definition
83
+ */
84
+ createTable(): Promise<void>;
85
+ /**
86
+ * Ensure table exists, create if not
87
+ */
88
+ ensureTable(): Promise<void>;
89
+ /**
90
+ * Wait for table to become active
91
+ */
92
+ private waitForTableActive;
93
+ /**
94
+ * Enqueue a new task
95
+ * Creates item with status=QUEUED
96
+ *
97
+ * @param sessionId - Session ID
98
+ * @param taskGroupId - Task Group ID
99
+ * @param prompt - User prompt
100
+ * @param taskId - Optional task ID (generates if not provided)
101
+ * @returns Created queue item
102
+ */
103
+ enqueue(sessionId: string, taskGroupId: string, prompt: string, taskId?: string): Promise<QueueItem>;
104
+ /**
105
+ * Get item by task_id
106
+ */
107
+ getItem(taskId: string): Promise<QueueItem | null>;
108
+ /**
109
+ * Claim the oldest QUEUED task (atomic QUEUED -> RUNNING)
110
+ * Per spec: Uses conditional update for double execution prevention
111
+ *
112
+ * @returns ClaimResult with success flag and item if claimed
113
+ */
114
+ claim(): Promise<ClaimResult>;
115
+ /**
116
+ * Update task status
117
+ * Per spec: RUNNING -> COMPLETE or RUNNING -> ERROR
118
+ *
119
+ * @param taskId - Task ID
120
+ * @param status - New status
121
+ * @param errorMessage - Optional error message (for ERROR status)
122
+ */
123
+ updateStatus(taskId: string, status: QueueItemStatus, errorMessage?: string): Promise<void>;
124
+ /**
125
+ * Get items by session ID
126
+ * Uses session-index GSI
127
+ */
128
+ getBySession(sessionId: string): Promise<QueueItem[]>;
129
+ /**
130
+ * Get items by status
131
+ * Uses status-index GSI
132
+ */
133
+ getByStatus(status: QueueItemStatus): Promise<QueueItem[]>;
134
+ /**
135
+ * Get items by task group ID
136
+ * Uses task-group-index GSI
137
+ * Per spec/19_WEB_UI.md: for listing tasks in a task group
138
+ */
139
+ getByTaskGroup(taskGroupId: string): Promise<QueueItem[]>;
140
+ /**
141
+ * Get all distinct task groups with summary
142
+ * Per spec/19_WEB_UI.md: for task group list view
143
+ * Note: Uses Scan - consider pagination for large datasets
144
+ */
145
+ getAllTaskGroups(): Promise<TaskGroupSummary[]>;
146
+ /**
147
+ * Delete item (for testing)
148
+ */
149
+ deleteItem(taskId: string): Promise<void>;
150
+ /**
151
+ * Mark stale RUNNING tasks as ERROR
152
+ * Per spec: fail-closed - don't leave tasks in "limbo"
153
+ *
154
+ * @param maxAgeMs - Max age in milliseconds for RUNNING tasks
155
+ * @returns Number of tasks marked as ERROR
156
+ */
157
+ recoverStaleTasks(maxAgeMs?: number): Promise<number>;
158
+ /**
159
+ * Close the client connection
160
+ */
161
+ destroy(): void;
162
+ }
163
+ //# sourceMappingURL=queue-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-store.d.ts","sourceRoot":"","sources":["../../src/queue/queue-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmBH;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,GAAE,gBAAqB;IAqBzC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAcrC;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IA0DlC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IASlC;;OAEG;YACW,kBAAkB;IAkBhC;;;;;;;;;OASG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC;IAsBrB;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAWxD;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAgEnC;;;;;;;OAOG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,EACvB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IA6BhB;;;OAGG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAgB3D;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAmBhE;;;;OAIG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAgB/D;;;;OAIG;IACG,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAiDrD;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C;;;;;;OAMG;IACG,iBAAiB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB1E;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,421 @@
1
+ "use strict";
2
+ /**
3
+ * Queue Store - DynamoDB Local implementation
4
+ * Per spec/20_QUEUE_STORE.md
5
+ *
6
+ * Provides queue operations with:
7
+ * - Atomic QUEUED -> RUNNING transitions (conditional update)
8
+ * - Double execution prevention
9
+ * - Fail-closed error handling
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.QueueStore = void 0;
13
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
14
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
15
+ const uuid_1 = require("uuid");
16
+ /**
17
+ * Queue Store
18
+ * Manages task queue with DynamoDB Local
19
+ */
20
+ class QueueStore {
21
+ client;
22
+ docClient;
23
+ tableName;
24
+ endpoint;
25
+ constructor(config = {}) {
26
+ this.endpoint = config.endpoint || 'http://localhost:8000';
27
+ this.tableName = config.tableName || 'pm-runner-queue';
28
+ const region = config.region || 'local';
29
+ this.client = new client_dynamodb_1.DynamoDBClient({
30
+ endpoint: this.endpoint,
31
+ region: region,
32
+ credentials: {
33
+ accessKeyId: 'local',
34
+ secretAccessKey: 'local',
35
+ },
36
+ });
37
+ this.docClient = lib_dynamodb_1.DynamoDBDocumentClient.from(this.client, {
38
+ marshallOptions: {
39
+ removeUndefinedValues: true,
40
+ },
41
+ });
42
+ }
43
+ /**
44
+ * Get table name
45
+ */
46
+ getTableName() {
47
+ return this.tableName;
48
+ }
49
+ /**
50
+ * Get endpoint
51
+ */
52
+ getEndpoint() {
53
+ return this.endpoint;
54
+ }
55
+ /**
56
+ * Check if table exists
57
+ */
58
+ async tableExists() {
59
+ try {
60
+ await this.client.send(new client_dynamodb_1.DescribeTableCommand({ TableName: this.tableName }));
61
+ return true;
62
+ }
63
+ catch (error) {
64
+ if (error instanceof client_dynamodb_1.ResourceNotFoundException) {
65
+ return false;
66
+ }
67
+ throw error;
68
+ }
69
+ }
70
+ /**
71
+ * Create table with required GSIs
72
+ * Per spec/20_QUEUE_STORE.md table definition
73
+ */
74
+ async createTable() {
75
+ const command = new client_dynamodb_1.CreateTableCommand({
76
+ TableName: this.tableName,
77
+ KeySchema: [{ AttributeName: 'task_id', KeyType: 'HASH' }],
78
+ AttributeDefinitions: [
79
+ { AttributeName: 'task_id', AttributeType: 'S' },
80
+ { AttributeName: 'session_id', AttributeType: 'S' },
81
+ { AttributeName: 'status', AttributeType: 'S' },
82
+ { AttributeName: 'created_at', AttributeType: 'S' },
83
+ { AttributeName: 'task_group_id', AttributeType: 'S' },
84
+ ],
85
+ GlobalSecondaryIndexes: [
86
+ {
87
+ IndexName: 'session-index',
88
+ KeySchema: [
89
+ { AttributeName: 'session_id', KeyType: 'HASH' },
90
+ { AttributeName: 'created_at', KeyType: 'RANGE' },
91
+ ],
92
+ Projection: { ProjectionType: 'ALL' },
93
+ ProvisionedThroughput: {
94
+ ReadCapacityUnits: 5,
95
+ WriteCapacityUnits: 5,
96
+ },
97
+ },
98
+ {
99
+ IndexName: 'status-index',
100
+ KeySchema: [
101
+ { AttributeName: 'status', KeyType: 'HASH' },
102
+ { AttributeName: 'created_at', KeyType: 'RANGE' },
103
+ ],
104
+ Projection: { ProjectionType: 'ALL' },
105
+ ProvisionedThroughput: {
106
+ ReadCapacityUnits: 5,
107
+ WriteCapacityUnits: 5,
108
+ },
109
+ },
110
+ {
111
+ IndexName: 'task-group-index',
112
+ KeySchema: [
113
+ { AttributeName: 'task_group_id', KeyType: 'HASH' },
114
+ { AttributeName: 'created_at', KeyType: 'RANGE' },
115
+ ],
116
+ Projection: { ProjectionType: 'ALL' },
117
+ ProvisionedThroughput: {
118
+ ReadCapacityUnits: 5,
119
+ WriteCapacityUnits: 5,
120
+ },
121
+ },
122
+ ],
123
+ ProvisionedThroughput: {
124
+ ReadCapacityUnits: 5,
125
+ WriteCapacityUnits: 5,
126
+ },
127
+ });
128
+ await this.client.send(command);
129
+ }
130
+ /**
131
+ * Ensure table exists, create if not
132
+ */
133
+ async ensureTable() {
134
+ const exists = await this.tableExists();
135
+ if (!exists) {
136
+ await this.createTable();
137
+ // Wait for table to be active
138
+ await this.waitForTableActive();
139
+ }
140
+ }
141
+ /**
142
+ * Wait for table to become active
143
+ */
144
+ async waitForTableActive(maxWaitMs = 30000) {
145
+ const startTime = Date.now();
146
+ while (Date.now() - startTime < maxWaitMs) {
147
+ try {
148
+ const result = await this.client.send(new client_dynamodb_1.DescribeTableCommand({ TableName: this.tableName }));
149
+ if (result.Table?.TableStatus === 'ACTIVE') {
150
+ return;
151
+ }
152
+ }
153
+ catch {
154
+ // Table not ready yet
155
+ }
156
+ await new Promise(resolve => setTimeout(resolve, 100));
157
+ }
158
+ throw new Error(`Table ${this.tableName} did not become active within ${maxWaitMs}ms`);
159
+ }
160
+ /**
161
+ * Enqueue a new task
162
+ * Creates item with status=QUEUED
163
+ *
164
+ * @param sessionId - Session ID
165
+ * @param taskGroupId - Task Group ID
166
+ * @param prompt - User prompt
167
+ * @param taskId - Optional task ID (generates if not provided)
168
+ * @returns Created queue item
169
+ */
170
+ async enqueue(sessionId, taskGroupId, prompt, taskId) {
171
+ const now = new Date().toISOString();
172
+ const item = {
173
+ task_id: taskId || (0, uuid_1.v4)(),
174
+ task_group_id: taskGroupId,
175
+ session_id: sessionId,
176
+ status: 'QUEUED',
177
+ prompt,
178
+ created_at: now,
179
+ updated_at: now,
180
+ };
181
+ await this.docClient.send(new lib_dynamodb_1.PutCommand({
182
+ TableName: this.tableName,
183
+ Item: item,
184
+ }));
185
+ return item;
186
+ }
187
+ /**
188
+ * Get item by task_id
189
+ */
190
+ async getItem(taskId) {
191
+ const result = await this.docClient.send(new lib_dynamodb_1.GetCommand({
192
+ TableName: this.tableName,
193
+ Key: { task_id: taskId },
194
+ }));
195
+ return result.Item || null;
196
+ }
197
+ /**
198
+ * Claim the oldest QUEUED task (atomic QUEUED -> RUNNING)
199
+ * Per spec: Uses conditional update for double execution prevention
200
+ *
201
+ * @returns ClaimResult with success flag and item if claimed
202
+ */
203
+ async claim() {
204
+ // Query for oldest QUEUED item using status-index
205
+ const queryResult = await this.docClient.send(new lib_dynamodb_1.QueryCommand({
206
+ TableName: this.tableName,
207
+ IndexName: 'status-index',
208
+ KeyConditionExpression: '#status = :queued',
209
+ ExpressionAttributeNames: {
210
+ '#status': 'status',
211
+ },
212
+ ExpressionAttributeValues: {
213
+ ':queued': 'QUEUED',
214
+ },
215
+ Limit: 1,
216
+ ScanIndexForward: true, // Ascending by created_at (oldest first)
217
+ }));
218
+ if (!queryResult.Items || queryResult.Items.length === 0) {
219
+ return { success: false };
220
+ }
221
+ const item = queryResult.Items[0];
222
+ // Atomic update: QUEUED -> RUNNING with conditional check
223
+ try {
224
+ const now = new Date().toISOString();
225
+ await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
226
+ TableName: this.tableName,
227
+ Key: { task_id: item.task_id },
228
+ UpdateExpression: 'SET #status = :running, updated_at = :now',
229
+ ConditionExpression: '#status = :queued',
230
+ ExpressionAttributeNames: {
231
+ '#status': 'status',
232
+ },
233
+ ExpressionAttributeValues: {
234
+ ':running': 'RUNNING',
235
+ ':queued': 'QUEUED',
236
+ ':now': now,
237
+ },
238
+ }));
239
+ // Update local item with new status
240
+ item.status = 'RUNNING';
241
+ item.updated_at = now;
242
+ return { success: true, item };
243
+ }
244
+ catch (error) {
245
+ // ConditionalCheckFailed means another process claimed it
246
+ if (error &&
247
+ typeof error === 'object' &&
248
+ 'name' in error &&
249
+ error.name === 'ConditionalCheckFailedException') {
250
+ return { success: false, error: 'Task already claimed by another process' };
251
+ }
252
+ // Fail-closed: re-throw unexpected errors
253
+ throw error;
254
+ }
255
+ }
256
+ /**
257
+ * Update task status
258
+ * Per spec: RUNNING -> COMPLETE or RUNNING -> ERROR
259
+ *
260
+ * @param taskId - Task ID
261
+ * @param status - New status
262
+ * @param errorMessage - Optional error message (for ERROR status)
263
+ */
264
+ async updateStatus(taskId, status, errorMessage) {
265
+ const now = new Date().toISOString();
266
+ const updateExpression = errorMessage
267
+ ? 'SET #status = :status, updated_at = :now, error_message = :error'
268
+ : 'SET #status = :status, updated_at = :now';
269
+ const expressionAttributeValues = {
270
+ ':status': status,
271
+ ':now': now,
272
+ };
273
+ if (errorMessage) {
274
+ expressionAttributeValues[':error'] = errorMessage;
275
+ }
276
+ await this.docClient.send(new lib_dynamodb_1.UpdateCommand({
277
+ TableName: this.tableName,
278
+ Key: { task_id: taskId },
279
+ UpdateExpression: updateExpression,
280
+ ExpressionAttributeNames: {
281
+ '#status': 'status',
282
+ },
283
+ ExpressionAttributeValues: expressionAttributeValues,
284
+ }));
285
+ }
286
+ /**
287
+ * Get items by session ID
288
+ * Uses session-index GSI
289
+ */
290
+ async getBySession(sessionId) {
291
+ const result = await this.docClient.send(new lib_dynamodb_1.QueryCommand({
292
+ TableName: this.tableName,
293
+ IndexName: 'session-index',
294
+ KeyConditionExpression: 'session_id = :sid',
295
+ ExpressionAttributeValues: {
296
+ ':sid': sessionId,
297
+ },
298
+ ScanIndexForward: true, // Ascending by created_at
299
+ }));
300
+ return result.Items || [];
301
+ }
302
+ /**
303
+ * Get items by status
304
+ * Uses status-index GSI
305
+ */
306
+ async getByStatus(status) {
307
+ const result = await this.docClient.send(new lib_dynamodb_1.QueryCommand({
308
+ TableName: this.tableName,
309
+ IndexName: 'status-index',
310
+ KeyConditionExpression: '#status = :status',
311
+ ExpressionAttributeNames: {
312
+ '#status': 'status',
313
+ },
314
+ ExpressionAttributeValues: {
315
+ ':status': status,
316
+ },
317
+ ScanIndexForward: true, // Ascending by created_at
318
+ }));
319
+ return result.Items || [];
320
+ }
321
+ /**
322
+ * Get items by task group ID
323
+ * Uses task-group-index GSI
324
+ * Per spec/19_WEB_UI.md: for listing tasks in a task group
325
+ */
326
+ async getByTaskGroup(taskGroupId) {
327
+ const result = await this.docClient.send(new lib_dynamodb_1.QueryCommand({
328
+ TableName: this.tableName,
329
+ IndexName: 'task-group-index',
330
+ KeyConditionExpression: 'task_group_id = :tgid',
331
+ ExpressionAttributeValues: {
332
+ ':tgid': taskGroupId,
333
+ },
334
+ ScanIndexForward: true, // Ascending by created_at
335
+ }));
336
+ return result.Items || [];
337
+ }
338
+ /**
339
+ * Get all distinct task groups with summary
340
+ * Per spec/19_WEB_UI.md: for task group list view
341
+ * Note: Uses Scan - consider pagination for large datasets
342
+ */
343
+ async getAllTaskGroups() {
344
+ // Scan all items and aggregate by task_group_id
345
+ const result = await this.docClient.send(new lib_dynamodb_1.ScanCommand({
346
+ TableName: this.tableName,
347
+ ProjectionExpression: 'task_group_id, created_at, updated_at',
348
+ }));
349
+ const items = result.Items || [];
350
+ // Aggregate by task_group_id
351
+ const groupMap = new Map();
352
+ for (const item of items) {
353
+ const existing = groupMap.get(item.task_group_id);
354
+ if (existing) {
355
+ existing.count++;
356
+ if (item.created_at < existing.createdAt) {
357
+ existing.createdAt = item.created_at;
358
+ }
359
+ if (item.updated_at > existing.latestUpdatedAt) {
360
+ existing.latestUpdatedAt = item.updated_at;
361
+ }
362
+ }
363
+ else {
364
+ groupMap.set(item.task_group_id, {
365
+ count: 1,
366
+ createdAt: item.created_at,
367
+ latestUpdatedAt: item.updated_at,
368
+ });
369
+ }
370
+ }
371
+ // Convert to array and sort by created_at (oldest first)
372
+ const groups = [];
373
+ for (const [taskGroupId, data] of groupMap) {
374
+ groups.push({
375
+ task_group_id: taskGroupId,
376
+ task_count: data.count,
377
+ created_at: data.createdAt,
378
+ latest_updated_at: data.latestUpdatedAt,
379
+ });
380
+ }
381
+ groups.sort((a, b) => a.created_at.localeCompare(b.created_at));
382
+ return groups;
383
+ }
384
+ /**
385
+ * Delete item (for testing)
386
+ */
387
+ async deleteItem(taskId) {
388
+ await this.docClient.send(new lib_dynamodb_1.DeleteCommand({
389
+ TableName: this.tableName,
390
+ Key: { task_id: taskId },
391
+ }));
392
+ }
393
+ /**
394
+ * Mark stale RUNNING tasks as ERROR
395
+ * Per spec: fail-closed - don't leave tasks in "limbo"
396
+ *
397
+ * @param maxAgeMs - Max age in milliseconds for RUNNING tasks
398
+ * @returns Number of tasks marked as ERROR
399
+ */
400
+ async recoverStaleTasks(maxAgeMs = 5 * 60 * 1000) {
401
+ const runningTasks = await this.getByStatus('RUNNING');
402
+ const now = Date.now();
403
+ let recovered = 0;
404
+ for (const task of runningTasks) {
405
+ const taskAge = now - new Date(task.updated_at).getTime();
406
+ if (taskAge > maxAgeMs) {
407
+ await this.updateStatus(task.task_id, 'ERROR', `Task stale: running for ${Math.round(taskAge / 1000)}s without completion`);
408
+ recovered++;
409
+ }
410
+ }
411
+ return recovered;
412
+ }
413
+ /**
414
+ * Close the client connection
415
+ */
416
+ destroy() {
417
+ this.client.destroy();
418
+ }
419
+ }
420
+ exports.QueueStore = QueueStore;
421
+ //# sourceMappingURL=queue-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-store.js","sourceRoot":"","sources":["../../src/queue/queue-store.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,8DAKkC;AAClC,wDAQ+B;AAC/B,+BAAoC;AAuDpC;;;GAGG;AACH,MAAa,UAAU;IACJ,MAAM,CAAiB;IACvB,SAAS,CAAyB;IAClC,SAAS,CAAS;IAClB,QAAQ,CAAS;IAElC,YAAY,SAA2B,EAAE;QACvC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,uBAAuB,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,iBAAiB,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC;QAExC,IAAI,CAAC,MAAM,GAAG,IAAI,gCAAc,CAAC;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,MAAM;YACd,WAAW,EAAE;gBACX,WAAW,EAAE,OAAO;gBACpB,eAAe,EAAE,OAAO;aACzB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,GAAG,qCAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YACxD,eAAe,EAAE;gBACf,qBAAqB,EAAE,IAAI;aAC5B;SACF,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CACpB,IAAI,sCAAoB,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CACxD,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,2CAAyB,EAAE,CAAC;gBAC/C,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,OAAO,GAAG,IAAI,oCAAkB,CAAC;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAC1D,oBAAoB,EAAE;gBACpB,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE;gBAChD,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,EAAE;gBACnD,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE;gBAC/C,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,EAAE;gBACnD,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,EAAE;aACvD;YACD,sBAAsB,EAAE;gBACtB;oBACE,SAAS,EAAE,eAAe;oBAC1B,SAAS,EAAE;wBACT,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE;wBAChD,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE;qBAClD;oBACD,UAAU,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;oBACrC,qBAAqB,EAAE;wBACrB,iBAAiB,EAAE,CAAC;wBACpB,kBAAkB,EAAE,CAAC;qBACtB;iBACF;gBACD;oBACE,SAAS,EAAE,cAAc;oBACzB,SAAS,EAAE;wBACT,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;wBAC5C,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE;qBAClD;oBACD,UAAU,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;oBACrC,qBAAqB,EAAE;wBACrB,iBAAiB,EAAE,CAAC;wBACpB,kBAAkB,EAAE,CAAC;qBACtB;iBACF;gBACD;oBACE,SAAS,EAAE,kBAAkB;oBAC7B,SAAS,EAAE;wBACT,EAAE,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE;wBACnD,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE;qBAClD;oBACD,UAAU,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;oBACrC,qBAAqB,EAAE;wBACrB,iBAAiB,EAAE,CAAC;wBACpB,kBAAkB,EAAE,CAAC;qBACtB;iBACF;aACF;YACD,qBAAqB,EAAE;gBACrB,iBAAiB,EAAE,CAAC;gBACpB,kBAAkB,EAAE,CAAC;aACtB;SACF,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YACzB,8BAA8B;YAC9B,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,SAAS,GAAG,KAAK;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CACnC,IAAI,sCAAoB,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CACxD,CAAC;gBACF,IAAI,MAAM,CAAC,KAAK,EAAE,WAAW,KAAK,QAAQ,EAAE,CAAC;oBAC3C,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sBAAsB;YACxB,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,iCAAiC,SAAS,IAAI,CAAC,CAAC;IACzF,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,OAAO,CACX,SAAiB,EACjB,WAAmB,EACnB,MAAc,EACd,MAAe;QAEf,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,IAAI,GAAc;YACtB,OAAO,EAAE,MAAM,IAAI,IAAA,SAAM,GAAE;YAC3B,aAAa,EAAE,WAAW;YAC1B,UAAU,EAAE,SAAS;YACrB,MAAM,EAAE,QAAQ;YAChB,MAAM;YACN,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QAEF,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACvB,IAAI,yBAAU,CAAC;YACb,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI;SACX,CAAC,CACH,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAc;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACtC,IAAI,yBAAU,CAAC;YACb,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;SACzB,CAAC,CACH,CAAC;QAEF,OAAQ,MAAM,CAAC,IAAkB,IAAI,IAAI,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK;QACT,kDAAkD;QAClD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAC3C,IAAI,2BAAY,CAAC;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,cAAc;YACzB,sBAAsB,EAAE,mBAAmB;YAC3C,wBAAwB,EAAE;gBACxB,SAAS,EAAE,QAAQ;aACpB;YACD,yBAAyB,EAAE;gBACzB,SAAS,EAAE,QAAQ;aACpB;YACD,KAAK,EAAE,CAAC;YACR,gBAAgB,EAAE,IAAI,EAAE,yCAAyC;SAClE,CAAC,CACH,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAc,CAAC;QAE/C,0DAA0D;QAC1D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACvB,IAAI,4BAAa,CAAC;gBAChB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;gBAC9B,gBAAgB,EAAE,2CAA2C;gBAC7D,mBAAmB,EAAE,mBAAmB;gBACxC,wBAAwB,EAAE;oBACxB,SAAS,EAAE,QAAQ;iBACpB;gBACD,yBAAyB,EAAE;oBACzB,UAAU,EAAE,SAAS;oBACrB,SAAS,EAAE,QAAQ;oBACnB,MAAM,EAAE,GAAG;iBACZ;aACF,CAAC,CACH,CAAC;YAEF,oCAAoC;YACpC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YACxB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;YAEtB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,0DAA0D;YAC1D,IACE,KAAK;gBACL,OAAO,KAAK,KAAK,QAAQ;gBACzB,MAAM,IAAI,KAAK;gBACf,KAAK,CAAC,IAAI,KAAK,iCAAiC,EAChD,CAAC;gBACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC;YAC9E,CAAC;YACD,0CAA0C;YAC1C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAChB,MAAc,EACd,MAAuB,EACvB,YAAqB;QAErB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,MAAM,gBAAgB,GAAG,YAAY;YACnC,CAAC,CAAC,kEAAkE;YACpE,CAAC,CAAC,0CAA0C,CAAC;QAE/C,MAAM,yBAAyB,GAA2B;YACxD,SAAS,EAAE,MAAM;YACjB,MAAM,EAAE,GAAG;SACZ,CAAC;QAEF,IAAI,YAAY,EAAE,CAAC;YACjB,yBAAyB,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAC;QACrD,CAAC;QAED,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACvB,IAAI,4BAAa,CAAC;YAChB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;YACxB,gBAAgB,EAAE,gBAAgB;YAClC,wBAAwB,EAAE;gBACxB,SAAS,EAAE,QAAQ;aACpB;YACD,yBAAyB,EAAE,yBAAyB;SACrD,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,SAAiB;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACtC,IAAI,2BAAY,CAAC;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,eAAe;YAC1B,sBAAsB,EAAE,mBAAmB;YAC3C,yBAAyB,EAAE;gBACzB,MAAM,EAAE,SAAS;aAClB;YACD,gBAAgB,EAAE,IAAI,EAAE,0BAA0B;SACnD,CAAC,CACH,CAAC;QAEF,OAAQ,MAAM,CAAC,KAAqB,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,MAAuB;QACvC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACtC,IAAI,2BAAY,CAAC;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,cAAc;YACzB,sBAAsB,EAAE,mBAAmB;YAC3C,wBAAwB,EAAE;gBACxB,SAAS,EAAE,QAAQ;aACpB;YACD,yBAAyB,EAAE;gBACzB,SAAS,EAAE,MAAM;aAClB;YACD,gBAAgB,EAAE,IAAI,EAAE,0BAA0B;SACnD,CAAC,CACH,CAAC;QAEF,OAAQ,MAAM,CAAC,KAAqB,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,WAAmB;QACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACtC,IAAI,2BAAY,CAAC;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,kBAAkB;YAC7B,sBAAsB,EAAE,uBAAuB;YAC/C,yBAAyB,EAAE;gBACzB,OAAO,EAAE,WAAW;aACrB;YACD,gBAAgB,EAAE,IAAI,EAAE,0BAA0B;SACnD,CAAC,CACH,CAAC;QAEF,OAAQ,MAAM,CAAC,KAAqB,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB;QACpB,gDAAgD;QAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACtC,IAAI,0BAAW,CAAC;YACd,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,oBAAoB,EAAE,uCAAuC;SAC9D,CAAC,CACH,CAAC;QAEF,MAAM,KAAK,GAAI,MAAM,CAAC,KAA0E,IAAI,EAAE,CAAC;QAEvG,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyE,CAAC;QAElG,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAClD,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACjB,IAAI,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;oBACzC,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;gBACvC,CAAC;gBACD,IAAI,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,eAAe,EAAE,CAAC;oBAC/C,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC;gBAC7C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE;oBAC/B,KAAK,EAAE,CAAC;oBACR,SAAS,EAAE,IAAI,CAAC,UAAU;oBAC1B,eAAe,EAAE,IAAI,CAAC,UAAU;iBACjC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,yDAAyD;QACzD,MAAM,MAAM,GAAuB,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC;gBACV,aAAa,EAAE,WAAW;gBAC1B,UAAU,EAAE,IAAI,CAAC,KAAK;gBACtB,UAAU,EAAE,IAAI,CAAC,SAAS;gBAC1B,iBAAiB,EAAE,IAAI,CAAC,eAAe;aACxC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAEhE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACvB,IAAI,4BAAa,CAAC;YAChB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;SACzB,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,iBAAiB,CAAC,WAAmB,CAAC,GAAG,EAAE,GAAG,IAAI;QACtD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1D,IAAI,OAAO,GAAG,QAAQ,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,YAAY,CACrB,IAAI,CAAC,OAAO,EACZ,OAAO,EACP,2BAA2B,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,sBAAsB,CAC5E,CAAC;gBACF,SAAS,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;CACF;AA9dD,gCA8dC"}
@@ -50,13 +50,15 @@ export declare class LogsCommand {
50
50
  * Get task detail
51
51
  * Per spec 10_REPL_UX.md: /logs <task-id> shows details (Layer 2)
52
52
  * Per spec 06_CORRECTNESS_PROPERTIES.md Property 25: --full for executor logs
53
+ * Per redesign: Shows visibility fields from TaskLogEntry
53
54
  *
54
55
  * @param projectPath - Project path
55
56
  * @param taskId - Task ID
56
57
  * @param full - Show full details (executor logs)
58
+ * @param sessionId - Session ID (optional, for getting TaskLogEntry with visibility fields)
57
59
  * @returns Logs result
58
60
  */
59
- getTaskDetail(projectPath: string, taskId: string, full?: boolean): Promise<LogsResult>;
61
+ getTaskDetail(projectPath: string, taskId: string, full?: boolean, sessionId?: string): Promise<LogsResult>;
60
62
  /**
61
63
  * Create a new task log
62
64
  * Called when starting a new task
@@ -1 +1 @@
1
- {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/repl/commands/logs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,WAAW,CAAc;IAEjC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAQxB;;;;;;;OAOG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAuB3E;;;;;;;;;OASG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAoCpG;;;;;;;;OAQG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBhG;;;;;;;;OAQG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC;IAyBtB;;;;;;;;OAQG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,OAAO,EAC3C,aAAa,GAAE,MAAM,EAAO,GAC3B,OAAO,CAAC,UAAU,CAAC;CAoBvB"}
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/repl/commands/logs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,WAAW,CAAc;IAEjC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAQxB;;;;;;;OAOG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAuB3E;;;;;;;;;;;OAWG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAwDxH;;;;;;;;OAQG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBhG;;;;;;;;OAQG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC;IAyBtB;;;;;;;;OAQG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,OAAO,EAC3C,aAAa,GAAE,MAAM,EAAO,GAC3B,OAAO,CAAC,UAAU,CAAC;CAoBvB"}
@@ -69,17 +69,37 @@ class LogsCommand {
69
69
  * Get task detail
70
70
  * Per spec 10_REPL_UX.md: /logs <task-id> shows details (Layer 2)
71
71
  * Per spec 06_CORRECTNESS_PROPERTIES.md Property 25: --full for executor logs
72
+ * Per redesign: Shows visibility fields from TaskLogEntry
72
73
  *
73
74
  * @param projectPath - Project path
74
75
  * @param taskId - Task ID
75
76
  * @param full - Show full details (executor logs)
77
+ * @param sessionId - Session ID (optional, for getting TaskLogEntry with visibility fields)
76
78
  * @returns Logs result
77
79
  */
78
- async getTaskDetail(projectPath, taskId, full = false) {
80
+ async getTaskDetail(projectPath, taskId, full = false, sessionId) {
79
81
  try {
80
82
  const manager = this.ensureLogManager(projectPath);
81
83
  const visibility = full ? 'full' : 'summary';
82
- const { log, events } = await manager.getTaskDetail(taskId, visibility);
84
+ // Try to get with session context if sessionId provided
85
+ let log;
86
+ let events;
87
+ let entry;
88
+ if (sessionId) {
89
+ // Use session-based methods for visibility fields
90
+ const result = await manager.getTaskDetailWithSession(taskId, sessionId, visibility);
91
+ log = result.log;
92
+ events = result.events;
93
+ // Get the TaskLogEntry for visibility fields
94
+ const index = await manager.getSessionIndex(sessionId);
95
+ entry = index.entries.find(e => e.task_id === taskId);
96
+ }
97
+ else {
98
+ // Fallback to legacy method
99
+ const result = await manager.getTaskDetail(taskId, visibility);
100
+ log = result.log;
101
+ events = result.events;
102
+ }
83
103
  if (!log) {
84
104
  return {
85
105
  success: false,
@@ -90,7 +110,7 @@ class LogsCommand {
90
110
  },
91
111
  };
92
112
  }
93
- const output = manager.formatTaskDetail(taskId, log, events, full);
113
+ const output = manager.formatTaskDetail(taskId, log, events, full, entry);
94
114
  return {
95
115
  success: true,
96
116
  message: 'Task detail retrieved',