pi-harness-runtime 1.1.349 → 1.1.351

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 (128) hide show
  1. package/README.md +3 -0
  2. package/package.json +1 -1
  3. package/packages/a2a-adapter/package.json +1 -1
  4. package/packages/agent-policy/package.json +1 -1
  5. package/packages/architecture-generator/package.json +1 -1
  6. package/packages/auth/package.json +1 -1
  7. package/packages/autonomous-refactor/package.json +1 -1
  8. package/packages/autonomous-runtime/package.json +1 -1
  9. package/packages/cache-strategy/package.json +1 -1
  10. package/packages/capability-registry/package.json +1 -1
  11. package/packages/checkpoint/package.json +1 -1
  12. package/packages/cli-plugin-sdk/package.json +1 -1
  13. package/packages/clipboard/package.json +1 -1
  14. package/packages/clipboard-plugin/package.json +1 -1
  15. package/packages/code-generation/package.json +1 -1
  16. package/packages/code-review/package.json +1 -1
  17. package/packages/codex-adapter/package.json +1 -1
  18. package/packages/codex-watcher/package.json +1 -1
  19. package/packages/config-capture/package.json +1 -1
  20. package/packages/connection-runtime/package.json +1 -1
  21. package/packages/context-compiler/package.json +1 -1
  22. package/packages/context-discovery/package.json +1 -1
  23. package/packages/context-manager/package.json +1 -1
  24. package/packages/contracts/dist/delegation-assessor.d.ts +27 -0
  25. package/packages/contracts/dist/delegation-assessor.js +210 -0
  26. package/packages/contracts/dist/delegation-store.d.ts +35 -0
  27. package/packages/contracts/dist/delegation-store.js +172 -0
  28. package/packages/contracts/dist/delegation.d.ts +142 -0
  29. package/packages/contracts/dist/delegation.js +33 -0
  30. package/packages/contracts/dist/index.d.ts +5 -0
  31. package/packages/contracts/dist/index.js +5 -0
  32. package/packages/contracts/dist/scope-discovery.d.ts +65 -0
  33. package/packages/contracts/dist/scope-discovery.js +247 -0
  34. package/packages/contracts/dist/work-partitioner.d.ts +57 -0
  35. package/packages/contracts/dist/work-partitioner.js +165 -0
  36. package/packages/contracts/package.json +1 -1
  37. package/packages/contracts/src/delegation-assessor.ts +268 -0
  38. package/packages/contracts/src/delegation-store.ts +204 -0
  39. package/packages/contracts/src/delegation.ts +174 -0
  40. package/packages/contracts/src/index.ts +5 -0
  41. package/packages/contracts/src/scope-discovery.ts +352 -0
  42. package/packages/contracts/src/work-partitioner.ts +251 -0
  43. package/packages/contracts/test/delegation.test.ts +350 -0
  44. package/packages/cookie-sanitizer/package.json +1 -1
  45. package/packages/cost-optimizer/package.json +1 -1
  46. package/packages/dependency-analyzer/package.json +1 -1
  47. package/packages/django-plugin/package.json +1 -1
  48. package/packages/doc-generator/package.json +1 -1
  49. package/packages/durable-review/package.json +1 -1
  50. package/packages/e2e-tester/package.json +1 -1
  51. package/packages/evaluation-engine/package.json +1 -1
  52. package/packages/evaluation-runner/package.json +1 -1
  53. package/packages/event-bus/package.json +1 -1
  54. package/packages/event-sink/package.json +1 -1
  55. package/packages/event-store/package.json +1 -1
  56. package/packages/experience-replay/package.json +1 -1
  57. package/packages/feedback-collector/package.json +1 -1
  58. package/packages/file-copy-helper/package.json +1 -1
  59. package/packages/framework-detector/package.json +1 -1
  60. package/packages/framework-plugin-sdk/package.json +1 -1
  61. package/packages/frappe-plugin/package.json +1 -1
  62. package/packages/generic-web-plugin/package.json +1 -1
  63. package/packages/health-monitor/package.json +1 -1
  64. package/packages/intent-analyzer/package.json +1 -1
  65. package/packages/jev-judge/package.json +1 -1
  66. package/packages/knowledge-graph/package.json +1 -1
  67. package/packages/knowledge-retrieval/package.json +1 -1
  68. package/packages/laravel-plugin/package.json +1 -1
  69. package/packages/learning-engine/package.json +1 -1
  70. package/packages/mcp-adapter/package.json +1 -1
  71. package/packages/memory-engine/package.json +1 -1
  72. package/packages/milestone-manager/package.json +1 -1
  73. package/packages/model-registry/package.json +1 -1
  74. package/packages/nextjs-plugin/package.json +1 -1
  75. package/packages/notification/package.json +1 -1
  76. package/packages/observability/package.json +1 -1
  77. package/packages/okf-indexer/package.json +1 -1
  78. package/packages/paperclip-integration/package.json +1 -1
  79. package/packages/performance-optimizer/package.json +1 -1
  80. package/packages/permission-mode/package.json +1 -1
  81. package/packages/privilege-broker/package.json +1 -1
  82. package/packages/project-analyzer/package.json +1 -1
  83. package/packages/project-bootstrap/package.json +1 -1
  84. package/packages/projection-engine/package.json +1 -1
  85. package/packages/prompt-compiler/package.json +1 -1
  86. package/packages/prompt-versioning/package.json +1 -1
  87. package/packages/provider-adapter-sdk/package.json +1 -1
  88. package/packages/provider-router/package.json +1 -1
  89. package/packages/provider-selector/package.json +1 -1
  90. package/packages/providers/package.json +1 -1
  91. package/packages/qdrant-skills/package.json +1 -1
  92. package/packages/quota-manager/package.json +1 -1
  93. package/packages/rate-limiter/package.json +1 -1
  94. package/packages/react-vite-plugin/package.json +1 -1
  95. package/packages/relay/package.json +1 -1
  96. package/packages/release-manager/package.json +1 -1
  97. package/packages/requirement-compiler/package.json +1 -1
  98. package/packages/runtime/package.json +1 -1
  99. package/packages/scheduler/package.json +1 -1
  100. package/packages/scheduler-adapter/package.json +1 -1
  101. package/packages/session/package.json +1 -1
  102. package/packages/session-api/package.json +1 -1
  103. package/packages/session-export/package.json +1 -1
  104. package/packages/shared-context/package.json +1 -1
  105. package/packages/skill-mcp-client/package.json +1 -1
  106. package/packages/skill-registry/package.json +1 -1
  107. package/packages/skills/package.json +1 -1
  108. package/packages/sprint-planner/package.json +1 -1
  109. package/packages/subscription-engine/package.json +1 -1
  110. package/packages/task-compiler/package.json +1 -1
  111. package/packages/telegram/package.json +1 -1
  112. package/packages/tencentdb-memory/package.json +1 -1
  113. package/packages/tencentdb-sync/package.json +1 -1
  114. package/packages/test-data-generator/package.json +1 -1
  115. package/packages/test-generator/package.json +1 -1
  116. package/packages/todo-bd-sync/package.json +1 -1
  117. package/packages/token-estimation/package.json +1 -1
  118. package/packages/token-optimizer/package.json +1 -1
  119. package/packages/trajectory/package.json +1 -1
  120. package/packages/tui/package.json +1 -1
  121. package/packages/types/package.json +1 -1
  122. package/packages/voice-api/package.json +1 -1
  123. package/packages/webmcp-tester/package.json +1 -1
  124. package/packages/wiki/package.json +1 -1
  125. package/packages/workflow-events/package.json +1 -1
  126. package/packages/workspace-scanner/package.json +1 -1
  127. package/packages/worktree/package.json +1 -1
  128. package/packages/write-review/package.json +1 -1
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Delegation Assessment Types
3
+ *
4
+ * Types for consistent delegation assessment for large refactors.
5
+ */
6
+ /**
7
+ * Scope estimation for a refactoring task
8
+ */
9
+ export interface ScopeFacts {
10
+ /** Estimated number of relevant files affected */
11
+ estimatedFiles: number;
12
+ /** Actual observed number of files (after scanning) */
13
+ observedFiles: number;
14
+ /** Estimated number of call sites/changes */
15
+ estimatedCallSites: number;
16
+ /** Actual observed call sites */
17
+ observedCallSites: number;
18
+ /** Number of independent components/groups */
19
+ independentComponents: number;
20
+ /** Whether changes are tightly coupled (shared APIs) */
21
+ tightlyCoupled: boolean;
22
+ /** Whether transformation is mechanical (safe for scripts) */
23
+ isMechanical: boolean;
24
+ /** Whether transformation is complex (needs reasoning) */
25
+ isComplex: boolean;
26
+ /** File type breakdown */
27
+ fileTypes: Record<string, number>;
28
+ /** Scope fingerprint for change detection */
29
+ fingerprint: string;
30
+ }
31
+ /**
32
+ * Delegation strategy decision
33
+ */
34
+ export type DelegationStrategy = "delegate" | "script_then_delegate" | "script_only" | "single_agent" | "unavailable";
35
+ /**
36
+ * Work group for delegation
37
+ */
38
+ export interface WorkGroup {
39
+ /** Unique group ID */
40
+ groupId: string;
41
+ /** Human-readable description */
42
+ description: string;
43
+ /** Files owned by this group */
44
+ ownedPaths: string[];
45
+ /** Whether this group is mechanical (script-friendly) */
46
+ isMechanical: boolean;
47
+ /** Assigned child agent ID (if delegated) */
48
+ childId?: string;
49
+ /** Status of this group */
50
+ status: "pending" | "dispatched" | "running" | "completed" | "failed" | "cancelled";
51
+ /** Validation evidence */
52
+ validation?: {
53
+ passed: boolean;
54
+ details: string;
55
+ };
56
+ }
57
+ /**
58
+ * Delegation decision from Jev or fallback
59
+ */
60
+ export interface DelegationDecision {
61
+ /** Strategy selected */
62
+ strategy: DelegationStrategy;
63
+ /** Reason for the decision */
64
+ reason: string;
65
+ /** Proposed work groups (for delegate strategies) */
66
+ workGroups: WorkGroup[];
67
+ /** Validation expectations */
68
+ validationExpectations: string;
69
+ /** Confidence level */
70
+ confidence: "high" | "medium" | "low";
71
+ /** Whether Jev was used */
72
+ jevUsed: boolean;
73
+ /** Reassessment triggers */
74
+ reassessmentTriggers: string[];
75
+ }
76
+ /**
77
+ * Delegation receipt for persistence
78
+ */
79
+ export interface DelegationReceipt {
80
+ /** Version for schema compatibility */
81
+ version: number;
82
+ /** Workspace canonical path */
83
+ workspacePath: string;
84
+ /** Session ID */
85
+ sessionId: string;
86
+ /** Parent task ID */
87
+ parentTaskId: string;
88
+ /** Scope fingerprint */
89
+ scopeFingerprint: string;
90
+ /** Decision made */
91
+ decision: DelegationDecision;
92
+ /** Created timestamp */
93
+ createdAt: number;
94
+ /** Last updated timestamp */
95
+ updatedAt: number;
96
+ /** Status */
97
+ status: "assessing" | "in_progress" | "completed" | "failed" | "cancelled";
98
+ /** Active child IDs */
99
+ childIds: string[];
100
+ /** Outstanding validation items */
101
+ pendingValidation: string[];
102
+ /** User constraints (e.g., no delegation) */
103
+ userConstraints: string[];
104
+ }
105
+ /**
106
+ * Delegation assessment trigger config
107
+ */
108
+ export interface DelegationTriggerConfig {
109
+ /** Minimum files to trigger assessment */
110
+ minFiles: number;
111
+ /** Minimum call sites to trigger assessment */
112
+ minCallSites: number;
113
+ /** Minimum independent components to suggest delegation */
114
+ minIndependentComponents: number;
115
+ /** Whether to assess on scope discovery vs mutation */
116
+ assessOnDiscovery: boolean;
117
+ }
118
+ /**
119
+ * Default trigger config
120
+ */
121
+ export declare const DEFAULT_DELEGATION_TRIGGERS: DelegationTriggerConfig;
122
+ /**
123
+ * Extension capability for delegation
124
+ */
125
+ export interface ExtensionCapability {
126
+ /** Extension name */
127
+ name: string;
128
+ /** Whether it supports sub-agents */
129
+ supportsSubagents: boolean;
130
+ /** Whether it supports work isolation */
131
+ supportsWorkIsolation: boolean;
132
+ /** Whether it supports cancellation */
133
+ supportsCancellation: boolean;
134
+ /** Supported tool names */
135
+ availableTools: string[];
136
+ /** Verified working */
137
+ verified: boolean;
138
+ }
139
+ /**
140
+ * Check if delegation should be triggered
141
+ */
142
+ export declare function shouldTriggerAssessment(facts: ScopeFacts, config?: DelegationTriggerConfig): boolean;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Delegation Assessment Types
3
+ *
4
+ * Types for consistent delegation assessment for large refactors.
5
+ */
6
+ /**
7
+ * Default trigger config
8
+ */
9
+ export const DEFAULT_DELEGATION_TRIGGERS = {
10
+ minFiles: 10,
11
+ minCallSites: 50,
12
+ minIndependentComponents: 2,
13
+ assessOnDiscovery: true,
14
+ };
15
+ /**
16
+ * Check if delegation should be triggered
17
+ */
18
+ export function shouldTriggerAssessment(facts, config = DEFAULT_DELEGATION_TRIGGERS) {
19
+ // Check file count
20
+ if (facts.observedFiles >= config.minFiles)
21
+ return true;
22
+ if (facts.estimatedFiles >= config.minFiles)
23
+ return true;
24
+ // Check call sites
25
+ if (facts.observedCallSites >= config.minCallSites)
26
+ return true;
27
+ if (facts.estimatedCallSites >= config.minCallSites)
28
+ return true;
29
+ // Check independent components
30
+ if (facts.independentComponents >= config.minIndependentComponents)
31
+ return true;
32
+ return false;
33
+ }
@@ -18,3 +18,8 @@ export * from './sessions.js';
18
18
  export * from './projects.js';
19
19
  export * from './notifications.js';
20
20
  export * from './approvals.js';
21
+ export * from './delegation.js';
22
+ export * from './delegation-assessor.js';
23
+ export * from './delegation-store.js';
24
+ export * from './scope-discovery.js';
25
+ export * from './work-partitioner.js';
@@ -18,3 +18,8 @@ export * from './sessions.js';
18
18
  export * from './projects.js';
19
19
  export * from './notifications.js';
20
20
  export * from './approvals.js';
21
+ export * from './delegation.js';
22
+ export * from './delegation-assessor.js';
23
+ export * from './delegation-store.js';
24
+ export * from './scope-discovery.js';
25
+ export * from './work-partitioner.js';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Scope Discovery
3
+ *
4
+ * Discovers and estimates the scope of refactoring work.
5
+ */
6
+ /**
7
+ * File pattern matcher
8
+ */
9
+ export interface FilePattern {
10
+ /** Glob pattern or exact extension */
11
+ pattern: string;
12
+ /** Whether to recurse into directories */
13
+ recursive?: boolean;
14
+ }
15
+ /**
16
+ * Scope discovery configuration
17
+ */
18
+ export interface ScopeDiscoveryConfig {
19
+ /** File extensions to consider relevant */
20
+ relevantExtensions: string[];
21
+ /** Directories to exclude (vendored, generated, etc.) */
22
+ excludeDirs: string[];
23
+ /** Files to exclude by name */
24
+ excludeFiles: string[];
25
+ /** Whether to scan for call sites */
26
+ scanCallSites: boolean;
27
+ /** Call site patterns to count */
28
+ callSitePatterns: string[];
29
+ }
30
+ /**
31
+ * Default scope discovery config
32
+ */
33
+ export declare const DEFAULT_SCOPE_CONFIG: ScopeDiscoveryConfig;
34
+ /**
35
+ * Discovered scope result
36
+ */
37
+ export interface DiscoveredScope {
38
+ /** Total relevant files found */
39
+ totalFiles: number;
40
+ /** Files matching the refactoring pattern */
41
+ matchingFiles: number;
42
+ /** Estimated call sites */
43
+ callSites: number;
44
+ /** Independent components found */
45
+ components: string[];
46
+ /** File breakdown by type */
47
+ fileTypes: Record<string, number>;
48
+ /** Whether shared APIs were detected */
49
+ hasSharedApis: boolean;
50
+ /** Whether transformation appears mechanical */
51
+ isMechanical: boolean;
52
+ /** Scope fingerprint for change detection */
53
+ fingerprint: string;
54
+ }
55
+ /**
56
+ * Discover scope by scanning files
57
+ */
58
+ export declare function discoverScope(workspacePath: string, searchPattern: string, config?: Partial<ScopeDiscoveryConfig>): DiscoveredScope;
59
+ /**
60
+ * Quick scope estimate using git grep
61
+ */
62
+ export declare function quickScopeEstimate(workspacePath: string, pattern: string): {
63
+ fileCount: number;
64
+ lineCount: number;
65
+ };
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Scope Discovery
3
+ *
4
+ * Discovers and estimates the scope of refactoring work.
5
+ */
6
+ import { readFileSync, readdirSync } from "fs";
7
+ import { join, extname, relative } from "path";
8
+ import { execSync } from "child_process";
9
+ /**
10
+ * Default scope discovery config
11
+ */
12
+ export const DEFAULT_SCOPE_CONFIG = {
13
+ relevantExtensions: [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs"],
14
+ excludeDirs: [
15
+ "node_modules",
16
+ ".git",
17
+ "dist",
18
+ "build",
19
+ ".next",
20
+ "__pycache__",
21
+ "vendor",
22
+ "generated",
23
+ ".venv",
24
+ "coverage",
25
+ ],
26
+ excludeFiles: [
27
+ "package-lock.json",
28
+ "yarn.lock",
29
+ "pnpm-lock.yaml",
30
+ "bun.lockb",
31
+ "*.min.js",
32
+ "*.bundle.js",
33
+ ],
34
+ scanCallSites: true,
35
+ callSitePatterns: [
36
+ "TODO:",
37
+ "FIXME:",
38
+ "console.log",
39
+ "throw new",
40
+ "await this",
41
+ "// @ts-ignore",
42
+ ],
43
+ };
44
+ /**
45
+ * Discover scope by scanning files
46
+ */
47
+ export function discoverScope(workspacePath, searchPattern, config = {}) {
48
+ const cfg = { ...DEFAULT_SCOPE_CONFIG, ...config };
49
+ const files = [];
50
+ const fileTypes = {};
51
+ const callSites = [];
52
+ const components = new Set();
53
+ // Scan directory recursively
54
+ scanDirectory(workspacePath, files, fileTypes, cfg, 0);
55
+ // Filter to relevant files
56
+ const relevantFiles = files.filter((f) => cfg.relevantExtensions.includes(extname(f)));
57
+ // Count matching files and call sites
58
+ let matchingCount = 0;
59
+ for (const file of relevantFiles) {
60
+ const content = readFileSync(file, "utf8").slice(0, 10000); // First 10KB
61
+ // Check if file matches search pattern
62
+ if (content.toLowerCase().includes(searchPattern.toLowerCase())) {
63
+ matchingCount++;
64
+ // Count call sites
65
+ if (cfg.scanCallSites) {
66
+ for (const pattern of cfg.callSitePatterns) {
67
+ const matches = content.match(new RegExp(pattern, "gi"));
68
+ if (matches) {
69
+ callSites.push(...matches.map((m) => `${file}:${m}`));
70
+ }
71
+ }
72
+ }
73
+ // Identify component (directory)
74
+ const relPath = relative(workspacePath, file);
75
+ const parts = relPath.split("/");
76
+ if (parts.length > 1) {
77
+ components.add(parts.slice(0, -1).join("/"));
78
+ }
79
+ }
80
+ }
81
+ // Detect shared APIs (files that are imported by multiple components)
82
+ const hasSharedApis = detectSharedApis(relevantFiles);
83
+ // Detect if transformation is mechanical (simple replacements)
84
+ const isMechanical = detectMechanicalPattern(relevantFiles, searchPattern);
85
+ // Generate fingerprint
86
+ const fingerprint = generateFingerprint(matchingCount, callSites.length, components.size);
87
+ return {
88
+ totalFiles: relevantFiles.length,
89
+ matchingFiles: matchingCount,
90
+ callSites: callSites.slice(0, 100).length,
91
+ components: Array.from(components),
92
+ fileTypes,
93
+ hasSharedApis,
94
+ isMechanical,
95
+ fingerprint,
96
+ };
97
+ }
98
+ /**
99
+ * Recursively scan directory
100
+ */
101
+ function scanDirectory(dir, files, fileTypes, config, depth) {
102
+ if (depth > 10)
103
+ return; // Max depth guard
104
+ try {
105
+ const entries = readdirSync(dir, { withFileTypes: true });
106
+ for (const entry of entries) {
107
+ const fullPath = join(dir, entry.name);
108
+ // Skip excluded
109
+ if (config.excludeDirs.includes(entry.name))
110
+ continue;
111
+ if (config.excludeFiles.some((f) => entry.name.includes(f)))
112
+ continue;
113
+ if (entry.isDirectory()) {
114
+ scanDirectory(fullPath, files, fileTypes, config, depth + 1);
115
+ }
116
+ else if (entry.isFile()) {
117
+ files.push(fullPath);
118
+ const ext = extname(entry.name);
119
+ fileTypes[ext] = (fileTypes[ext] || 0) + 1;
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ // Skip inaccessible directories
125
+ }
126
+ }
127
+ /**
128
+ * Detect if files have shared API patterns
129
+ */
130
+ function detectSharedApis(files) {
131
+ // Look for common export patterns
132
+ const exportCounts = new Map();
133
+ for (const file of files.slice(0, 50)) {
134
+ // Sample first 50 files
135
+ try {
136
+ const content = readFileSync(file, "utf8").slice(0, 5000);
137
+ // Count exports
138
+ const exportMatches = content.match(/export\s+(const|function|class|type|interface)/g);
139
+ if (exportMatches) {
140
+ exportCounts.set(file, (exportCounts.get(file) || 0) + exportMatches.length);
141
+ }
142
+ }
143
+ catch {
144
+ // Skip unreadable files
145
+ }
146
+ }
147
+ // Multiple files with exports suggests shared APIs
148
+ let filesWithExports = 0;
149
+ for (const count of exportCounts.values()) {
150
+ if (count > 0)
151
+ filesWithExports++;
152
+ }
153
+ return filesWithExports > 3;
154
+ }
155
+ /**
156
+ * Detect if transformation is mechanical (simple replacements)
157
+ */
158
+ function detectMechanicalPattern(files, searchPattern) {
159
+ // Mechanical = simple string replacement, no complex logic
160
+ // Look for consistent patterns
161
+ let mechanicalCount = 0;
162
+ let totalMatches = 0;
163
+ for (const file of files.slice(0, 20)) {
164
+ try {
165
+ const content = readFileSync(file, "utf8");
166
+ const matches = content.match(new RegExp(searchPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi"));
167
+ if (matches) {
168
+ totalMatches += matches.length;
169
+ // Check if each match is a simple replacement (same context)
170
+ // Mechanical if: same indentation, same surrounding code pattern
171
+ const uniqueContexts = new Set();
172
+ for (const match of matches.slice(0, 5)) {
173
+ const idx = content.indexOf(match);
174
+ const before = content.slice(Math.max(0, idx - 20), idx);
175
+ const after = content.slice(idx + match.length, idx + match.length + 20);
176
+ uniqueContexts.add(before.trim() + "|" + after.trim());
177
+ }
178
+ // Single context = mechanical
179
+ if (uniqueContexts.size === 1) {
180
+ mechanicalCount++;
181
+ }
182
+ }
183
+ }
184
+ catch {
185
+ // Skip unreadable files
186
+ }
187
+ }
188
+ // More than half mechanical = likely mechanical
189
+ return totalMatches > 0 && mechanicalCount / totalMatches > 0.5;
190
+ }
191
+ /**
192
+ * Generate scope fingerprint
193
+ */
194
+ function generateFingerprint(fileCount, callSiteCount, componentCount) {
195
+ // Simple fingerprint based on counts
196
+ const data = `${fileCount}:${callSiteCount}:${componentCount}`;
197
+ let hash = 0;
198
+ for (let i = 0; i < data.length; i++) {
199
+ const char = data.charCodeAt(i);
200
+ hash = (hash << 5) - hash + char;
201
+ hash = hash & hash; // Convert to 32bit integer
202
+ }
203
+ return Math.abs(hash).toString(36);
204
+ }
205
+ /**
206
+ * Quick scope estimate using git grep
207
+ */
208
+ export function quickScopeEstimate(workspacePath, pattern) {
209
+ // Validate inputs to prevent command injection
210
+ const safePath = validatePath(workspacePath);
211
+ if (!safePath)
212
+ return { fileCount: 0, lineCount: 0 };
213
+ const safePattern = escapeForGrep(pattern);
214
+ if (!safePattern)
215
+ return { fileCount: 0, lineCount: 0 };
216
+ try {
217
+ const result = execSync(`grep -r "${safePattern}" "${safePath}" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" -l 2>/dev/null | wc -l`, { encoding: "utf8", timeout: 10000 });
218
+ const fileCount = parseInt(result.trim(), 10) || 0;
219
+ const lineResult = execSync(`grep -r "${safePattern}" "${safePath}" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | wc -l`, { encoding: "utf8", timeout: 10000 });
220
+ const lineCount = parseInt(lineResult.trim(), 10) || 0;
221
+ return { fileCount, lineCount };
222
+ }
223
+ catch {
224
+ return { fileCount: 0, lineCount: 0 };
225
+ }
226
+ }
227
+ /**
228
+ * Validate and sanitize a file path
229
+ */
230
+ function validatePath(path) {
231
+ // Only allow alphanumeric, hyphen, underscore, dot, and forward slash
232
+ if (!/^[\w./-]+$/.test(path)) {
233
+ return null;
234
+ }
235
+ // Prevent path traversal
236
+ if (path.includes("..")) {
237
+ return null;
238
+ }
239
+ return path;
240
+ }
241
+ /**
242
+ * Escape a string for safe use in grep pattern
243
+ */
244
+ function escapeForGrep(pattern) {
245
+ // Remove any shell metacharacters
246
+ return pattern.replace(/[|;&$`\\"'<>\(\)\[\]\{\}]/g, "");
247
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Work Partitioner
3
+ *
4
+ * Partitions work into disjoint file ownership groups.
5
+ */
6
+ import type { WorkGroup, ScopeFacts } from "./delegation.js";
7
+ /**
8
+ * File dependency info
9
+ */
10
+ export interface FileDependency {
11
+ path: string;
12
+ imports: string[];
13
+ exports: string[];
14
+ }
15
+ /**
16
+ * Partition configuration
17
+ */
18
+ export interface PartitionConfig {
19
+ /** Maximum files per group */
20
+ maxFilesPerGroup: number;
21
+ /** Whether to group by directory */
22
+ groupByDirectory: boolean;
23
+ /** Shared files that shouldn't be partitioned */
24
+ sharedPaths: string[];
25
+ }
26
+ /**
27
+ * Default partition config
28
+ */
29
+ export declare const DEFAULT_PARTITION_CONFIG: PartitionConfig;
30
+ /**
31
+ * Partition files into ownership groups
32
+ */
33
+ export declare function partitionWork(files: string[], facts: ScopeFacts, config?: Partial<PartitionConfig>): WorkGroup[];
34
+ /**
35
+ * Detect ownership conflicts
36
+ */
37
+ export declare function detectOwnershipConflicts(groups: WorkGroup[], newPaths: string[]): string[];
38
+ /**
39
+ * Assign work to group
40
+ */
41
+ export declare function assignWorkToGroup(groups: WorkGroup[], groupId: string, paths: string[]): WorkGroup | null;
42
+ /**
43
+ * Get unowned files
44
+ */
45
+ export declare function getUnownedFiles(allFiles: string[], groups: WorkGroup[]): string[];
46
+ /**
47
+ * Update group status
48
+ */
49
+ export declare function updateGroupStatus(groups: WorkGroup[], groupId: string, status: WorkGroup["status"], childId?: string): WorkGroup[];
50
+ /**
51
+ * Check if all groups are complete
52
+ */
53
+ export declare function areAllGroupsComplete(groups: WorkGroup[]): boolean;
54
+ /**
55
+ * Get pending groups
56
+ */
57
+ export declare function getPendingGroups(groups: WorkGroup[]): WorkGroup[];