omegon 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +3 -0
- package/AGENTS.md +16 -0
- package/LICENSE +15 -0
- package/README.md +289 -0
- package/bin/pi.mjs +30 -0
- package/extensions/00-secrets/index.ts +1126 -0
- package/extensions/01-auth/auth.ts +401 -0
- package/extensions/01-auth/index.ts +289 -0
- package/extensions/auto-compact.ts +42 -0
- package/extensions/bootstrap/deps.ts +291 -0
- package/extensions/bootstrap/index.ts +811 -0
- package/extensions/chronos/chronos.sh +487 -0
- package/extensions/chronos/index.ts +148 -0
- package/extensions/cleave/assessment.ts +754 -0
- package/extensions/cleave/bridge.ts +31 -0
- package/extensions/cleave/conflicts.ts +250 -0
- package/extensions/cleave/dispatcher.ts +808 -0
- package/extensions/cleave/guardrails.ts +426 -0
- package/extensions/cleave/index.ts +3121 -0
- package/extensions/cleave/lifecycle-emitter.ts +20 -0
- package/extensions/cleave/openspec.ts +811 -0
- package/extensions/cleave/planner.ts +260 -0
- package/extensions/cleave/review.ts +579 -0
- package/extensions/cleave/skills.ts +355 -0
- package/extensions/cleave/types.ts +261 -0
- package/extensions/cleave/workspace.ts +861 -0
- package/extensions/cleave/worktree.ts +243 -0
- package/extensions/core-renderers.ts +253 -0
- package/extensions/dashboard/context-gauge.ts +58 -0
- package/extensions/dashboard/file-watch.ts +14 -0
- package/extensions/dashboard/footer.ts +1145 -0
- package/extensions/dashboard/git.ts +185 -0
- package/extensions/dashboard/index.ts +478 -0
- package/extensions/dashboard/memory-audit.ts +34 -0
- package/extensions/dashboard/overlay-data.ts +705 -0
- package/extensions/dashboard/overlay.ts +365 -0
- package/extensions/dashboard/render-utils.ts +54 -0
- package/extensions/dashboard/types.ts +191 -0
- package/extensions/dashboard/uri-helper.ts +45 -0
- package/extensions/debug.ts +69 -0
- package/extensions/defaults.ts +282 -0
- package/extensions/design-tree/dashboard-state.ts +161 -0
- package/extensions/design-tree/design-card.ts +362 -0
- package/extensions/design-tree/index.ts +2130 -0
- package/extensions/design-tree/lifecycle-emitter.ts +41 -0
- package/extensions/design-tree/tree.ts +1607 -0
- package/extensions/design-tree/types.ts +163 -0
- package/extensions/distill.ts +127 -0
- package/extensions/effort/index.ts +395 -0
- package/extensions/effort/tiers.ts +146 -0
- package/extensions/effort/types.ts +105 -0
- package/extensions/lib/git-state.ts +227 -0
- package/extensions/lib/local-models.ts +157 -0
- package/extensions/lib/model-preferences.ts +51 -0
- package/extensions/lib/model-routing.ts +720 -0
- package/extensions/lib/operator-fallback.ts +205 -0
- package/extensions/lib/operator-profile.ts +360 -0
- package/extensions/lib/slash-command-bridge.ts +253 -0
- package/extensions/lib/typebox-helpers.ts +16 -0
- package/extensions/local-inference/index.ts +727 -0
- package/extensions/mcp-bridge/README.md +220 -0
- package/extensions/mcp-bridge/index.ts +951 -0
- package/extensions/mcp-bridge/lib.ts +365 -0
- package/extensions/mcp-bridge/mcp.json +3 -0
- package/extensions/mcp-bridge/package.json +11 -0
- package/extensions/model-budget.ts +752 -0
- package/extensions/offline-driver.ts +403 -0
- package/extensions/openspec/archive-gate.ts +164 -0
- package/extensions/openspec/branch-cleanup.ts +64 -0
- package/extensions/openspec/dashboard-state.ts +50 -0
- package/extensions/openspec/index.ts +1917 -0
- package/extensions/openspec/lifecycle-emitter.ts +65 -0
- package/extensions/openspec/lifecycle-files.ts +70 -0
- package/extensions/openspec/lifecycle.ts +50 -0
- package/extensions/openspec/reconcile.ts +187 -0
- package/extensions/openspec/spec.ts +1385 -0
- package/extensions/openspec/types.ts +98 -0
- package/extensions/project-memory/DESIGN-global-mind.md +198 -0
- package/extensions/project-memory/README.md +202 -0
- package/extensions/project-memory/api-types.ts +382 -0
- package/extensions/project-memory/compaction-policy.ts +29 -0
- package/extensions/project-memory/core.ts +164 -0
- package/extensions/project-memory/embeddings.ts +230 -0
- package/extensions/project-memory/extraction-v2.ts +861 -0
- package/extensions/project-memory/factstore.ts +2177 -0
- package/extensions/project-memory/index.ts +3459 -0
- package/extensions/project-memory/injection-metrics.ts +91 -0
- package/extensions/project-memory/jsonl-io.ts +12 -0
- package/extensions/project-memory/lifecycle.ts +331 -0
- package/extensions/project-memory/migration.ts +293 -0
- package/extensions/project-memory/package.json +9 -0
- package/extensions/project-memory/sci-renderers.ts +7 -0
- package/extensions/project-memory/template.ts +103 -0
- package/extensions/project-memory/triggers.ts +52 -0
- package/extensions/project-memory/types.ts +102 -0
- package/extensions/render/composition/fonts/Inter-Bold.ttf +0 -0
- package/extensions/render/composition/fonts/Inter-Regular.ttf +0 -0
- package/extensions/render/composition/fonts/Tomorrow-Bold.ttf +0 -0
- package/extensions/render/composition/fonts/Tomorrow-Regular.ttf +0 -0
- package/extensions/render/composition/package-lock.json +534 -0
- package/extensions/render/composition/package.json +22 -0
- package/extensions/render/composition/render.mjs +246 -0
- package/extensions/render/composition/test-comp.tsx +87 -0
- package/extensions/render/composition/types.ts +24 -0
- package/extensions/render/excalidraw/UPSTREAM.md +81 -0
- package/extensions/render/excalidraw/elements.ts +764 -0
- package/extensions/render/excalidraw/index.ts +66 -0
- package/extensions/render/excalidraw/types.ts +223 -0
- package/extensions/render/excalidraw-renderer/pyproject.toml +8 -0
- package/extensions/render/excalidraw-renderer/render_excalidraw.py +182 -0
- package/extensions/render/excalidraw-renderer/render_template.html +59 -0
- package/extensions/render/index.ts +830 -0
- package/extensions/render/native-diagrams/index.ts +57 -0
- package/extensions/render/native-diagrams/motifs.ts +542 -0
- package/extensions/render/native-diagrams/raster.ts +8 -0
- package/extensions/render/native-diagrams/scene.ts +75 -0
- package/extensions/render/native-diagrams/spec.ts +204 -0
- package/extensions/render/native-diagrams/svg.ts +116 -0
- package/extensions/sci-ui.ts +304 -0
- package/extensions/session-log.ts +174 -0
- package/extensions/shared-state.ts +146 -0
- package/extensions/spinner-verbs.ts +91 -0
- package/extensions/style.ts +281 -0
- package/extensions/terminal-title.ts +191 -0
- package/extensions/tool-profile/index.ts +291 -0
- package/extensions/tool-profile/profiles.ts +290 -0
- package/extensions/types.d.ts +9 -0
- package/extensions/vault/index.ts +185 -0
- package/extensions/version-check.ts +90 -0
- package/extensions/view/index.ts +859 -0
- package/extensions/view/uri-resolver.ts +148 -0
- package/extensions/web-search/index.ts +182 -0
- package/extensions/web-search/providers.ts +121 -0
- package/extensions/web-ui/index.ts +110 -0
- package/extensions/web-ui/server.ts +265 -0
- package/extensions/web-ui/state.ts +462 -0
- package/extensions/web-ui/static/index.html +145 -0
- package/extensions/web-ui/types.ts +284 -0
- package/package.json +76 -0
- package/prompts/init.md +75 -0
- package/prompts/new-repo.md +54 -0
- package/prompts/oci-login.md +56 -0
- package/prompts/status.md +50 -0
- package/settings.json +4 -0
- package/skills/cleave/SKILL.md +218 -0
- package/skills/git/SKILL.md +209 -0
- package/skills/git/_reference/ci-validation.md +204 -0
- package/skills/oci/SKILL.md +338 -0
- package/skills/openspec/SKILL.md +346 -0
- package/skills/pi-extensions/SKILL.md +191 -0
- package/skills/pi-tui/SKILL.md +517 -0
- package/skills/python/SKILL.md +189 -0
- package/skills/rust/SKILL.md +268 -0
- package/skills/security/SKILL.md +206 -0
- package/skills/style/SKILL.md +264 -0
- package/skills/typescript/SKILL.md +225 -0
- package/skills/vault/SKILL.md +102 -0
- package/themes/alpharius-legacy.json +85 -0
- package/themes/alpharius.conf +59 -0
- package/themes/alpharius.json +88 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { buildSlashCommandResult } from "../lib/slash-command-bridge.ts";
|
|
2
|
+
import type { AssessStructuredResult } from "./assessment.ts";
|
|
3
|
+
|
|
4
|
+
export function buildAssessBridgeResult(
|
|
5
|
+
bridgedArgs: string[],
|
|
6
|
+
result: AssessStructuredResult,
|
|
7
|
+
): ReturnType<typeof buildSlashCommandResult> {
|
|
8
|
+
return buildSlashCommandResult(result.command, bridgedArgs, {
|
|
9
|
+
ok: result.ok,
|
|
10
|
+
summary: result.summary,
|
|
11
|
+
humanText: result.humanText,
|
|
12
|
+
data: {
|
|
13
|
+
subcommand: result.subcommand,
|
|
14
|
+
data: result.data,
|
|
15
|
+
completion: result.completion,
|
|
16
|
+
lifecycleHint: result.lifecycle,
|
|
17
|
+
assessEffects: result.effects,
|
|
18
|
+
bridge: {
|
|
19
|
+
completionSemantics: result.completion?.completedInBand ? "synchronous" : "follow-up-driven",
|
|
20
|
+
completionState: result.completion?.completed ? "completed" : "pending",
|
|
21
|
+
originalArgs: [...bridgedArgs],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
lifecycle: result.lifecycleRecord,
|
|
25
|
+
effects: {
|
|
26
|
+
sideEffectClass: result.subcommand === "cleave" ? "workspace-write" : "read",
|
|
27
|
+
lifecycleTouched: result.lifecycleRecord ? [result.lifecycleRecord.changeName] : undefined,
|
|
28
|
+
},
|
|
29
|
+
nextSteps: result.nextSteps.map((step) => ({ label: step })),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cleave/conflicts — 4-step conflict detection for reunification.
|
|
3
|
+
*
|
|
4
|
+
* Ported from styrene-lab/cleave src/cleave/core/conflicts.py.
|
|
5
|
+
* Pure functions with no runtime dependencies.
|
|
6
|
+
*
|
|
7
|
+
* Conflict types:
|
|
8
|
+
* 1. File Overlap — multiple children modified same file
|
|
9
|
+
* 2. Decision Contradiction — incompatible technology/approach choices
|
|
10
|
+
* 3. Interface Mismatch — published signatures differ
|
|
11
|
+
* 4. Assumption Violation — contradicts sibling's decision
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { Conflict, TaskResult } from "./types.ts";
|
|
15
|
+
|
|
16
|
+
// ─── Task result parsing ────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Parse a task markdown file to extract result info for conflict detection.
|
|
20
|
+
*
|
|
21
|
+
* Expects the task file format used by the cleave workspace:
|
|
22
|
+
* - **Status:** SUCCESS|PARTIAL|FAILED|PENDING
|
|
23
|
+
* - **Summary:** ...
|
|
24
|
+
* - **Artifacts:** bullet list of file paths
|
|
25
|
+
* - **Decisions Made:** bullet list
|
|
26
|
+
* - **Assumptions:** bullet list
|
|
27
|
+
* - Interface signatures in backticks: `funcName(params) -> ReturnType`
|
|
28
|
+
*/
|
|
29
|
+
export function parseTaskResult(content: string, filePath: string): TaskResult {
|
|
30
|
+
const result: TaskResult = {
|
|
31
|
+
path: filePath,
|
|
32
|
+
status: "PENDING",
|
|
33
|
+
summary: null,
|
|
34
|
+
fileClaims: [],
|
|
35
|
+
interfacesPublished: [],
|
|
36
|
+
decisions: [],
|
|
37
|
+
assumptions: [],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Status
|
|
41
|
+
if (content.includes("**Status:** SUCCESS")) result.status = "SUCCESS";
|
|
42
|
+
else if (content.includes("**Status:** PARTIAL")) result.status = "PARTIAL";
|
|
43
|
+
else if (content.includes("**Status:** FAILED")) result.status = "FAILED";
|
|
44
|
+
|
|
45
|
+
// Summary
|
|
46
|
+
const summaryMatch = content.match(/\*\*Summary:\*\*\s*(.+?)(?:\n\*\*|\n##|$)/s);
|
|
47
|
+
if (summaryMatch) {
|
|
48
|
+
const summary = summaryMatch[1].trim();
|
|
49
|
+
if (!summary.startsWith("[")) result.summary = summary;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Interfaces: `function_name(params) -> return_type`
|
|
53
|
+
const ifaceRe = /`([a-zA-Z_]\w*\([^)]*\)\s*->\s*[^`]+)`/g;
|
|
54
|
+
let ifaceMatch: RegExpExecArray | null;
|
|
55
|
+
while ((ifaceMatch = ifaceRe.exec(content)) !== null) {
|
|
56
|
+
result.interfacesPublished.push(ifaceMatch[1]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// File claims from Artifacts section
|
|
60
|
+
const artifactsMatch = content.match(/\*\*Artifacts:\*\*\s*\n((?:\s*-\s*.+\n?)+)/);
|
|
61
|
+
if (artifactsMatch) {
|
|
62
|
+
const section = artifactsMatch[1];
|
|
63
|
+
// Quoted paths
|
|
64
|
+
for (const m of section.matchAll(/-\s*[`"']([^`"']+)[`"']/g)) {
|
|
65
|
+
const cleaned = m[1].trim().replace(/[,;:]$/, "");
|
|
66
|
+
if (cleaned && !cleaned.startsWith("[")) result.fileClaims.push(cleaned);
|
|
67
|
+
}
|
|
68
|
+
// Unquoted paths with extension
|
|
69
|
+
for (const m of section.matchAll(/-\s*([a-zA-Z0-9_./-]+\.[a-zA-Z0-9]+)(?:\s|$|,)/g)) {
|
|
70
|
+
const cleaned = m[1].trim().replace(/[,;:]$/, "");
|
|
71
|
+
if (cleaned && !cleaned.startsWith("[")) result.fileClaims.push(cleaned);
|
|
72
|
+
}
|
|
73
|
+
result.fileClaims = [...new Set(result.fileClaims)];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Decisions
|
|
77
|
+
const decisionsMatch = content.match(/\*\*Decisions Made:\*\*\s*\n((?:\s*-\s*.+\n?)+)/);
|
|
78
|
+
if (decisionsMatch) {
|
|
79
|
+
result.decisions = [...decisionsMatch[1].matchAll(/-\s*(.+)/g)]
|
|
80
|
+
.map((m) => m[1].trim())
|
|
81
|
+
.filter((d) => d && !d.startsWith("["));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Assumptions
|
|
85
|
+
const assumptionsMatch = content.match(/\*\*Assumptions:\*\*\s*\n((?:\s*-\s*.+\n?)+)/);
|
|
86
|
+
if (assumptionsMatch) {
|
|
87
|
+
result.assumptions = [...assumptionsMatch[1].matchAll(/-\s*(.+)/g)]
|
|
88
|
+
.map((m) => m[1].trim())
|
|
89
|
+
.filter((a) => a && !a.startsWith("["));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ─── Conflict detection ─────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
/** Technology contradiction pairs for decision conflict detection. */
|
|
98
|
+
const CONTRADICTION_PAIRS: [string[], string[]][] = [
|
|
99
|
+
[["redis", "use redis"], ["memcached", "use memcached"]],
|
|
100
|
+
[["sql", "postgresql", "mysql"], ["nosql", "mongodb", "dynamodb"]],
|
|
101
|
+
[["sync", "synchronous"], ["async", "asynchronous"]],
|
|
102
|
+
[["rest", "restful"], ["graphql", "grpc"]],
|
|
103
|
+
[["jwt"], ["session", "cookie-based"]],
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const REJECTION_PHRASES = ["instead of", "not ", "rather than", "over ", "rejected"];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Run 4-step conflict detection on parsed task results.
|
|
110
|
+
*
|
|
111
|
+
* Steps:
|
|
112
|
+
* 1. File Overlap — multiple children modified same file
|
|
113
|
+
* 2. Decision Contradiction — opposing technology choices
|
|
114
|
+
* 3. Interface Mismatch — conflicting function signatures
|
|
115
|
+
* 4. Assumption Violation — assumption contradicts sibling's decision
|
|
116
|
+
*/
|
|
117
|
+
export function detectConflicts(results: TaskResult[]): Conflict[] {
|
|
118
|
+
const conflicts: Conflict[] = [];
|
|
119
|
+
|
|
120
|
+
// ── Step 1: File Overlap ──────────────────────────────────────────────
|
|
121
|
+
// Collect ALL claimants per file, then emit one conflict per file with
|
|
122
|
+
// all involved children (handles N-way overlaps, not just pairwise).
|
|
123
|
+
const fileClaims = new Map<string, number[]>();
|
|
124
|
+
for (let i = 0; i < results.length; i++) {
|
|
125
|
+
for (const file of results[i].fileClaims) {
|
|
126
|
+
const existing = fileClaims.get(file);
|
|
127
|
+
if (existing) {
|
|
128
|
+
existing.push(i);
|
|
129
|
+
} else {
|
|
130
|
+
fileClaims.set(file, [i]);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const [file, claimants] of fileClaims) {
|
|
135
|
+
if (claimants.length > 1) {
|
|
136
|
+
conflicts.push({
|
|
137
|
+
type: "file_overlap",
|
|
138
|
+
description: `Multiple children modified ${file}`,
|
|
139
|
+
involved: claimants,
|
|
140
|
+
resolution: "3way_merge",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ── Step 2: Decision Contradiction ────────────────────────────────────
|
|
146
|
+
const allDecisions: Array<[number, string]> = [];
|
|
147
|
+
for (let i = 0; i < results.length; i++) {
|
|
148
|
+
for (const d of results[i].decisions) {
|
|
149
|
+
allDecisions.push([i, d.toLowerCase()]);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
for (const [termsA, termsB] of CONTRADICTION_PAIRS) {
|
|
154
|
+
const siblingsA = new Set<number>();
|
|
155
|
+
const siblingsB = new Set<number>();
|
|
156
|
+
|
|
157
|
+
for (const [i, d] of allDecisions) {
|
|
158
|
+
const hasA = termsA.some((t) => d.includes(t));
|
|
159
|
+
const rejectedA = termsB.some((t) => d.includes(t)) && REJECTION_PHRASES.some((r) => d.includes(r));
|
|
160
|
+
if (hasA && !rejectedA) siblingsA.add(i);
|
|
161
|
+
|
|
162
|
+
const hasB = termsB.some((t) => d.includes(t));
|
|
163
|
+
const rejectedB = termsA.some((t) => d.includes(t)) && REJECTION_PHRASES.some((r) => d.includes(r));
|
|
164
|
+
if (hasB && !rejectedB) siblingsB.add(i);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Only flag if DIFFERENT siblings made opposing choices
|
|
168
|
+
const uniqueA = new Set([...siblingsA].filter((x) => !siblingsB.has(x)));
|
|
169
|
+
const uniqueB = new Set([...siblingsB].filter((x) => !siblingsA.has(x)));
|
|
170
|
+
|
|
171
|
+
if (uniqueA.size > 0 && uniqueB.size > 0) {
|
|
172
|
+
conflicts.push({
|
|
173
|
+
type: "decision_contradiction",
|
|
174
|
+
description: `Contradictory decisions: ${termsA[0]} vs ${termsB[0]}`,
|
|
175
|
+
involved: [...uniqueA, ...uniqueB],
|
|
176
|
+
resolution: "escalate_to_parent",
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Step 3: Interface Mismatch ────────────────────────────────────────
|
|
182
|
+
const published = new Map<string, { signature: string; source: number }>();
|
|
183
|
+
for (let i = 0; i < results.length; i++) {
|
|
184
|
+
for (const iface of results[i].interfacesPublished) {
|
|
185
|
+
const funcName = iface.includes("(") ? iface.split("(")[0] : iface;
|
|
186
|
+
const existing = published.get(funcName);
|
|
187
|
+
if (existing && existing.signature !== iface) {
|
|
188
|
+
conflicts.push({
|
|
189
|
+
type: "interface_mismatch",
|
|
190
|
+
description: `Interface '${funcName}' has conflicting signatures`,
|
|
191
|
+
involved: [existing.source, i],
|
|
192
|
+
resolution: "adapter_required",
|
|
193
|
+
});
|
|
194
|
+
} else if (!existing) {
|
|
195
|
+
published.set(funcName, { signature: iface, source: i });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ── Step 4: Assumption Violation ──────────────────────────────────────
|
|
201
|
+
// Only check assumption violations between siblings that have overlapping
|
|
202
|
+
// file scopes. In greenfield projects where each child creates entirely
|
|
203
|
+
// new files, cross-child assumption checking produces false positives
|
|
204
|
+
// from generic task description language.
|
|
205
|
+
const allAssumptions: Array<[number, string]> = [];
|
|
206
|
+
for (let i = 0; i < results.length; i++) {
|
|
207
|
+
for (const a of results[i].assumptions) {
|
|
208
|
+
allAssumptions.push([i, a.toLowerCase()]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (const [assIdx, assumption] of allAssumptions) {
|
|
213
|
+
for (const [decIdx, decision] of allDecisions) {
|
|
214
|
+
if (assIdx === decIdx) continue;
|
|
215
|
+
|
|
216
|
+
// Skip if the two siblings have zero file scope overlap.
|
|
217
|
+
// Non-overlapping children are unlikely to have real assumption
|
|
218
|
+
// violations — the detector would fire on generic phrasing.
|
|
219
|
+
const filesA = new Set(results[assIdx].fileClaims);
|
|
220
|
+
const filesB = results[decIdx].fileClaims;
|
|
221
|
+
const hasOverlap = filesB.some((f) => filesA.has(f));
|
|
222
|
+
if (filesA.size > 0 && filesB.length > 0 && !hasOverlap) continue;
|
|
223
|
+
|
|
224
|
+
// Check negation patterns
|
|
225
|
+
const negInAssumption =
|
|
226
|
+
assumption.includes("not ") &&
|
|
227
|
+
assumption
|
|
228
|
+
.replace("not ", "")
|
|
229
|
+
.split(/\s+/)
|
|
230
|
+
.some((w) => decision.includes(w));
|
|
231
|
+
const negInDecision =
|
|
232
|
+
decision.includes("not ") &&
|
|
233
|
+
decision
|
|
234
|
+
.replace("not ", "")
|
|
235
|
+
.split(/\s+/)
|
|
236
|
+
.some((w) => assumption.includes(w));
|
|
237
|
+
|
|
238
|
+
if (negInAssumption || negInDecision) {
|
|
239
|
+
conflicts.push({
|
|
240
|
+
type: "assumption_violation",
|
|
241
|
+
description: `Sibling ${assIdx}'s assumption may conflict with sibling ${decIdx}'s decision`,
|
|
242
|
+
involved: [assIdx, decIdx],
|
|
243
|
+
resolution: "verify_with_parent",
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return conflicts;
|
|
250
|
+
}
|