@telora/daemon 0.15.36 → 0.15.40

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 (110) hide show
  1. package/build-info.json +2 -2
  2. package/dist/assembly-resolvers.d.ts +1 -1
  3. package/dist/assembly-resolvers.d.ts.map +1 -1
  4. package/dist/constants.d.ts +1 -1
  5. package/dist/constants.js +1 -1
  6. package/dist/delivery-lifecycle.d.ts +3 -0
  7. package/dist/delivery-lifecycle.d.ts.map +1 -1
  8. package/dist/delivery-lifecycle.js +13 -1
  9. package/dist/delivery-lifecycle.js.map +1 -1
  10. package/dist/drift-eval-loop.d.ts +63 -0
  11. package/dist/drift-eval-loop.d.ts.map +1 -0
  12. package/dist/drift-eval-loop.js +215 -0
  13. package/dist/drift-eval-loop.js.map +1 -0
  14. package/dist/drift-evaluator.d.ts +51 -0
  15. package/dist/drift-evaluator.d.ts.map +1 -0
  16. package/dist/drift-evaluator.js +62 -0
  17. package/dist/drift-evaluator.js.map +1 -0
  18. package/dist/feeds/ghsa.d.ts +88 -0
  19. package/dist/feeds/ghsa.d.ts.map +1 -0
  20. package/dist/feeds/ghsa.js +219 -0
  21. package/dist/feeds/ghsa.js.map +1 -0
  22. package/dist/feeds/local.d.ts +55 -0
  23. package/dist/feeds/local.d.ts.map +1 -0
  24. package/dist/feeds/local.js +196 -0
  25. package/dist/feeds/local.js.map +1 -0
  26. package/dist/feeds/osv.d.ts +89 -0
  27. package/dist/feeds/osv.d.ts.map +1 -0
  28. package/dist/feeds/osv.js +266 -0
  29. package/dist/feeds/osv.js.map +1 -0
  30. package/dist/focus-completion-event.d.ts +2 -0
  31. package/dist/focus-completion-event.d.ts.map +1 -1
  32. package/dist/focus-completion-event.js +51 -13
  33. package/dist/focus-completion-event.js.map +1 -1
  34. package/dist/focus-completion.d.ts +1 -1
  35. package/dist/focus-completion.js +7 -7
  36. package/dist/focus-completion.js.map +1 -1
  37. package/dist/focus-engine.d.ts.map +1 -1
  38. package/dist/focus-engine.js +71 -0
  39. package/dist/focus-engine.js.map +1 -1
  40. package/dist/focus-executor.d.ts +53 -0
  41. package/dist/focus-executor.d.ts.map +1 -1
  42. package/dist/focus-executor.js +41 -26
  43. package/dist/focus-executor.js.map +1 -1
  44. package/dist/focus-loop.d.ts +1 -1
  45. package/dist/focus-loop.js +2 -2
  46. package/dist/focus-loop.js.map +1 -1
  47. package/dist/focus-phase.js +1 -1
  48. package/dist/focus-phase.js.map +1 -1
  49. package/dist/focus-prompt-builder.d.ts +1 -1
  50. package/dist/focus-prompt-builder.js +1 -1
  51. package/dist/listener-auto-advance.d.ts +3 -3
  52. package/dist/listener-auto-advance.js +10 -10
  53. package/dist/listener-auto-advance.js.map +1 -1
  54. package/dist/listener.js +1 -1
  55. package/dist/listener.js.map +1 -1
  56. package/dist/queries/deliveries.d.ts +20 -1
  57. package/dist/queries/deliveries.d.ts.map +1 -1
  58. package/dist/queries/deliveries.js +8 -1
  59. package/dist/queries/deliveries.js.map +1 -1
  60. package/dist/queries/drift.d.ts +50 -0
  61. package/dist/queries/drift.d.ts.map +1 -0
  62. package/dist/queries/drift.js +28 -0
  63. package/dist/queries/drift.js.map +1 -0
  64. package/dist/queries/focuses.d.ts.map +1 -1
  65. package/dist/queries/focuses.js +1 -0
  66. package/dist/queries/focuses.js.map +1 -1
  67. package/dist/queries/index.d.ts +2 -0
  68. package/dist/queries/index.d.ts.map +1 -1
  69. package/dist/queries/index.js +1 -0
  70. package/dist/queries/index.js.map +1 -1
  71. package/dist/queries/schemas.d.ts +2 -0
  72. package/dist/queries/schemas.d.ts.map +1 -1
  73. package/dist/queries/schemas.js +1 -0
  74. package/dist/queries/schemas.js.map +1 -1
  75. package/dist/scanners/deps.d.ts +101 -0
  76. package/dist/scanners/deps.d.ts.map +1 -0
  77. package/dist/scanners/deps.js +242 -0
  78. package/dist/scanners/deps.js.map +1 -0
  79. package/dist/scanners/signatures.d.ts +44 -0
  80. package/dist/scanners/signatures.d.ts.map +1 -0
  81. package/dist/scanners/signatures.js +140 -0
  82. package/dist/scanners/signatures.js.map +1 -0
  83. package/dist/scanners/workflow.d.ts +34 -0
  84. package/dist/scanners/workflow.d.ts.map +1 -0
  85. package/dist/scanners/workflow.js +239 -0
  86. package/dist/scanners/workflow.js.map +1 -0
  87. package/dist/security-auto-inject.d.ts +114 -0
  88. package/dist/security-auto-inject.d.ts.map +1 -0
  89. package/dist/security-auto-inject.js +148 -0
  90. package/dist/security-auto-inject.js.map +1 -0
  91. package/dist/security-rescan-resolution.d.ts +84 -0
  92. package/dist/security-rescan-resolution.d.ts.map +1 -0
  93. package/dist/security-rescan-resolution.js +114 -0
  94. package/dist/security-rescan-resolution.js.map +1 -0
  95. package/dist/security-scan-engine.d.ts +96 -0
  96. package/dist/security-scan-engine.d.ts.map +1 -0
  97. package/dist/security-scan-engine.js +189 -0
  98. package/dist/security-scan-engine.js.map +1 -0
  99. package/dist/stage-classifier.d.ts +2 -2
  100. package/dist/stage-classifier.d.ts.map +1 -1
  101. package/dist/stage-classifier.js +7 -7
  102. package/dist/stage-classifier.js.map +1 -1
  103. package/dist/state-cascade.d.ts +1 -1
  104. package/dist/state-cascade.js +1 -1
  105. package/dist/team-prompt-base.d.ts.map +1 -1
  106. package/dist/team-prompt-base.js +15 -0
  107. package/dist/team-prompt-base.js.map +1 -1
  108. package/dist/types/focus.d.ts +6 -0
  109. package/dist/types/focus.d.ts.map +1 -1
  110. package/package.json +3 -2
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Re-scan resolution: when a scan run completes that covered a finding's
3
+ * IOC class but did not re-produce a previously-open finding, flip the
4
+ * finding to 'resolved' and (if the linked injection's delivery is done)
5
+ * auto-verify the injection.
6
+ *
7
+ * Called by the scanner engine immediately after a run finishes writing
8
+ * its findings, before suppression-expiry sweeps and before the next
9
+ * tick begins.
10
+ *
11
+ * @module security-rescan-resolution
12
+ */
13
+ import { callApi } from './queries/shared.js';
14
+ /**
15
+ * Resolve previously-open findings that didn't re-appear in this run.
16
+ *
17
+ * @returns the list of finding ids that were flipped to 'resolved'.
18
+ */
19
+ export async function resolveStaleFindings(productId, observedSets, deps) {
20
+ const iocClasses = observedSets.map((s) => s.iocClass);
21
+ if (iocClasses.length === 0)
22
+ return [];
23
+ const openFindings = await deps.listOpenFindings(productId, iocClasses);
24
+ const observedByClass = new Map();
25
+ for (const set of observedSets) {
26
+ observedByClass.set(set.iocClass, set.identifiers);
27
+ }
28
+ const resolvedIds = [];
29
+ for (const finding of openFindings) {
30
+ const observedInClass = observedByClass.get(finding.iocClass);
31
+ if (!observedInClass)
32
+ continue;
33
+ if (observedInClass.has(finding.identifier))
34
+ continue;
35
+ // Finding was open, its class was covered, but it didn't re-appear.
36
+ await deps.markFindingResolved(finding.id);
37
+ await deps.writeAudit({
38
+ findingId: finding.id,
39
+ organizationId: finding.organizationId,
40
+ action: 'resolved',
41
+ payload: { reason: 'absent_in_rescan', ioc_class: finding.iocClass },
42
+ });
43
+ resolvedIds.push(finding.id);
44
+ // Auto-verify the linked injection if its delivery has reached 'done'.
45
+ if (finding.linkedInjectionId) {
46
+ const status = await deps.getInjectionDeliveryStatus(finding.linkedInjectionId);
47
+ if (status === 'done') {
48
+ await deps.verifyInjection(finding.linkedInjectionId);
49
+ }
50
+ }
51
+ }
52
+ return resolvedIds;
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Default Deps -- daemon-side wiring via callApi.
56
+ // ---------------------------------------------------------------------------
57
+ export function buildDefaultResolutionDeps() {
58
+ return {
59
+ listOpenFindings: async (productId, iocClasses) => {
60
+ const res = await callApi('daemon_list_open_security_findings', { productId, iocClasses });
61
+ return res.items ?? [];
62
+ },
63
+ markFindingResolved: async (findingId) => {
64
+ await callApi('daemon_resolve_security_finding', { findingId });
65
+ },
66
+ writeAudit: async (input) => {
67
+ await callApi('daemon_write_security_finding_audit', input);
68
+ },
69
+ getInjectionDeliveryStatus: async (injectionNodeId) => {
70
+ const res = await callApi('daemon_get_injection_delivery_status', { injectionNodeId });
71
+ return res.status;
72
+ },
73
+ verifyInjection: async (injectionNodeId) => {
74
+ await callApi('reality_tree_verify_injection', { injectionNodeId });
75
+ },
76
+ };
77
+ }
78
+ /**
79
+ * Sweep suppressions whose expires_at has passed and flip them back to
80
+ * 'open'. Idempotent: a suppression already expired is a no-op on the
81
+ * second call because the predicate now matches status='open'.
82
+ *
83
+ * @returns the finding ids whose suppression was lifted.
84
+ */
85
+ export async function runSuppressionExpirySweep(deps) {
86
+ const expired = await deps.listExpiredSuppressions();
87
+ const lifted = [];
88
+ for (const finding of expired) {
89
+ await deps.unsuppressFinding(finding.id);
90
+ await deps.writeAudit({
91
+ findingId: finding.id,
92
+ organizationId: finding.organizationId,
93
+ action: 'unsuppressed',
94
+ payload: { reason: 'suppression_expired' },
95
+ });
96
+ lifted.push(finding.id);
97
+ }
98
+ return lifted;
99
+ }
100
+ export function buildDefaultSuppressionExpirySweepDeps() {
101
+ return {
102
+ listExpiredSuppressions: async () => {
103
+ const res = await callApi('daemon_list_expired_security_suppressions', {});
104
+ return res.items ?? [];
105
+ },
106
+ unsuppressFinding: async (findingId) => {
107
+ await callApi('daemon_unsuppress_security_finding', { findingId });
108
+ },
109
+ writeAudit: async (input) => {
110
+ await callApi('daemon_write_security_finding_audit', input);
111
+ },
112
+ };
113
+ }
114
+ //# sourceMappingURL=security-rescan-resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-rescan-resolution.js","sourceRoot":"","sources":["../src/security-rescan-resolution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Security scan engine.
3
+ *
4
+ * Polls security_scan_configs for due scans (cron-due or manual_run_requested_at
5
+ * set), dispatches pluggable Scanner implementations per IOC class, writes
6
+ * one security_scan_runs row plus N security_findings rows per execution,
7
+ * and (downstream) hands findings to security-auto-inject for severity-gated
8
+ * injection materialization.
9
+ *
10
+ * Activation: gated by shouldRunLoop('TELORA_SECURITY_SCAN_LOOP') in
11
+ * unified-shell.ts. Opt-out semantics match the other daemon loop ticks
12
+ * (unset/anything-but-'0' = enabled, '0' = disabled). See
13
+ * docs/runbook-loop-activation.md.
14
+ *
15
+ * Pattern reference: verification-engine.ts (pluggable strategies + Deps).
16
+ *
17
+ * @module security-scan-engine
18
+ */
19
+ import type { DaemonConfig } from './types.js';
20
+ import { type AutoInjectDeps } from './security-auto-inject.js';
21
+ import { type ResolutionDeps } from './security-rescan-resolution.js';
22
+ export type Severity = 'low' | 'medium' | 'high' | 'critical';
23
+ /** Configuration row driving an individual product's scan cadence. */
24
+ export interface ScanConfig {
25
+ id: string;
26
+ organizationId: string;
27
+ productId: string;
28
+ scheduleCron: string;
29
+ enabledIocClasses: string[];
30
+ autoInjectSeverityThreshold: Severity;
31
+ enabled: boolean;
32
+ manualRunRequestedAt: string | null;
33
+ lastRunAt: string | null;
34
+ }
35
+ /** Per-scan context passed to each Scanner. */
36
+ export interface ScanContext {
37
+ config: ScanConfig;
38
+ repoPath: string;
39
+ }
40
+ /** Single finding draft emitted by a Scanner. Stored in security_findings. */
41
+ export interface FindingDraft {
42
+ iocClass: string;
43
+ severity: Severity;
44
+ identifier: string;
45
+ payload: Record<string, unknown>;
46
+ }
47
+ /** Per-scanner output for a single scan run. */
48
+ export interface ScanResult {
49
+ findings: FindingDraft[];
50
+ /** Coverage breadcrumb (e.g. packages_audited, files_scanned) + any warnings. */
51
+ coverage: Record<string, unknown>;
52
+ }
53
+ /** Pluggable Scanner contract -- one per IOC class. */
54
+ export interface Scanner {
55
+ /** IOC class slug, matched against ScanConfig.enabledIocClasses. */
56
+ iocClass: string;
57
+ scan(ctx: ScanContext): Promise<ScanResult>;
58
+ }
59
+ export declare function registerScanner(scanner: Scanner): void;
60
+ export declare function getRegisteredScanners(): Scanner[];
61
+ export interface SecurityScanDeps {
62
+ getDueScanConfigs: () => Promise<ScanConfig[]>;
63
+ startRun: (configId: string, trigger: 'schedule' | 'manual') => Promise<string>;
64
+ finishRun: (runId: string, update: {
65
+ status: 'succeeded' | 'failed' | 'partial';
66
+ coverageSummary: Record<string, unknown>;
67
+ findingsCountBySeverity: Record<Severity, number>;
68
+ durationMs: number;
69
+ }) => Promise<void>;
70
+ /**
71
+ * Persist a finding and return its DB-assigned id so downstream
72
+ * hooks (auto-injection, resolution) can reference it.
73
+ */
74
+ writeFinding: (runId: string, productId: string, organizationId: string, finding: FindingDraft) => Promise<{
75
+ findingId: string;
76
+ }>;
77
+ clearManualRunRequest: (configId: string) => Promise<void>;
78
+ resolveCwd: (productId: string) => string;
79
+ scanners: Scanner[];
80
+ /**
81
+ * Optional severity-gated auto-injection hook. When set, each newly
82
+ * written finding is passed to processNewFinding so the daemon can
83
+ * materialize a remediation injection + delivery for it.
84
+ */
85
+ autoInjectDeps?: AutoInjectDeps;
86
+ /**
87
+ * Optional re-scan resolution hook. When set, after every scan run
88
+ * finishes, the engine asks the resolution module to flip previously
89
+ * open findings whose identifiers did not re-appear to 'resolved'.
90
+ */
91
+ resolutionDeps?: ResolutionDeps;
92
+ }
93
+ export declare function runScanForConfig(config: ScanConfig, trigger: 'schedule' | 'manual', deps: SecurityScanDeps): Promise<void>;
94
+ export declare function runSecurityScanTick(deps: SecurityScanDeps): Promise<void>;
95
+ export declare function buildDefaultSecurityScanDeps(config: DaemonConfig): SecurityScanDeps;
96
+ //# sourceMappingURL=security-scan-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-scan-engine.d.ts","sourceRoot":"","sources":["../src/security-scan-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Security scan engine.
3
+ *
4
+ * Polls security_scan_configs for due scans (cron-due or manual_run_requested_at
5
+ * set), dispatches pluggable Scanner implementations per IOC class, writes
6
+ * one security_scan_runs row plus N security_findings rows per execution,
7
+ * and (downstream) hands findings to security-auto-inject for severity-gated
8
+ * injection materialization.
9
+ *
10
+ * Activation: gated by shouldRunLoop('TELORA_SECURITY_SCAN_LOOP') in
11
+ * unified-shell.ts. Opt-out semantics match the other daemon loop ticks
12
+ * (unset/anything-but-'0' = enabled, '0' = disabled). See
13
+ * docs/runbook-loop-activation.md.
14
+ *
15
+ * Pattern reference: verification-engine.ts (pluggable strategies + Deps).
16
+ *
17
+ * @module security-scan-engine
18
+ */
19
+ import { callApi } from './queries/shared.js';
20
+ import { configForProduct } from './config.js';
21
+ import { buildDefaultAutoInjectDeps, processNewFinding, } from './security-auto-inject.js';
22
+ import { resolveStaleFindings, buildDefaultResolutionDeps, } from './security-rescan-resolution.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Default registry -- scanners self-register here in their own modules
25
+ // ---------------------------------------------------------------------------
26
+ const DEFAULT_REGISTRY = new Map();
27
+ export function registerScanner(scanner) {
28
+ DEFAULT_REGISTRY.set(scanner.iocClass, scanner);
29
+ }
30
+ export function getRegisteredScanners() {
31
+ return [...DEFAULT_REGISTRY.values()];
32
+ }
33
+ export async function runScanForConfig(config, trigger, deps) {
34
+ const runId = await deps.startRun(config.id, trigger);
35
+ const startedAt = Date.now();
36
+ const coverage = {};
37
+ const warnings = [];
38
+ const counts = { low: 0, medium: 0, high: 0, critical: 0 };
39
+ let anyFailure = false;
40
+ let anySuccess = false;
41
+ const enabledScanners = deps.scanners.filter((s) => config.enabledIocClasses.includes(s.iocClass));
42
+ // Per-class observed identifier sets for re-scan resolution. Only
43
+ // classes whose scanner ran without error contribute -- a failed
44
+ // scanner can't claim coverage for its class.
45
+ const observedByClass = new Map();
46
+ for (const scanner of enabledScanners) {
47
+ try {
48
+ const result = await scanner.scan({
49
+ config,
50
+ repoPath: deps.resolveCwd(config.productId),
51
+ });
52
+ coverage[scanner.iocClass] = result.coverage;
53
+ anySuccess = true;
54
+ const observed = new Set();
55
+ for (const finding of result.findings) {
56
+ const { findingId } = await deps.writeFinding(runId, config.productId, config.organizationId, finding);
57
+ counts[finding.severity] = (counts[finding.severity] ?? 0) + 1;
58
+ observed.add(finding.identifier);
59
+ // Severity-gated auto-injection. Run per-finding so a failing
60
+ // injection for one finding does not block the others.
61
+ if (deps.autoInjectDeps) {
62
+ try {
63
+ const forInjection = {
64
+ id: findingId,
65
+ organizationId: config.organizationId,
66
+ productId: config.productId,
67
+ iocClass: finding.iocClass,
68
+ severity: finding.severity,
69
+ identifier: finding.identifier,
70
+ payload: finding.payload,
71
+ status: 'open',
72
+ suppression: null,
73
+ linkedInjectionId: null,
74
+ };
75
+ const options = {
76
+ autoInjectThreshold: config.autoInjectSeverityThreshold,
77
+ };
78
+ await processNewFinding(forInjection, options, deps.autoInjectDeps);
79
+ }
80
+ catch (err) {
81
+ warnings.push(`auto-inject ${finding.identifier}: ${err.message}`);
82
+ }
83
+ }
84
+ }
85
+ observedByClass.set(scanner.iocClass, observed);
86
+ }
87
+ catch (err) {
88
+ anyFailure = true;
89
+ warnings.push(`${scanner.iocClass}: ${err.message}`);
90
+ coverage[scanner.iocClass] = { error: err.message };
91
+ }
92
+ }
93
+ // Re-scan resolution: previously-open findings whose class was
94
+ // covered by this run but whose identifier did not re-appear are
95
+ // flipped to 'resolved'. Failures here are non-fatal -- the run
96
+ // already succeeded for its primary purpose (finding fresh issues).
97
+ if (deps.resolutionDeps && observedByClass.size > 0) {
98
+ try {
99
+ const observedSets = Array.from(observedByClass.entries()).map(([iocClass, identifiers]) => ({ iocClass, identifiers }));
100
+ const resolved = await resolveStaleFindings(config.productId, observedSets, deps.resolutionDeps);
101
+ if (resolved.length > 0) {
102
+ coverage.resolved_findings = resolved.length;
103
+ }
104
+ }
105
+ catch (err) {
106
+ warnings.push(`resolution: ${err.message}`);
107
+ }
108
+ }
109
+ if (warnings.length > 0) {
110
+ coverage.warnings = warnings;
111
+ }
112
+ const status = anyFailure
113
+ ? anySuccess
114
+ ? 'partial'
115
+ : 'failed'
116
+ : 'succeeded';
117
+ await deps.finishRun(runId, {
118
+ status,
119
+ coverageSummary: coverage,
120
+ findingsCountBySeverity: counts,
121
+ durationMs: Date.now() - startedAt,
122
+ });
123
+ if (trigger === 'manual') {
124
+ await deps.clearManualRunRequest(config.id);
125
+ }
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Loop tick -- invoked by unified-shell on a fixed cadence
129
+ // ---------------------------------------------------------------------------
130
+ export async function runSecurityScanTick(deps) {
131
+ const configs = await deps.getDueScanConfigs();
132
+ for (const config of configs) {
133
+ if (!config.enabled)
134
+ continue;
135
+ const trigger = config.manualRunRequestedAt ? 'manual' : 'schedule';
136
+ try {
137
+ await runScanForConfig(config, trigger, deps);
138
+ }
139
+ catch {
140
+ // Per-config failures are swallowed so a single broken product
141
+ // does not stop the engine from servicing others. The run row
142
+ // already records the failure status.
143
+ }
144
+ }
145
+ }
146
+ // ---------------------------------------------------------------------------
147
+ // Default Deps -- daemon-side wiring via callApi
148
+ // ---------------------------------------------------------------------------
149
+ export function buildDefaultSecurityScanDeps(config) {
150
+ const resolveCwd = (productId) => {
151
+ const product = config.products.find((p) => p.id === productId);
152
+ if (!product)
153
+ return config.repoPath;
154
+ return configForProduct(config, product).repoPath;
155
+ };
156
+ return {
157
+ getDueScanConfigs: async () => {
158
+ const res = await callApi('daemon_get_due_security_scan_configs', {});
159
+ return res.items ?? [];
160
+ },
161
+ startRun: async (configId, trigger) => {
162
+ const res = await callApi('daemon_start_security_scan_run', {
163
+ configId,
164
+ trigger,
165
+ });
166
+ return res.runId;
167
+ },
168
+ finishRun: async (runId, update) => {
169
+ await callApi('daemon_finish_security_scan_run', { runId, ...update });
170
+ },
171
+ writeFinding: async (runId, productId, organizationId, finding) => {
172
+ const res = await callApi('daemon_write_security_finding', {
173
+ runId,
174
+ productId,
175
+ organizationId,
176
+ ...finding,
177
+ });
178
+ return { findingId: res.findingId };
179
+ },
180
+ clearManualRunRequest: async (configId) => {
181
+ await callApi('daemon_clear_manual_scan_request', { configId });
182
+ },
183
+ resolveCwd,
184
+ scanners: getRegisteredScanners(),
185
+ autoInjectDeps: buildDefaultAutoInjectDeps(),
186
+ resolutionDeps: buildDefaultResolutionDeps(),
187
+ };
188
+ }
189
+ //# sourceMappingURL=security-scan-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-scan-engine.js","sourceRoot":"","sources":["../src/security-scan-engine.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  * without metadata populated.
8
8
  */
9
9
  import type { WorkflowStage, Workflow } from './types.js';
10
- /** Stage where agent team has work to do (e.g., queued, coding, iterating). */
10
+ /** Stage where agent team has work to do (e.g., queued, coding, awaiting_verify). */
11
11
  export declare function isAgentActionable(stage: WorkflowStage): boolean;
12
12
  /** Truly terminal — no more work ever (e.g., done, cancelled). */
13
13
  export declare function isTerminal(stage: WorkflowStage): boolean;
@@ -19,7 +19,7 @@ export declare function isCascadable(stage: WorkflowStage): boolean;
19
19
  /**
20
20
  * Blocks subsequent ranked deliveries from being picked up.
21
21
  * Backlog stages, agent-work stages, and paused block.
22
- * Review/iterating/terminal stages don't block.
22
+ * Review/awaiting_verify/terminal stages don't block.
23
23
  */
24
24
  export declare function isBlocking(stage: WorkflowStage): boolean;
25
25
  /** Excluded from cascade checks entirely (cancelled but not done). */
@@ -1 +1 @@
1
- {"version":3,"file":"stage-classifier.d.ts","sourceRoot":"","sources":["../src/stage-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI1D,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAG/D;AAED,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAGxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAS1D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAUxD;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAEnE;AAUD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAMpF;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAM7E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAM/E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAM7E;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAMxF"}
1
+ {"version":3,"file":"stage-classifier.d.ts","sourceRoot":"","sources":["../src/stage-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI1D,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAG/D;AAED,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAGxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAS1D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAUxD;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAEnE;AAUD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAMpF;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAM7E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAM/E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAM7E;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAMxF"}
@@ -7,11 +7,11 @@
7
7
  * without metadata populated.
8
8
  */
9
9
  // ── Stage-level classifiers ──────────────────────────────────────
10
- /** Stage where agent team has work to do (e.g., queued, coding, iterating). */
10
+ /** Stage where agent team has work to do (e.g., queued, coding, awaiting_verify). */
11
11
  export function isAgentActionable(stage) {
12
12
  if (stage.is_agent_actionable !== undefined)
13
13
  return stage.is_agent_actionable;
14
- return stage.name === 'queued' || stage.name === 'coding' || stage.name === 'iterating';
14
+ return stage.name === 'queued' || stage.name === 'coding' || stage.name === 'awaiting_verify';
15
15
  }
16
16
  /** Truly terminal — no more work ever (e.g., done, cancelled). */
17
17
  export function isTerminal(stage) {
@@ -29,7 +29,7 @@ export function isCascadable(stage) {
29
29
  if (stage.is_terminal)
30
30
  return true;
31
31
  // Non-terminal, non-actionable, non-blocking active stages are cascadable
32
- // (verify, in_review, iterating)
32
+ // (verify, in_review, awaiting_verify)
33
33
  return !isAgentActionable(stage) && !isBlocking(stage);
34
34
  }
35
35
  return ['verify', 'in_review', 'done', 'cancelled'].includes(stage.name);
@@ -37,7 +37,7 @@ export function isCascadable(stage) {
37
37
  /**
38
38
  * Blocks subsequent ranked deliveries from being picked up.
39
39
  * Backlog stages, agent-work stages, and paused block.
40
- * Review/iterating/terminal stages don't block.
40
+ * Review/awaiting_verify/terminal stages don't block.
41
41
  */
42
42
  export function isBlocking(stage) {
43
43
  if (stage.meta_bucket !== undefined) {
@@ -52,7 +52,7 @@ export function isBlocking(stage) {
52
52
  return true;
53
53
  return false;
54
54
  }
55
- return !['done', 'cancelled', 'verify', 'in_review', 'iterating'].includes(stage.name);
55
+ return !['done', 'cancelled', 'verify', 'in_review', 'awaiting_verify'].includes(stage.name);
56
56
  }
57
57
  /** Excluded from cascade checks entirely (cancelled but not done). */
58
58
  export function isExcludedFromCascade(stage) {
@@ -70,7 +70,7 @@ export function isStatusAgentActionable(status, workflow) {
70
70
  if (stage)
71
71
  return isAgentActionable(stage);
72
72
  }
73
- return status === 'queued' || status === 'coding' || status === 'iterating';
73
+ return status === 'queued' || status === 'coding' || status === 'awaiting_verify';
74
74
  }
75
75
  export function isStatusTerminal(status, workflow) {
76
76
  if (workflow) {
@@ -94,7 +94,7 @@ export function isStatusBlocking(status, workflow) {
94
94
  if (stage)
95
95
  return isBlocking(stage);
96
96
  }
97
- return !['done', 'cancelled', 'verify', 'in_review', 'iterating'].includes(status);
97
+ return !['done', 'cancelled', 'verify', 'in_review', 'awaiting_verify'].includes(status);
98
98
  }
99
99
  export function isStatusExcludedFromCascade(status, workflow) {
100
100
  if (workflow) {
@@ -1 +1 @@
1
- {"version":3,"file":"stage-classifier.js","sourceRoot":"","sources":["../src/stage-classifier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stage-classifier.js","sourceRoot":"","sources":["../src/stage-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,oEAAoE;AAEpE,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAAC,KAAoB;IACpD,IAAI,KAAK,CAAC,mBAAmB,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,mBAAmB,CAAC;IAC9E,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC;AAChG,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC;IAC9D,OAAO,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAoB;IAC/C,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACpC,wCAAwC;QACxC,IAAI,KAAK,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QACnC,0EAA0E;QAC1E,uCAAuC;QACvC,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACjD,IAAI,KAAK,CAAC,WAAW,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;QAC/C,iEAAiE;QACjE,IAAI,iBAAiB,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC/F,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,qBAAqB,CAAC,KAAoB;IACxD,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;AACpD,CAAC;AAED,oEAAoE;AACpE,8DAA8D;AAE9D,6DAA6D;AAC7D,SAAS,SAAS,CAAC,MAAc,EAAE,QAAkB;IACnD,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,QAAmB;IACzE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,iBAAiB,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,QAAmB;IAClE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,WAAW,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,QAAmB;IACpE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,QAAmB;IAClE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,MAAc,EAAE,QAAmB;IAC7E,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,KAAK,WAAW,CAAC;AAChC,CAAC"}
@@ -14,7 +14,7 @@
14
14
  * user can request a fresh review when verify is reached again.
15
15
  *
16
16
  * Review completion is NOT auto-routed here. Closing out a review and
17
- * routing in_review deliveries to done/iterating is the exclusive
17
+ * routing in_review deliveries to done/awaiting_verify is the exclusive
18
18
  * responsibility of focus-completion.ts's review exit handler, which
19
19
  * gates on the exiting team's sessionType === 'review' (a positive
20
20
  * signal that an actual review ran). If the review team never spawns
@@ -14,7 +14,7 @@
14
14
  * user can request a fresh review when verify is reached again.
15
15
  *
16
16
  * Review completion is NOT auto-routed here. Closing out a review and
17
- * routing in_review deliveries to done/iterating is the exclusive
17
+ * routing in_review deliveries to done/awaiting_verify is the exclusive
18
18
  * responsibility of focus-completion.ts's review exit handler, which
19
19
  * gates on the exiting team's sessionType === 'review' (a positive
20
20
  * signal that an actual review ran). If the review team never spawns
@@ -1 +1 @@
1
- {"version":3,"file":"team-prompt-base.d.ts","sourceRoot":"","sources":["../src/team-prompt-base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"team-prompt-base.d.ts","sourceRoot":"","sources":["../src/team-prompt-base.ts"],"names":[],"mappings":"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"}
@@ -424,6 +424,21 @@ export function buildStatusUpdateRulesSection() {
424
424
  '2. When the worker completes, verify its output',
425
425
  '3. Set issue to "Done" after verification',
426
426
  '',
427
+ '**Completion artifacts (MANDATORY on close):**',
428
+ '- When you set an issue to "Done" or "In Review", you MUST also supply',
429
+ ' `completionArtifacts` listing the primary files the work produced or',
430
+ ' modified. Shape: `{ "files": ["src/foo.ts", "src/foo.test.ts"], "tests": [...] }`.',
431
+ '- Drift detection compares these references against the worktree on a',
432
+ ' schedule. Without them, drift cannot surface for this issue and the',
433
+ ' Done-work signal is unreliable.',
434
+ '- Use repo-relative paths (no leading slash, no `./`). Include test files',
435
+ ' under `files` or `tests` -- both are checked.',
436
+ '- Workers spawned via Task: when reporting completion, return the list of',
437
+ ' files you modified so the team lead can pass them through in the',
438
+ ' `issue_update` call.',
439
+ '- Example close call:',
440
+ ' `{ "issueId": "<id>", "status": "Done", "completionArtifacts": { "files": ["src/foo.ts"] } }`',
441
+ '',
427
442
  ];
428
443
  }
429
444
  /**