@undefineds.co/linx 0.3.20 → 0.3.23

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 (99) hide show
  1. package/dist/generated/version.js +1 -1
  2. package/dist/index.js +6 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/auto-mode/pod-persistence.js +53 -3
  5. package/dist/lib/auto-mode/pod-persistence.js.map +1 -1
  6. package/dist/lib/auto-mode/secretary.js +2 -2
  7. package/dist/lib/auto-mode/secretary.js.map +1 -1
  8. package/dist/lib/chat-api.js +23 -61
  9. package/dist/lib/chat-api.js.map +1 -1
  10. package/dist/lib/codex-plugin/index.js +1 -0
  11. package/dist/lib/codex-plugin/index.js.map +1 -1
  12. package/dist/lib/codex-plugin/symphony-mcp.js +335 -0
  13. package/dist/lib/codex-plugin/symphony-mcp.js.map +1 -0
  14. package/dist/lib/linx-cloud-errors.js +0 -5
  15. package/dist/lib/linx-cloud-errors.js.map +1 -1
  16. package/dist/lib/linx-status-line.js +1 -8
  17. package/dist/lib/linx-status-line.js.map +1 -1
  18. package/dist/lib/linx-tui-contract.js +2 -1
  19. package/dist/lib/linx-tui-contract.js.map +1 -1
  20. package/dist/lib/models.js +3 -2
  21. package/dist/lib/models.js.map +1 -1
  22. package/dist/lib/pi-adapter/auth.js +68 -0
  23. package/dist/lib/pi-adapter/auth.js.map +1 -0
  24. package/dist/lib/pi-adapter/branding.js +67 -110
  25. package/dist/lib/pi-adapter/branding.js.map +1 -1
  26. package/dist/lib/pi-adapter/interactive.js +341 -101
  27. package/dist/lib/pi-adapter/interactive.js.map +1 -1
  28. package/dist/lib/pi-adapter/pod-mirror.js +38 -107
  29. package/dist/lib/pi-adapter/pod-mirror.js.map +1 -1
  30. package/dist/lib/pi-adapter/pod-native.js +2 -0
  31. package/dist/lib/pi-adapter/pod-native.js.map +1 -1
  32. package/dist/lib/pi-adapter/pod-tools.js +140 -0
  33. package/dist/lib/pi-adapter/pod-tools.js.map +1 -0
  34. package/dist/lib/pi-adapter/runtime.js +2 -12
  35. package/dist/lib/pi-adapter/runtime.js.map +1 -1
  36. package/dist/lib/pi-adapter/session.js +13 -17
  37. package/dist/lib/pi-adapter/session.js.map +1 -1
  38. package/dist/lib/pi-adapter/stream.js +2 -20
  39. package/dist/lib/pi-adapter/stream.js.map +1 -1
  40. package/dist/lib/pod-chat-store.js +53 -4
  41. package/dist/lib/pod-chat-store.js.map +1 -1
  42. package/dist/lib/resource-identity.js +2 -0
  43. package/dist/lib/resource-identity.js.map +1 -0
  44. package/dist/lib/status-line-command.js +2 -2
  45. package/dist/lib/status-line-command.js.map +1 -1
  46. package/dist/lib/symphony/archive.js +15 -37
  47. package/dist/lib/symphony/archive.js.map +1 -1
  48. package/dist/lib/symphony/pod-projection.js +189 -1346
  49. package/dist/lib/symphony/pod-projection.js.map +1 -1
  50. package/dist/lib/symphony-command.js +209 -109
  51. package/dist/lib/symphony-command.js.map +1 -1
  52. package/dist/plugins/linx-symphony-codex/.codex-plugin/plugin.json +38 -0
  53. package/dist/plugins/linx-symphony-codex/.mcp.json +10 -0
  54. package/dist/plugins/linx-symphony-codex/README.md +9 -0
  55. package/dist/plugins/linx-symphony-codex/hooks.json +60 -0
  56. package/dist/plugins/linx-symphony-codex/scripts/symphony-hook-events.mjs +119 -0
  57. package/dist/plugins/linx-symphony-codex/scripts/symphony-mcp.mjs +335 -0
  58. package/dist/plugins/linx-symphony-codex/skills/symphony/SKILL.md +791 -0
  59. package/dist/skills/symphony/SKILL.md +7 -0
  60. package/dist/skills/xpod-cli/SKILL.md +2 -13
  61. package/package.json +4 -4
  62. package/vendor/agent-runtime/dist/chat-reconciler.d.ts +33 -0
  63. package/vendor/agent-runtime/dist/chat-reconciler.js +108 -0
  64. package/vendor/agent-runtime/dist/index.d.ts +4 -1
  65. package/vendor/agent-runtime/dist/index.js +4 -1
  66. package/vendor/agent-runtime/dist/matrix-client.d.ts +149 -0
  67. package/vendor/agent-runtime/dist/matrix-client.js +220 -0
  68. package/vendor/agent-runtime/dist/pod-resource-identity.d.ts +17 -0
  69. package/vendor/agent-runtime/dist/pod-resource-identity.js +54 -0
  70. package/vendor/agent-runtime/dist/reconciler.d.ts +0 -11
  71. package/vendor/agent-runtime/dist/reconciler.js +5 -43
  72. package/vendor/agent-runtime/dist/symphony.d.ts +272 -27
  73. package/vendor/agent-runtime/dist/symphony.js +1268 -21
  74. package/vendor/agent-runtime/dist/workspace.d.ts +61 -0
  75. package/vendor/agent-runtime/dist/workspace.js +81 -0
  76. package/vendor/agent-runtime/package.json +5 -1
  77. package/vendor/stores/dist/current-pod-base.d.ts +2 -0
  78. package/vendor/stores/dist/current-pod-base.js +14 -0
  79. package/vendor/stores/dist/exact-records.d.ts +7 -0
  80. package/vendor/stores/dist/exact-records.js +87 -0
  81. package/vendor/stores/dist/index.d.ts +1 -0
  82. package/vendor/stores/dist/index.js +1 -0
  83. package/vendor/stores/dist/login.d.ts +51 -0
  84. package/vendor/stores/dist/login.js +195 -0
  85. package/vendor/stores/dist/pod-collection.d.ts +28 -0
  86. package/vendor/stores/dist/pod-collection.js +194 -0
  87. package/vendor/stores/dist/pod-write-guard.d.ts +5 -0
  88. package/vendor/stores/dist/pod-write-guard.js +133 -0
  89. package/vendor/stores/dist/symphony-control.d.ts +245 -0
  90. package/vendor/stores/dist/symphony-control.js +2175 -0
  91. package/vendor/stores/package.json +14 -0
  92. package/dist/lib/capture/persistence.js +0 -377
  93. package/dist/lib/capture/persistence.js.map +0 -1
  94. package/dist/lib/capture/tool.js +0 -242
  95. package/dist/lib/capture/tool.js.map +0 -1
  96. package/dist/skills/basic/SKILL.md +0 -46
  97. package/dist/skills/capture/SKILL.md +0 -165
  98. package/vendor/agent-runtime/dist/coordination.d.ts +0 -93
  99. package/vendor/agent-runtime/dist/coordination.js +0 -145
@@ -0,0 +1,54 @@
1
+ const ABSOLUTE_IRI = /^[a-zA-Z][a-zA-Z\d+.-]*:/;
2
+ const AGENT_RESOURCE_ID = /^([A-Za-z0-9_.-]+)\/$/;
3
+ const AGENT_KEY = /^[A-Za-z0-9_.-]+$/;
4
+ export function asBaseRelativeResourceId(value, label = 'Resource id') {
5
+ if (typeof value !== 'string' || value.trim().length === 0) {
6
+ throw new Error(`${label} must be a non-empty base-relative resource id.`);
7
+ }
8
+ const normalized = value.trim();
9
+ if (ABSOLUTE_IRI.test(normalized) || normalized.startsWith('/') || normalized.startsWith('//')) {
10
+ throw new Error(`${label} must be a base-relative resource id.`);
11
+ }
12
+ return normalized;
13
+ }
14
+ export function asResourceIri(value, label = 'Resource IRI') {
15
+ if (typeof value !== 'string' || value.trim().length === 0) {
16
+ throw new Error(`${label} must be a non-empty resource IRI.`);
17
+ }
18
+ const normalized = value.trim();
19
+ if (!ABSOLUTE_IRI.test(normalized)) {
20
+ throw new Error(`${label} must be a full resource IRI.`);
21
+ }
22
+ return normalized;
23
+ }
24
+ export function requireRowResourceId(row, label = 'Pod row') {
25
+ if (!row || typeof row.id !== 'string' || row.id.trim().length === 0) {
26
+ throw new Error(`${label} row is missing row.id.`);
27
+ }
28
+ return asBaseRelativeResourceId(row.id, `${label} row.id`);
29
+ }
30
+ function defaultAgentKey() {
31
+ return `agent_${Math.random().toString(36).slice(2, 12)}`;
32
+ }
33
+ export function agentResourceId(key) {
34
+ const raw = typeof key === 'string' ? key.trim() : '';
35
+ const value = raw || defaultAgentKey();
36
+ if (AGENT_RESOURCE_ID.test(value)) {
37
+ return asBaseRelativeResourceId(value, 'Agent resource id');
38
+ }
39
+ if (!AGENT_KEY.test(value)) {
40
+ throw new Error('Agent key must use letters, numbers, dot, underscore, or dash.');
41
+ }
42
+ return asBaseRelativeResourceId(`${value}/`, 'Agent resource id');
43
+ }
44
+ export function agentKeyFromResourceId(resourceId) {
45
+ const id = asBaseRelativeResourceId(resourceId, 'Agent resource id');
46
+ const match = id.match(AGENT_RESOURCE_ID);
47
+ if (!match?.[1]) {
48
+ throw new Error('Agent resource id must use {agentKey}/.');
49
+ }
50
+ return match[1];
51
+ }
52
+ export function agentHomeDirFromResourceId(resourceId) {
53
+ return asBaseRelativeResourceId(agentResourceId(agentKeyFromResourceId(resourceId)), 'Agent home dir');
54
+ }
@@ -1,5 +1,4 @@
1
1
  import type { AgentParticipantRole } from './turn-controller.js';
2
- import { type ClientReconcilerLease, type ReconcilerOwner } from './coordination.js';
3
2
  export type ThreadPolicyKind = 'direct' | 'auto' | 'symphony' | 'open_group' | 'review';
4
3
  export type ThreadKind = 'main' | 'control' | 'worker' | 'review' | 'schedule' | 'schedule_run';
5
4
  export type ReconcilerEventType = 'message.appended' | 'input.required' | 'approval.required' | 'inbox.notification.created' | 'inbox.notification.updated' | 'delivery.submitted' | 'delivery.completed' | 'delivery.failed' | 'schedule.tick' | 'worker.blocked' | 'change.requested' | 'issue.updated' | 'task.updated' | 'run.updated' | (string & {});
@@ -63,9 +62,6 @@ export interface ThreadControlEvent<TData extends Record<string, unknown> = Reco
63
62
  }
64
63
  export interface ThreadPolicy {
65
64
  kind: ThreadPolicyKind;
66
- reconcilerOwner?: ReconcilerOwner;
67
- humanAuthorities?: string[];
68
- humanAuthorityCount?: number;
69
65
  secretaryAgent?: string;
70
66
  defaultAssistantAgent?: string;
71
67
  assignedWorkerAgent?: string;
@@ -118,7 +114,6 @@ export interface ReconcilerNotificationEvent {
118
114
  export interface ReconcileDecision {
119
115
  id: string;
120
116
  policyKind: ThreadPolicyKind;
121
- reconcilerOwner: ReconcilerOwner;
122
117
  event: ThreadControlEvent;
123
118
  placement: ThreadPlacement;
124
119
  wakeJobs: WakeJob[];
@@ -145,7 +140,6 @@ export interface WakeJobSummary {
145
140
  export interface ReconcileDecisionSummary {
146
141
  id: string;
147
142
  policyKind: ThreadPolicyKind;
148
- reconcilerOwner: ReconcilerOwner;
149
143
  eventType: ReconcilerEventType;
150
144
  thread: string;
151
145
  chat?: string;
@@ -157,11 +151,6 @@ export interface ReconcileDecisionSummary {
157
151
  export interface ReconcileThreadEventInput {
158
152
  policy: ThreadPolicyKind | ThreadPolicy;
159
153
  event: ThreadControlEvent;
160
- reconcilerOwner?: ReconcilerOwner;
161
- humanAuthorities?: string[];
162
- humanAuthorityCount?: number;
163
- clientReconcilerLease?: ClientReconcilerLease | null;
164
- requireClientReconcilerLease?: boolean;
165
154
  chat?: string;
166
155
  thread?: string;
167
156
  now?: Date;
@@ -1,4 +1,3 @@
1
- import { canClientCoordinateThread, resolveReconcilerOwnership, } from './coordination.js';
2
1
  const DEFAULT_SECRETARY_AGENT = '__secretary__';
3
2
  const DEFAULT_ASSISTANT_AGENT = 'primary-agent';
4
3
  const DEFAULT_REVIEWER_AGENT = 'ai-reviewer';
@@ -25,27 +24,12 @@ export function reconcileThreadEvent(input) {
25
24
  thread: input.thread,
26
25
  randomId: input.randomId,
27
26
  });
28
- const ownership = resolveReconcilerOwnership({
29
- policyKind: policy.kind,
30
- humanAuthorities: input.humanAuthorities ?? policy.humanAuthorities,
31
- humanAuthorityCount: input.humanAuthorityCount ?? policy.humanAuthorityCount,
32
- reconcilerOwner: input.reconcilerOwner ?? policy.reconcilerOwner,
33
- });
34
- const clientCoordinationSkip = resolveClientCoordinationSkip({
35
- ownership,
36
- input,
37
- placement,
38
- createdAt,
39
- });
40
- const jobs = clientCoordinationSkip
41
- ? []
42
- : selectWakeJobs(policy, event, placement, createdAt, input.randomId, input.client);
27
+ const jobs = selectWakeJobs(policy, event, placement, createdAt, input.randomId, input.client);
43
28
  const notificationEvents = selectNotificationEvents(event, placement, createdAt, input.randomId);
44
- const skippedReason = clientCoordinationSkip ?? (jobs.length === 0 ? skipReasonFor(policy, event, input.client) : undefined);
29
+ const skippedReason = jobs.length === 0 ? skipReasonFor(policy, event, input.client) : undefined;
45
30
  return {
46
31
  id: createReconcilerId('decision', input.randomId),
47
32
  policyKind: policy.kind,
48
- reconcilerOwner: ownership.reconcilerOwner,
49
33
  event,
50
34
  placement,
51
35
  wakeJobs: jobs,
@@ -58,7 +42,6 @@ export function summarizeReconcileDecision(decision) {
58
42
  return {
59
43
  id: decision.id,
60
44
  policyKind: decision.policyKind,
61
- reconcilerOwner: decision.reconcilerOwner,
62
45
  eventType: decision.event.type,
63
46
  thread: decision.placement.thread,
64
47
  ...(decision.placement.chat ? { chat: decision.placement.chat } : {}),
@@ -137,27 +120,6 @@ export function resolveThreadPlacement(input) {
137
120
  kind: 'control',
138
121
  };
139
122
  }
140
- function resolveClientCoordinationSkip(input) {
141
- if (input.ownership.reconcilerOwner !== 'client') {
142
- return undefined;
143
- }
144
- if (!input.input.requireClientReconcilerLease && !input.input.clientReconcilerLease) {
145
- return undefined;
146
- }
147
- const clientId = input.input.client?.id;
148
- if (canClientCoordinateThread({
149
- clientId,
150
- thread: input.placement.thread,
151
- lease: input.input.clientReconcilerLease,
152
- now: input.createdAt,
153
- })) {
154
- return undefined;
155
- }
156
- const owner = input.input.clientReconcilerLease?.ownerClientId;
157
- return owner
158
- ? `Client-owned Reconciler is leased by ${owner}; client ${clientId ?? 'unknown'} must not reconcile ${input.placement.thread}.`
159
- : `Client-owned Reconciler requires an active client coordinator lease for ${input.placement.thread}.`;
160
- }
161
123
  function selectWakeJobs(policy, event, placement, createdAt, randomId, client) {
162
124
  if (policy.kind === 'direct') {
163
125
  return isUserMessage(event)
@@ -165,7 +127,7 @@ function selectWakeJobs(policy, event, placement, createdAt, randomId, client) {
165
127
  targetAgent: policy.defaultAssistantAgent ?? DEFAULT_ASSISTANT_AGENT,
166
128
  targetRole: 'primary-agent',
167
129
  priority: 'normal',
168
- reason: 'Single-human assistant surfaces route user messages to the default assistant.',
130
+ reason: 'Direct thread routes user messages to the default assistant.',
169
131
  createdAt,
170
132
  randomId,
171
133
  })]
@@ -211,10 +173,10 @@ function selectWakeJobs(policy, event, placement, createdAt, randomId, client) {
211
173
  return [createSecretaryWakeJob(policy, event, placement, 'Symphony Delivery submissions wake Secretary for review or routing.', 'normal', createdAt, randomId)];
212
174
  }
213
175
  if (event.type === 'delivery.completed') {
214
- return [createSecretaryWakeJob(policy, event, placement, 'Symphony completion Delivery wakes Secretary for quality, acceptance, and follow-up extraction reconciliation.', 'high', createdAt, randomId)];
176
+ return [createSecretaryWakeJob(policy, event, placement, 'Symphony completion Delivery wakes Secretary for quality and acceptance reconciliation.', 'high', createdAt, randomId)];
215
177
  }
216
178
  if (event.type === 'delivery.failed') {
217
- return [createSecretaryWakeJob(policy, event, placement, 'Symphony failed Delivery wakes Secretary for feasibility, retry, scope change, or follow-up extraction reconciliation.', 'high', createdAt, randomId)];
179
+ return [createSecretaryWakeJob(policy, event, placement, 'Symphony failed Delivery wakes Secretary for feasibility, retry, or scope change reconciliation.', 'high', createdAt, randomId)];
218
180
  }
219
181
  if (event.type === 'issue.updated' || event.type === 'task.updated' || event.type === 'run.updated') {
220
182
  return [createSecretaryWakeJob(policy, event, placement, 'Symphony state changes wake Secretary to reconcile system state.', 'normal', createdAt, randomId)];
@@ -1,44 +1,79 @@
1
1
  import type { AutoModeMode, AutoModeWorkerBackend } from './auto-mode.js';
2
- import { type ReconcileDecision, type ReconcileDecisionSummary } from './reconciler.js';
2
+ import { type ReconcileDecision, type ReconcileDecisionSummary, type ReconcilerActorRef, type ReconcilerClientContext, type ReconcilerEventType, type ReconcilerNotificationEvent, type ThreadPolicy, type ThreadPolicyKind, type WakeJobSummary } from './reconciler.js';
3
+ import type { AgentWorkspace, AgentWorkspaceEnvironment, AgentWorkspaceKind } from './workspace.js';
3
4
  export declare const SYMPHONY_HOME_DIRNAME = "symphony";
4
5
  export declare const SYMPHONY_IDEAS_DIRNAME = "ideas";
5
6
  export declare const SYMPHONY_ISSUES_DIRNAME = "issues";
6
7
  export declare const SYMPHONY_TASKS_DIRNAME = "tasks";
7
8
  export declare const SYMPHONY_DELIVERIES_DIRNAME = "deliveries";
8
9
  export declare const SYMPHONY_SESSIONS_DIRNAME = "sessions";
10
+ export declare const SYMPHONY_RUN_STEPS_DIRNAME = "run-steps";
9
11
  export declare const SYMPHONY_IDEA_FILE_NAME = "idea.json";
10
12
  export declare const SYMPHONY_ISSUE_FILE_NAME = "issue.json";
11
13
  export declare const SYMPHONY_TASK_FILE_NAME = "task.json";
12
14
  export declare const SYMPHONY_DELIVERY_FILE_NAME = "delivery.json";
13
15
  export declare const SYMPHONY_SESSION_FILE_NAME = "session.json";
14
- export type WorkerWorkspaceKind = 'git' | 'folder';
16
+ export declare const SYMPHONY_RUN_STEP_FILE_NAME = "run-step.json";
17
+ export type WorkerWorkspaceKind = AgentWorkspaceKind;
15
18
  export type SymphonyIdeaStatus = 'captured' | 'exploring' | 'candidate' | 'promoted' | 'deferred' | 'rejected' | 'superseded';
16
19
  export type SymphonyIdeaCommitment = 'thought' | 'direction' | 'tentative_decision' | 'committed';
17
20
  export type SymphonyIssueStatus = 'open' | 'triaging' | 'in_progress' | 'blocked' | 'resolved' | 'closed';
18
- export type SymphonyTaskStatus = 'pending' | 'running' | 'completed' | 'failed';
21
+ export type SymphonyTaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'blocked';
19
22
  export type SymphonyDeliveryStatus = 'pending' | 'dispatched' | 'completed' | 'failed';
20
23
  export type SymphonySessionStatus = 'planned' | 'running' | 'completed' | 'failed';
21
24
  export type SymphonyProjectionRole = 'user' | 'system' | 'tool';
22
- export type SymphonyResourceKind = 'idea' | 'issue' | 'task' | 'delivery' | 'session';
25
+ export type SymphonyResourceKind = 'idea' | 'issue' | 'task' | 'delivery' | 'session' | 'runStep';
26
+ export type SymphonyRuntimeEventType = 'session.started' | 'session.resumed' | 'run.started' | 'run.step' | 'approval.required' | 'input.required' | 'worker.blocked' | 'delivery.submitted' | 'delivery.completed' | 'delivery.failed' | 'run.completed' | 'run.failed';
27
+ export type SymphonyFollowUpCandidateKind = 'new_defect' | 'missing_shared_abstraction' | 'app_local_glue' | 'models_gap' | 'orm_gap' | 'runtime_api_gap' | 'shared_runtime_utility' | 'test_harness' | 'live_verification_gap' | 'documentation' | 'cleanup' | 'other';
28
+ export type SymphonyFollowUpDisposition = 'same_issue_task' | 'new_issue' | 'idea' | 'evidence_only' | 'ask_user';
29
+ export type SymphonyAcceptanceOutcome = 'accepted' | 'rejected' | 'blocked' | 'follow_up';
30
+ export type SymphonyRecordSource = 'cli' | 'web' | 'service' | 'tui' | 'mcp' | 'runtime' | 'control-plane';
23
31
  export interface SymphonyReconcilerState {
24
32
  decisions: ReconcileDecisionSummary[];
25
33
  }
26
- export interface WorkerWorkspaceRef {
27
- path: string;
28
- kind: WorkerWorkspaceKind;
29
- repository?: string;
30
- branch?: string;
31
- worktree?: string;
32
- workspace?: string;
33
- baseRevision?: string;
34
- environment?: SymphonyWorkerEnvironmentRef;
35
- }
36
- export interface SymphonyWorkerEnvironmentRef {
37
- kind: 'local-shell' | 'remote-container' | 'cloud-runner' | 'backend-runtime' | 'unknown';
34
+ export type SymphonyThreadReconcilerNextAction = 'noop' | 'wake_secretary' | 'wake_worker' | 'wake_reviewer' | 'notify_user';
35
+ export interface SymphonyThreadReconcileEventInput {
38
36
  id?: string;
39
- label?: string;
40
- runtime?: AutoModeWorkerBackend | string;
37
+ type?: ReconcilerEventType;
38
+ eventType?: ReconcilerEventType;
39
+ chat?: string;
40
+ thread?: string;
41
+ resource?: string;
42
+ actor?: ReconcilerActorRef;
43
+ content?: string;
44
+ message?: string;
45
+ createdAt?: string;
46
+ data?: Record<string, unknown>;
47
+ symphonyHookEvent?: boolean;
48
+ hookEventName?: string;
49
+ sessionId?: string;
50
+ source?: string;
51
+ [key: string]: unknown;
52
+ }
53
+ export interface ReconcileSymphonyThreadEventsInput {
54
+ policy?: ThreadPolicyKind | ThreadPolicy;
55
+ chat?: string;
56
+ thread?: string;
57
+ randomId?: string;
58
+ now?: Date | string;
59
+ client?: ReconcilerClientContext;
60
+ events?: SymphonyThreadReconcileEventInput[];
61
+ }
62
+ export interface ReconcileSymphonyThreadEventsResult {
63
+ policyKind: ThreadPolicyKind;
64
+ chat?: string;
65
+ thread: string;
66
+ eventCount: number;
67
+ decisions: ReconcileDecisionSummary[];
68
+ wakeJobs: WakeJobSummary[];
69
+ notificationEvents: ReconcilerNotificationEvent[];
70
+ nextAction: SymphonyThreadReconcilerNextAction;
71
+ summary: string;
41
72
  }
73
+ export type WorkerWorkspace = AgentWorkspace & {
74
+ path: string;
75
+ };
76
+ export type WorkerEnvironment = AgentWorkspaceEnvironment;
42
77
  export interface SymphonySupervisorPolicy {
43
78
  strategy: 'interval';
44
79
  intervalMs: number;
@@ -59,7 +94,6 @@ export type SymphonyDelegationTargetSource = 'active-session' | 'group-chat' | '
59
94
  export interface SymphonyDelegationTarget extends SymphonyChatThreadRef {
60
95
  source: SymphonyDelegationTargetSource;
61
96
  backend: AutoModeWorkerBackend;
62
- contact?: string;
63
97
  agent?: string;
64
98
  label?: string;
65
99
  }
@@ -69,7 +103,7 @@ export interface SymphonyIdeaRecord extends SymphonyChatThreadRef {
69
103
  input?: string;
70
104
  status: SymphonyIdeaStatus;
71
105
  commitment: SymphonyIdeaCommitment;
72
- source: 'cli';
106
+ source: SymphonyRecordSource;
73
107
  affectedArea?: string;
74
108
  currentUnderstanding?: string;
75
109
  openQuestions: string[];
@@ -86,8 +120,10 @@ export interface SymphonyIssueRecord extends SymphonyChatThreadRef {
86
120
  description?: string;
87
121
  status: SymphonyIssueStatus;
88
122
  priority: 'low' | 'medium' | 'high' | 'urgent';
89
- source: 'cli';
123
+ source: SymphonyRecordSource;
90
124
  issuer: SymphonyIssuerRef;
125
+ parentIssue?: string;
126
+ labels?: string[];
91
127
  tasks: string[];
92
128
  deliveries: string[];
93
129
  sessions: string[];
@@ -105,10 +141,10 @@ export interface SymphonyTaskRecord extends SymphonyChatThreadRef {
105
141
  status: SymphonyTaskStatus;
106
142
  target: SymphonyDelegationTarget;
107
143
  backend: AutoModeWorkerBackend;
108
- contact?: string;
109
144
  agent?: string;
110
145
  delivery: string;
111
146
  session: string;
147
+ acceptanceReview?: SymphonyAcceptanceReview;
112
148
  reconciler?: SymphonyReconcilerState;
113
149
  createdAt: string;
114
150
  updatedAt: string;
@@ -131,6 +167,7 @@ export interface SymphonyDeliveryRecord extends SymphonyChatThreadRef {
131
167
  };
132
168
  session?: string;
133
169
  autoModeSessionId?: string;
170
+ acceptanceReview?: SymphonyAcceptanceReview;
134
171
  reconciler?: SymphonyReconcilerState;
135
172
  createdAt: string;
136
173
  updatedAt: string;
@@ -147,13 +184,14 @@ export interface SymphonySessionRecord extends SymphonyChatThreadRef {
147
184
  secretaryAutoEnabled?: boolean;
148
185
  status: SymphonySessionStatus;
149
186
  cwd: string;
150
- workspaceRef?: WorkerWorkspaceRef;
187
+ workspace?: WorkerWorkspace;
151
188
  target: SymphonyDelegationTarget;
152
189
  model?: string;
153
190
  supervisor?: SymphonySupervisorPolicy;
154
191
  autoModeSessionId?: string;
155
192
  dryRun?: boolean;
156
193
  exitCode?: number | null;
194
+ acceptanceReview?: SymphonyAcceptanceReview;
157
195
  reconciler?: SymphonyReconcilerState;
158
196
  createdAt: string;
159
197
  updatedAt: string;
@@ -167,12 +205,25 @@ export interface SymphonyRunPlan {
167
205
  delivery: SymphonyDeliveryRecord;
168
206
  session: SymphonySessionRecord;
169
207
  workers: SymphonyWorkerPlan[];
208
+ followUpIssues?: SymphonyIssueRecord[];
170
209
  }
171
210
  export interface SymphonyWorkerPlan {
172
211
  task: string;
173
212
  taskRecord: SymphonyTaskRecord;
174
213
  delivery: SymphonyDeliveryRecord;
175
214
  session: SymphonySessionRecord;
215
+ runSteps?: SymphonyRunStepRecord[];
216
+ }
217
+ export interface SymphonyRunStepRecord {
218
+ uri: string;
219
+ issue: string;
220
+ task: string;
221
+ delivery: string;
222
+ session: string;
223
+ stepType: SymphonyRuntimeEventType;
224
+ message: string;
225
+ payload?: Record<string, unknown>;
226
+ createdAt: string;
176
227
  }
177
228
  export interface SymphonyWorkerSpec extends Partial<SymphonyDelegationTarget> {
178
229
  title?: string;
@@ -180,10 +231,172 @@ export interface SymphonyWorkerSpec extends Partial<SymphonyDelegationTarget> {
180
231
  acceptanceCriteria?: string[];
181
232
  model?: string;
182
233
  supervisorIntervalMs?: number;
183
- workspace?: Partial<WorkerWorkspaceRef>;
234
+ workspace?: Partial<WorkerWorkspace>;
235
+ }
236
+ export interface SymphonyFollowUpCandidate {
237
+ kind: SymphonyFollowUpCandidateKind;
238
+ summary: string;
239
+ evidence?: string[];
240
+ suggestedDisposition?: SymphonyFollowUpDisposition;
241
+ reason?: string;
242
+ requiredBeforeAcceptance?: boolean;
243
+ userDecisionRequired?: boolean;
244
+ targetPackage?: string;
245
+ }
246
+ export interface SymphonyClassifiedFollowUp extends SymphonyFollowUpCandidate {
247
+ disposition: SymphonyFollowUpDisposition;
248
+ reason: string;
249
+ source: 'worker_report' | 'secretary_inference';
250
+ issue?: string;
251
+ }
252
+ export interface SymphonyReusableExtractionDecision {
253
+ disposition: SymphonyFollowUpDisposition;
254
+ reason: string;
255
+ candidates: SymphonyClassifiedFollowUp[];
256
+ }
257
+ export interface SymphonyImplementationChangeRequest {
258
+ trigger: 'worker_failed' | 'acceptance_blocked';
259
+ task: string;
260
+ delivery: string;
261
+ session: string;
262
+ summary: string;
263
+ failedAssumption: string;
264
+ evidence: string[];
265
+ risks: string[];
266
+ recommendedNextShape: 'retry' | 'split' | 'redesign' | 'defer' | 'reduce_scope' | 'request_authority';
267
+ basedOnRunSteps: string[];
268
+ createdAt: string;
269
+ }
270
+ export interface SymphonyFinalReportEnvelope {
271
+ summary?: string;
272
+ evidence?: string[];
273
+ risks?: string[];
274
+ changedFiles?: string[];
275
+ commands?: string[];
276
+ followUps?: SymphonyFollowUpCandidate[];
277
+ }
278
+ export interface SymphonyRuntimeDeliveryEvent {
279
+ stepType: SymphonyRuntimeEventType;
280
+ message?: string;
281
+ payload?: Record<string, unknown>;
282
+ createdAt?: string;
283
+ randomId?: string;
284
+ }
285
+ export interface SymphonyRuntimeDeliveryResult {
286
+ status: 'completed' | 'failed';
287
+ exitCode: number;
288
+ autoModeSessionId?: string;
289
+ reportText?: string;
290
+ events: SymphonyRuntimeDeliveryEvent[];
291
+ }
292
+ export interface SymphonyAcceptanceReview {
293
+ outcome: SymphonyAcceptanceOutcome;
294
+ accepted: boolean;
295
+ reviewedBy: '__secretary__';
296
+ reviewedAt: string;
297
+ summary: string;
298
+ evidence: string[];
299
+ risks: string[];
300
+ changedFiles: string[];
301
+ commands: string[];
302
+ followUps: SymphonyClassifiedFollowUp[];
303
+ reusableExtraction: SymphonyReusableExtractionDecision;
304
+ implementationChangeRequest?: SymphonyImplementationChangeRequest;
305
+ }
306
+ export interface ReconcileSymphonyWorkerDeliveryInput {
307
+ issue: SymphonyIssueRecord;
308
+ worker: SymphonyWorkerPlan;
309
+ status: 'completed' | 'failed';
310
+ exitCode: number;
311
+ autoModeSessionId?: string;
312
+ reportText?: string;
313
+ now?: Date;
314
+ randomId?: string;
315
+ }
316
+ export interface ReconcileSymphonyWorkerDeliveryResult {
317
+ worker: SymphonyWorkerPlan;
318
+ acceptanceReview: SymphonyAcceptanceReview;
319
+ followUpIssues: SymphonyIssueRecord[];
320
+ }
321
+ export interface StartSymphonyWorkerRunInput {
322
+ worker: SymphonyWorkerPlan;
323
+ decision?: ReconcileDecision | ReconcileDecisionSummary;
324
+ now?: Date;
325
+ randomId?: string;
326
+ message?: string;
327
+ payload?: Record<string, unknown>;
328
+ }
329
+ export interface RecordSymphonyWorkerRuntimeEventInput {
330
+ worker: SymphonyWorkerPlan;
331
+ stepType: SymphonyRuntimeEventType;
332
+ message?: string;
333
+ payload?: Record<string, unknown>;
334
+ now?: Date;
335
+ randomId?: string;
336
+ }
337
+ export interface CompleteSymphonyWorkerRunInput {
338
+ issue: SymphonyIssueRecord;
339
+ worker: SymphonyWorkerPlan;
340
+ status: 'completed' | 'failed';
341
+ exitCode: number;
342
+ autoModeSessionId?: string;
343
+ reportText?: string;
344
+ decision?: ReconcileDecision | ReconcileDecisionSummary;
345
+ now?: Date;
346
+ randomId?: string;
347
+ }
348
+ export interface CreateSymphonyRunStepInput {
349
+ worker: SymphonyWorkerPlan;
350
+ stepType: SymphonyRuntimeEventType;
351
+ message?: string;
352
+ payload?: Record<string, unknown>;
353
+ now?: Date;
354
+ randomId?: string;
355
+ }
356
+ export interface SymphonyIssueStatusUpdates {
357
+ error?: string;
358
+ closedAt?: string;
359
+ now?: Date | string;
360
+ }
361
+ export interface SymphonyTaskStatusUpdates {
362
+ error?: string;
363
+ completedAt?: string;
364
+ now?: Date | string;
365
+ }
366
+ export interface SymphonyDeliveryStatusUpdates {
367
+ error?: string;
368
+ autoModeSessionId?: string;
369
+ completedAt?: string;
370
+ now?: Date | string;
371
+ }
372
+ export interface SymphonySessionStatusUpdates {
373
+ error?: string;
374
+ autoModeSessionId?: string;
375
+ exitCode?: number | null;
376
+ dryRun?: boolean;
377
+ completedAt?: string;
378
+ now?: Date | string;
379
+ }
380
+ export interface FinalizeSymphonyRunPlanAfterWorkersInput {
381
+ plan: SymphonyRunPlan;
382
+ workers?: SymphonyWorkerPlan[];
383
+ followUpIssues?: SymphonyIssueRecord[];
384
+ now?: Date | string;
385
+ }
386
+ export interface FinalizeSymphonyRunPlanAfterWorkersResult {
387
+ plan: SymphonyRunPlan;
388
+ status: 'completed' | 'failed';
389
+ issueStatus: 'resolved' | 'blocked';
390
+ blocker?: {
391
+ kind: 'worker_failure' | 'acceptance';
392
+ error: string;
393
+ exitCode?: number;
394
+ worker: SymphonyWorkerPlan;
395
+ };
184
396
  }
185
397
  export interface CreateSymphonyRunPlanInput {
186
398
  objective: string;
399
+ source?: SymphonyRecordSource;
187
400
  title?: string;
188
401
  acceptanceCriteria?: string[];
189
402
  workspacePath: string;
@@ -191,9 +404,9 @@ export interface CreateSymphonyRunPlanInput {
191
404
  repository?: string;
192
405
  branch?: string;
193
406
  worktree?: string;
194
- workspace?: string;
407
+ container?: string;
195
408
  baseRevision?: string;
196
- environment?: Partial<SymphonyWorkerEnvironmentRef>;
409
+ environment?: Partial<WorkerEnvironment>;
197
410
  backend: AutoModeWorkerBackend;
198
411
  mode: AutoModeMode;
199
412
  secretaryAutoEnabled?: boolean;
@@ -229,6 +442,10 @@ export declare function createSymphonySessionUri(options?: {
229
442
  now?: Date;
230
443
  randomId?: string;
231
444
  }): string;
445
+ export declare function createSymphonyRunStepUri(options?: {
446
+ now?: Date;
447
+ randomId?: string;
448
+ }): string;
232
449
  export declare function getSymphonyArchiveRelativePaths(uri: string, kind: SymphonyResourceKind): {
233
450
  dir: string;
234
451
  file: string;
@@ -237,12 +454,40 @@ export declare function createRunPlan(input: CreateSymphonyRunPlanInput): Sympho
237
454
  export declare function appendSymphonyReconcilerDecision<T extends {
238
455
  reconciler?: SymphonyReconcilerState;
239
456
  }>(record: T, decision: ReconcileDecision | ReconcileDecisionSummary): T;
457
+ export declare function reconcileSymphonyThreadEvents(input: ReconcileSymphonyThreadEventsInput): ReconcileSymphonyThreadEventsResult;
458
+ export declare function withSymphonyIssueStatus(record: SymphonyIssueRecord, status: SymphonyIssueStatus, updates?: SymphonyIssueStatusUpdates): SymphonyIssueRecord;
459
+ export declare function withSymphonyTaskStatus(record: SymphonyTaskRecord, status: SymphonyTaskStatus, updates?: SymphonyTaskStatusUpdates): SymphonyTaskRecord;
460
+ export declare function withSymphonyDeliveryStatus(record: SymphonyDeliveryRecord, status: SymphonyDeliveryStatus, updates?: SymphonyDeliveryStatusUpdates): SymphonyDeliveryRecord;
461
+ export declare function withSymphonySessionStatus(record: SymphonySessionRecord, status: SymphonySessionStatus, updates?: SymphonySessionStatusUpdates): SymphonySessionRecord;
462
+ export declare function withSymphonyRunPlanPrimaryWorker(plan: SymphonyRunPlan): SymphonyRunPlan;
463
+ export declare function withSymphonyRunPlanWorker(plan: SymphonyRunPlan, worker: SymphonyWorkerPlan): SymphonyRunPlan;
464
+ export declare function createSymphonyRunStepRecord(input: CreateSymphonyRunStepInput): SymphonyRunStepRecord;
465
+ export declare function withSymphonyWorkerRunStep(worker: SymphonyWorkerPlan, step: SymphonyRunStepRecord): SymphonyWorkerPlan;
466
+ export declare function withSymphonyWorkerRuntimeStep(worker: SymphonyWorkerPlan, input: Omit<CreateSymphonyRunStepInput, 'worker'>): SymphonyWorkerPlan;
467
+ export declare function startSymphonyWorkerRun(input: StartSymphonyWorkerRunInput): SymphonyWorkerPlan;
468
+ export declare function recordSymphonyWorkerRuntimeEvent(input: RecordSymphonyWorkerRuntimeEventInput): SymphonyWorkerPlan;
469
+ export declare function completeSymphonyWorkerRun(input: CompleteSymphonyWorkerRunInput): ReconcileSymphonyWorkerDeliveryResult;
470
+ export declare function finalizeSymphonyRunPlanAfterWorkers(input: FinalizeSymphonyRunPlanAfterWorkersInput): FinalizeSymphonyRunPlanAfterWorkersResult;
471
+ export declare function summarizeSymphonyAcceptanceBlocker(review: SymphonyAcceptanceReview): string;
472
+ export declare function reconcileSymphonyWorkerDelivery(input: ReconcileSymphonyWorkerDeliveryInput): ReconcileSymphonyWorkerDeliveryResult;
473
+ export declare function createSymphonyAcceptanceReview(input: {
474
+ issue: SymphonyIssueRecord;
475
+ worker: SymphonyWorkerPlan;
476
+ status: 'completed' | 'failed';
477
+ exitCode: number;
478
+ reportText?: string;
479
+ now?: Date;
480
+ }): SymphonyAcceptanceReview;
481
+ export declare function classifySymphonyFollowUpCandidate(candidate: SymphonyFollowUpCandidate): SymphonyClassifiedFollowUp;
482
+ export declare function parseSymphonyFinalReportEnvelope(text: string | undefined): SymphonyFinalReportEnvelope | null;
483
+ export declare function parseSymphonyRuntimeDeliveryResult(text: string | undefined): SymphonyRuntimeDeliveryResult | null;
484
+ export declare function normalizeSymphonyRuntimeDeliveryResult(value: unknown): SymphonyRuntimeDeliveryResult | null;
240
485
  export declare function renderSymphonyRuntimePrompt(input: {
241
486
  issue?: SymphonyIssueRecord;
242
487
  task: string;
243
488
  objective: string;
244
489
  acceptanceCriteria?: string[];
245
- workspace: WorkerWorkspaceRef;
490
+ workspace: WorkerWorkspace;
246
491
  backend: AutoModeWorkerBackend;
247
492
  mode: AutoModeMode;
248
493
  secretaryAutoEnabled?: boolean;