opencode-swarm 7.86.0 → 7.87.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.
Files changed (61) hide show
  1. package/dist/cli/{capability-probe-jevmgwmf.js → capability-probe-wsjzcp48.js} +2 -2
  2. package/dist/cli/{config-doctor-zejarrr6.js → config-doctor-6h64pn8n.js} +4 -4
  3. package/dist/cli/{dispatch-k86d928w.js → dispatch-kb69qw40.js} +3 -3
  4. package/dist/cli/{evidence-summary-service-g2znnd33.js → evidence-summary-service-gg5m9z57.js} +4 -4
  5. package/dist/cli/{guardrail-explain-rtd1x26f.js → guardrail-explain-wb1cj312.js} +13 -13
  6. package/dist/cli/{guardrail-log-80116wmz.js → guardrail-log-eegabqcp.js} +5 -5
  7. package/dist/cli/{index-jwz50183.js → index-0m44n5qv.js} +14 -14
  8. package/dist/cli/{index-0sxvwjt0.js → index-1cb4wxnm.js} +2 -2
  9. package/dist/cli/{index-zfsbaaqh.js → index-5e4e2hvv.js} +1 -1
  10. package/dist/cli/{index-vq2321gg.js → index-5hvbw5xh.js} +2 -2
  11. package/dist/cli/{index-5cb86007.js → index-5vpe6vq9.js} +1 -1
  12. package/dist/cli/{index-red8fm8p.js → index-89xjr3h4.js} +1162 -214
  13. package/dist/cli/{index-f8r50m3h.js → index-adz3nk9b.js} +2 -2
  14. package/dist/cli/{index-7r2b453y.js → index-f13d3b69.js} +2 -2
  15. package/dist/cli/{index-ckntc5gf.js → index-gn8n22th.js} +2 -2
  16. package/dist/cli/{index-hw9b2xng.js → index-q9h0wb04.js} +36 -3
  17. package/dist/cli/{index-d9fbxaqd.js → index-s8bj492g.js} +1 -1
  18. package/dist/cli/{index-hz59hg4h.js → index-v4fcn4tr.js} +1 -1
  19. package/dist/cli/{index-eb85wtx9.js → index-vqyfscxd.js} +2 -2
  20. package/dist/cli/{index-5q66xc88.js → index-wv2yj8ka.js} +2598 -1406
  21. package/dist/cli/{index-yx44zd0p.js → index-zgwm4ryv.js} +9 -1
  22. package/dist/cli/index.js +12 -12
  23. package/dist/cli/{pending-delegations-rd40tv9s.js → pending-delegations-35fvcj7z.js} +3 -3
  24. package/dist/cli/{pr-subscriptions-y1nn36e5.js → pr-subscriptions-b18n1yd8.js} +4 -4
  25. package/dist/cli/{schema-8d32b2v6.js → schema-84146tvk.js} +3 -1
  26. package/dist/cli/{skill-generator-a5ehggyg.js → skill-generator-3pvpk4y2.js} +2 -2
  27. package/dist/commands/coupling.d.ts +36 -0
  28. package/dist/commands/epic.d.ts +52 -0
  29. package/dist/commands/registry.d.ts +18 -2
  30. package/dist/config/constants.d.ts +1 -0
  31. package/dist/config/schema.d.ts +145 -0
  32. package/dist/git/branch.d.ts +22 -1
  33. package/dist/hooks/delegation-gate/worktree-merge-status.d.ts +86 -0
  34. package/dist/index.js +8401 -5792
  35. package/dist/memory/schema.d.ts +3 -3
  36. package/dist/plan/manager.d.ts +10 -0
  37. package/dist/state.d.ts +16 -0
  38. package/dist/tools/epic-plan-waves.d.ts +79 -0
  39. package/dist/tools/epic-record-divergence.d.ts +73 -0
  40. package/dist/tools/epic-run-phase.d.ts +179 -0
  41. package/dist/tools/index.d.ts +3 -0
  42. package/dist/tools/manifest.d.ts +3 -0
  43. package/dist/tools/tool-metadata.d.ts +12 -0
  44. package/dist/turbo/epic/activation.d.ts +193 -0
  45. package/dist/turbo/epic/calibration-engine.d.ts +88 -0
  46. package/dist/turbo/epic/calibration.d.ts +65 -0
  47. package/dist/turbo/epic/cochange-conflict.d.ts +79 -0
  48. package/dist/turbo/epic/cochange-source.d.ts +80 -0
  49. package/dist/turbo/epic/coupling-report.d.ts +85 -0
  50. package/dist/turbo/epic/divergence-recorder.d.ts +112 -0
  51. package/dist/turbo/epic/index.d.ts +24 -0
  52. package/dist/turbo/epic/promotion-evidence.d.ts +42 -0
  53. package/dist/turbo/epic/state.d.ts +85 -0
  54. package/dist/turbo/epic/task-commit.d.ts +110 -0
  55. package/dist/turbo/epic/upstream-commits.d.ts +82 -0
  56. package/dist/turbo/epic/wave-planner.d.ts +83 -0
  57. package/dist/turbo/lean/partition-common.d.ts +85 -0
  58. package/dist/turbo/lean/planner.d.ts +12 -20
  59. package/dist/utils/index.d.ts +1 -1
  60. package/dist/utils/logger.d.ts +19 -0
  61. package/package.json +1 -1
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Auto-commit on task completion — Rule 2 of the greenfield-smart redesign.
3
+ *
4
+ * When Epic Mode is active for the session and the project is a git repo,
5
+ * `update_task_status` calls `commitTaskCompletion` after a task transitions
6
+ * to `completed` and the durable plan write has succeeded. The resulting
7
+ * commit serves two purposes:
8
+ *
9
+ * 1. **Greenfield gate progress.** Each completed-and-committed task
10
+ * advances `commitsObserved` so the activation gate
11
+ * (`src/turbo/epic/activation.ts`) eventually opens. Without this,
12
+ * an Epic-only workflow never produces commits and the gate
13
+ * permanently blocks parallel promotion — the exact failure mode
14
+ * Rule 4 of the redesign identified.
15
+ *
16
+ * 2. **Parallel-eligibility evidence (Rule 3).** Downstream tasks can
17
+ * require their `depends:` upstream to be *committed* (not just
18
+ * marked complete) before they fan out. The commit message format
19
+ * `swarm(task <id>): ...` is the searchable marker the lane
20
+ * planner consumes in `upstream-commits.ts`.
21
+ *
22
+ * Failure handling: every step degrades non-fatally. A failed commit must
23
+ * never block the durable task-status update — the plan ledger is the
24
+ * authoritative source (AGENTS.md #5), git is a downstream artifact.
25
+ *
26
+ * Subprocess discipline: delegates to `src/git/branch.ts`, which already
27
+ * enforces AGENTS.md #3 (explicit cwd, bounded timeout, array-form spawn,
28
+ * non-interactive). This module adds no new subprocess primitives.
29
+ */
30
+ /** Result of a single task-commit attempt. */
31
+ export interface CommitTaskCompletionResult {
32
+ /**
33
+ * `true` when a `swarm(task <id>):` marker for this taskId is present
34
+ * in git history at function exit — whether this call produced it
35
+ * (`reason: 'success'`) or whether an earlier call did
36
+ * (`reason: 'idempotent-skip'`).
37
+ *
38
+ * Phase 17 (B.M9): pre-Phase-17 the `'already-committed'` reason
39
+ * returned `committed: false`, self-contradicting ("not committed
40
+ * because already committed"). Architect LLMs interpreted the
41
+ * `false` as a failure and retried, producing log noise. The fixed
42
+ * semantic: `committed` answers "is the marker in git for this
43
+ * taskId now?" — yes for both the fresh-write and the idempotent
44
+ * skip paths.
45
+ */
46
+ committed: boolean;
47
+ reason: 'no-git' | 'commit-failed' | 'success' | 'idempotent-skip';
48
+ sha?: string;
49
+ error?: string;
50
+ }
51
+ export declare function formatTaskCommitMessage(taskId: string, description?: string): string;
52
+ export declare function commitTaskCompletion(directory: string, taskId: string, description?: string, scopePaths?: string[]): Promise<CommitTaskCompletionResult>;
53
+ /**
54
+ * DI seam — production code calls through `_internals.<name>` so tests
55
+ * substitute deterministic doubles without `mock.module`'s cross-file
56
+ * leak (AGENTS.md invariant 7). Restore in `afterEach`.
57
+ */
58
+ export declare const _internals: {
59
+ isGitRepo: (cwd: string) => boolean;
60
+ /**
61
+ * Stage exactly the declared scope paths for this task. The trailing
62
+ * `:(exclude).swarm` + `:(exclude).swarm/**` pathspecs are belt-and-
63
+ * suspenders against AGENTS.md #4 even when the architect's scope
64
+ * declaration accidentally points into `.swarm/`. We do NOT rely on
65
+ * the user's `.gitignore`: a single misconfigured project would
66
+ * otherwise commit prompts, ledgers, telemetry, and evidence into
67
+ * git history every time Rule 2 fires.
68
+ *
69
+ * Missing pathspecs (declared scope points to a non-existent file) are
70
+ * left to surface as a `commit-failed` reason — better than silent
71
+ * staging skip, since it tells the user their scope declaration is
72
+ * stale. Rule 2's non-fatal contract means the plan-write still wins.
73
+ */
74
+ stageScopedPaths: (cwd: string, paths: string[]) => void;
75
+ /**
76
+ * `--allow-empty` variant of commit. We don't expose this in
77
+ * `src/git/branch.ts` because it's specific to the task-completion
78
+ * marker semantics — a normal commit should fail on empty trees to
79
+ * surface bugs. Here we explicitly want the marker.
80
+ *
81
+ * Phase 8: `--no-verify` skips `pre-commit`, `commit-msg`, and
82
+ * `pre-commit-msg` hooks. Rule 2's commits are protocol markers, not
83
+ * user-authored content — running Biome/typecheck/lint on every task
84
+ * completion would add minutes of wall-clock per task and, worse,
85
+ * could block the marker entirely on a repo with a strict pre-commit
86
+ * gate. Plan ledger remains authoritative; the commit is the audit
87
+ * trail, not the gate.
88
+ */
89
+ commitAllowEmpty: (cwd: string, message: string) => void;
90
+ gitHeadSha: (cwd: string) => string;
91
+ /**
92
+ * Returns true when a `swarm(task <id>):` marker subject for this
93
+ * taskId already exists anywhere in git history. Used by the
94
+ * idempotency guard above so repeat completion calls don't mint
95
+ * duplicate markers.
96
+ *
97
+ * Implementation: `git log --grep=<pattern> -F` is NOT used (it
98
+ * fixed-string-matches the whole subject); instead we anchor the
99
+ * regex with `--extended-regexp` and bound the scan with `-n 1` so a
100
+ * single match suffices. Returns false on any git failure — the
101
+ * caller treats that as "unknown" and proceeds.
102
+ */
103
+ /**
104
+ * Phase 11 (B5): async sleep used by `commitTaskCompletion`'s
105
+ * retry loop. Routed through `_internals` so tests can substitute
106
+ * a no-op stub and not actually wait during fast-path unit tests.
107
+ */
108
+ sleep: (ms: number) => Promise<void>;
109
+ hasExistingTaskCommit: (cwd: string, taskId: string) => boolean;
110
+ };
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Upstream-commit predicate — Rule 3 of the greenfield-smart redesign.
3
+ *
4
+ * Given a project directory, returns a fast `(taskId) => boolean` predicate
5
+ * that answers "has this task been committed?" The lane planner consults
6
+ * this when evaluating cross-batch dependencies: a downstream task is
7
+ * parallel-eligible only when every `depends:` upstream that lives in a
8
+ * prior phase batch is already in git HEAD's history.
9
+ *
10
+ * Why this matters: without it, the planner treats any dep not in the
11
+ * current task batch as implicitly satisfied (the existing behavior in
12
+ * `src/turbo/lean/planner.ts:381-390`). That's fine when the prior batch
13
+ * actually finished cleanly, but it doesn't distinguish "marked complete"
14
+ * from "marked complete *and* the work is in version control". Rule 3
15
+ * insists on the stronger condition so parallel coders can't inherit an
16
+ * uncommitted upstream worktree.
17
+ *
18
+ * Source format: `commitTaskCompletion` writes commit subjects shaped like
19
+ * `swarm(task <id>): <description>` (see `./task-commit.ts:formatTaskCommitMessage`).
20
+ * This module parses the `<id>` from those subjects.
21
+ *
22
+ * Boundedness (AGENTS.md #3): subprocess timeout matches the rest of git
23
+ * helpers (30s); `--max-count` caps the log scan; failures degrade to a
24
+ * permissive predicate so the planner does not regress when git is broken.
25
+ */
26
+ export interface BuildUpstreamCommitsOptions {
27
+ /** Override the log scan window. Default: 10,000. */
28
+ maxCommits?: number;
29
+ }
30
+ /**
31
+ * Eagerly read git log once and return a fast `(taskId) => boolean`
32
+ * predicate the lane planner uses for cross-batch upstream-commit checks.
33
+ *
34
+ * Single evidence source: a `swarm(task <id>):` commit subject in git
35
+ * log, produced by Rule 2's `commitTaskCompletion`.
36
+ *
37
+ * History note: an earlier revision OR'd in a plan-ledger fallback (any
38
+ * task with `status: completed` in `.swarm/plan.json` was treated as
39
+ * committed) to guard against a hypothetical deadlock where `commit-
40
+ * TaskCompletion` failed silently. Phase 5 of the 2026-06-03 corrective
41
+ * plan made Rule 2 reliable on every completion path by centralizing
42
+ * the invocation in `plan/manager.updateTaskStatus` — so the guard's
43
+ * premise no longer holds, and keeping the fallback would defeat Rule 3's
44
+ * own purpose (distinguishing "marked complete" from "in git history").
45
+ * Removed in Phase 6.
46
+ *
47
+ * Failure mode:
48
+ * - Git log read fails (no git, spawn error, timeout) → predicate
49
+ * returns `true` for everything (permissive). The lane planner falls
50
+ * back to its legacy "cross-batch dep implicitly satisfied" behavior,
51
+ * which is the pre-Rule-3 semantics. Better legacy than wedged in a
52
+ * broken environment.
53
+ */
54
+ export declare function buildIsUpstreamCommitted(directory: string, options?: BuildUpstreamCommitsOptions): (taskId: string) => boolean;
55
+ /**
56
+ * Phase 12 (B10) — same predicate construction as `buildIsUpstreamCommitted`
57
+ * but exposes whether the git-log read failed. Callers that need to FAIL
58
+ * CLOSED on a broken git environment (e.g. the Phase 10 activation gate,
59
+ * where the predicate is the only safety signal) use `gitFailed` to pick
60
+ * a stricter policy; callers that can tolerate "I don't know" fall-open
61
+ * (e.g. Rule 3 at the lane planner, where wave ordering is the backstop)
62
+ * continue using `buildIsUpstreamCommitted` directly.
63
+ *
64
+ * The two-tier API exists because the original permissive degradation
65
+ * was correct for Rule 3 (no regression vs pre-Rule-3 semantics) but
66
+ * inverted the safety polarity for Phase 10 (which has no Path-B
67
+ * fallback after the commit-count floor was retired).
68
+ */
69
+ export interface UpstreamCommittedEvidence {
70
+ predicate: (taskId: string) => boolean;
71
+ /** True when the git-log read threw — predicate is the permissive fallback. */
72
+ gitFailed: boolean;
73
+ }
74
+ export declare function buildIsUpstreamCommittedWithStatus(directory: string, options?: BuildUpstreamCommitsOptions): UpstreamCommittedEvidence;
75
+ /**
76
+ * DI seam — production code routes the git-log read through `_internals`
77
+ * so tests can substitute deterministic doubles without `mock.module`
78
+ * (AGENTS.md invariant 7).
79
+ */
80
+ export declare const _internals: {
81
+ readGitLogSubjects: (cwd: string, max: number) => string;
82
+ };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Epic Mode Wave Planner.
3
+ *
4
+ * The wave planner partitions a phase's pending tasks into ordered *waves*.
5
+ * A wave is a set of tasks that:
6
+ * - have all their dependencies satisfied by tasks in completed waves, AND
7
+ * - have mutually disjoint declared scopes (no two tasks in the same wave
8
+ * touch a shared file or parent/child path).
9
+ *
10
+ * Architectural contrast with the lane planner:
11
+ * - Lane planner: greedy fill into a fixed number of independent serial
12
+ * chains. Branching DAGs (e.g. `A → B → {C, D, E}`) collapse into a
13
+ * single chain because the cross-lane-dep rule forbids C/D/E from
14
+ * living in a different lane than A/B.
15
+ * - Wave planner: emits a sequence of concurrent groups. The same DAG
16
+ * becomes `wave 1: [A], wave 2: [B], wave 3: [C, D, E]`. Within a wave
17
+ * the architect dispatches one Task per taskId — all in one message —
18
+ * and the next wave starts only when the prior one is done.
19
+ *
20
+ * The two planners share `runPartitionPreflight` from `partition-common.ts`
21
+ * so classification (global/protected/no-scope/normal), scope resolution,
22
+ * and topological sort are identical. Divergence is intentional and lives
23
+ * only in the assignment loop below.
24
+ */
25
+ import type { LeanTurboConfig } from '../../config/schema';
26
+ import { type PlanPhase } from '../lean/partition-common';
27
+ import type { LeanTurboDegradedTask } from '../lean/state';
28
+ /**
29
+ * A single wave in the Epic plan. Tasks in a wave run concurrently; the next
30
+ * wave starts only after all tasks in this wave complete.
31
+ */
32
+ export interface EpicWave {
33
+ /** 1-indexed wave number (display + ordering). */
34
+ waveId: number;
35
+ /** Tasks in this wave. Architect dispatches one Task per id, all in one message. */
36
+ taskIds: string[];
37
+ /**
38
+ * Union of declared scope files across the wave. Informational — Epic
39
+ * Mode does NOT acquire file locks (architect-driven dispatch goes
40
+ * directly through `Task`, bypassing the lean runner's lock path).
41
+ * Used for evidence/divergence reporting.
42
+ */
43
+ files: string[];
44
+ }
45
+ /**
46
+ * The complete wave plan produced by `planEpicWaves`.
47
+ */
48
+ export interface EpicWavePlan {
49
+ /** The phase number this plan covers. */
50
+ phase: number;
51
+ /** Unique identifier for this wave plan. */
52
+ planId: string;
53
+ /** Ordered list of waves. Empty when every task degraded or serialized. */
54
+ waves: EpicWave[];
55
+ /** Tasks that were serialized (cycles, no-scope, invalid-scope, protected with serialize policy). */
56
+ serializedTasks: string[];
57
+ /** Tasks that were degraded (global files, protected paths, Rule-3 leftovers). */
58
+ degradedTasks: LeanTurboDegradedTask[];
59
+ /** Human-readable summary when all tasks ended up degraded. */
60
+ degradationSummary?: string;
61
+ /** Total number of pending tasks the planner saw (before assignment). */
62
+ totalPendingTasks: number;
63
+ /** Sum of `waves[*].taskIds.length` — tasks that will actually run concurrently in a wave. */
64
+ totalConcurrentTasks: number;
65
+ }
66
+ /**
67
+ * Partition phase tasks into ordered concurrent waves.
68
+ *
69
+ * @param directory - Project root directory
70
+ * @param phaseNumber - Phase number to plan
71
+ * @param plan - The full plan object (from `.swarm/plan.json`)
72
+ * @param config - Lean Turbo configuration (reused for risk/conflict policy)
73
+ * @param scopes - Optional pre-loaded scopes map (taskId -> file paths)
74
+ * @param isUpstreamCommitted - Optional Rule-3 predicate (greenfield-smart).
75
+ * When supplied, a cross-batch dependency (a `depends:` upstream NOT
76
+ * in this planning call's task set) is treated as satisfied only if
77
+ * the predicate returns `true`. Without it, legacy semantics apply
78
+ * (cross-batch deps implicitly satisfied).
79
+ * @returns Complete wave plan with ordered concurrent groups.
80
+ */
81
+ export declare function planEpicWaves(directory: string, phaseNumber: number, plan: {
82
+ phases: PlanPhase[];
83
+ }, config: LeanTurboConfig, scopes?: Record<string, string[]>, isUpstreamCommitted?: (taskId: string) => boolean): EpicWavePlan;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Shared partition primitives for Lean Turbo's lane planner AND Epic Mode's
3
+ * wave planner. Both planners run the same three preflight steps:
4
+ *
5
+ * 1. Resolve declared scopes (or files_touched fallback) per pending task.
6
+ * 2. Classify each task by file risk (global / protected / no-scope / normal).
7
+ * 3. Topologically sort with cycle detection so a downstream task can never
8
+ * be released before its upstream.
9
+ *
10
+ * They diverge only at the assignment step:
11
+ * - Lane planner: greedy fill into a fixed number of serial chains.
12
+ * - Wave planner: emit ordered concurrent groups whose membership is gated
13
+ * by inter-task scope disjointness.
14
+ *
15
+ * Owning the preflight in one place guarantees both planners produce
16
+ * identical classifications and sort orders for the same inputs.
17
+ */
18
+ import type { LeanTurboConfig } from '../../config/schema';
19
+ import { type TaskRiskAssessment } from './risk';
20
+ /**
21
+ * A single task within a plan phase. Matches `.swarm/plan.json`.
22
+ */
23
+ export interface PlanTask {
24
+ id: string;
25
+ description: string;
26
+ status: 'pending' | 'in_progress' | 'completed' | 'blocked';
27
+ depends?: string[];
28
+ files_touched?: string[];
29
+ }
30
+ /**
31
+ * A phase within a plan, containing multiple tasks.
32
+ */
33
+ export interface PlanPhase {
34
+ id: number;
35
+ name: string;
36
+ tasks: PlanTask[];
37
+ }
38
+ export type ClassifiedTask = {
39
+ task: PlanTask;
40
+ files: string[];
41
+ hasDeclaredScope: boolean;
42
+ category: TaskRiskAssessment['category'];
43
+ conflictReason?: string;
44
+ };
45
+ export interface PartitionPreflight {
46
+ /** Topologically sorted, lexicographically tie-broken. */
47
+ sortedTasks: ClassifiedTask[];
48
+ /** taskId -> ClassifiedTask for O(1) lookup. */
49
+ taskMap: Map<string, ClassifiedTask>;
50
+ /** Tasks whose deps form a cycle. Callers must fail-closed: serialize them. */
51
+ tasksInCycle: Set<string>;
52
+ }
53
+ /**
54
+ * Validate and normalize a task's declared scope.
55
+ *
56
+ * Symlink containment is NOT enforced here — the lock layer resolves symlinks
57
+ * at acquisition time. This lets architects declare scopes with symlinks for
58
+ * convenience without compromising actual file-write safety.
59
+ *
60
+ * @returns Tuple of [validFiles, invalidCount]
61
+ */
62
+ export declare function getValidatedFiles(files: string[], directory: string): [string[], number];
63
+ /**
64
+ * Run the shared preflight: resolve scopes, classify by risk, topo-sort with
65
+ * cycle detection.
66
+ *
67
+ * The same `(directory, pendingTasks, config, scopes)` produces the same
68
+ * `PartitionPreflight` from both planners.
69
+ */
70
+ export declare function runPartitionPreflight(directory: string, pendingTasks: PlanTask[], config: LeanTurboConfig, scopes?: Record<string, string[]>): PartitionPreflight;
71
+ /**
72
+ * Build the predicate that a task's dependencies are all satisfied.
73
+ *
74
+ * Rule 3 (greenfield-smart): when `isUpstreamCommitted` is supplied, a
75
+ * cross-batch dependency (a `depends:` upstream NOT in the current planning
76
+ * call's task set — typically completed in a prior phase) is treated as
77
+ * satisfied **only** if the predicate returns `true`. Without the predicate
78
+ * the legacy semantics apply: cross-batch deps are implicitly satisfied.
79
+ */
80
+ export declare function makeDependencySatisfactionChecker(taskMap: Map<string, ClassifiedTask>, assignedTasks: Set<string>, isUpstreamCommitted?: (taskId: string) => boolean): (task: ClassifiedTask) => boolean;
81
+ /**
82
+ * Return the next group of tasks ready for assignment: not yet assigned and
83
+ * all dependencies satisfied. Lexicographically sorted for determinism.
84
+ */
85
+ export declare function getReadyTasks(sortedTasks: ClassifiedTask[], assignedTasks: Set<string>, isSatisfied: (task: ClassifiedTask) => boolean): ClassifiedTask[];
@@ -48,27 +48,10 @@
48
48
  * before conflict detection. This ensures consistent behavior across platforms.
49
49
  */
50
50
  import type { LeanTurboConfig } from '../../config/schema';
51
+ import { type PlanPhase } from './partition-common';
51
52
  import type { LeanTurboCounters, LeanTurboDegradedTask, LeanTurboLane } from './state';
52
53
  export { GLOBAL_FILES_LIST, isGlobalFile, isPathSafe, isProtectedPath, normalizePath, PROTECTED_PATTERNS_LIST, pathsConflict, readTaskScopes, } from './conflicts';
53
- /**
54
- * A single task within a plan phase.
55
- * Matches the structure stored in .swarm/plan.json.
56
- */
57
- export interface PlanTask {
58
- id: string;
59
- description: string;
60
- status: 'pending' | 'in_progress' | 'completed' | 'blocked';
61
- depends?: string[];
62
- files_touched?: string[];
63
- }
64
- /**
65
- * A phase within a plan, containing multiple tasks.
66
- */
67
- export interface PlanPhase {
68
- id: number;
69
- name: string;
70
- tasks: PlanTask[];
71
- }
54
+ export type { PlanPhase, PlanTask } from './partition-common';
72
55
  /**
73
56
  * The complete lane plan produced by `planLeanTurboLanes`.
74
57
  * Describes how phase tasks are partitioned into parallel lanes.
@@ -108,8 +91,17 @@ export interface LeanTurboLanePlan {
108
91
  * @param plan - The full plan object (from .swarm/plan.json)
109
92
  * @param config - Lean Turbo configuration
110
93
  * @param scopes - Optional pre-loaded scopes map (taskId -> file paths)
94
+ * @param isUpstreamCommitted - Optional Rule-3 predicate (greenfield-smart
95
+ * redesign). When supplied, a cross-batch dependency (a `depends:`
96
+ * upstream not present in this planning call's task set — typically
97
+ * completed in a prior phase) is treated as satisfied **only** if
98
+ * the predicate returns `true`. Production callers build this from
99
+ * `buildIsUpstreamCommitted(directory)` so the check resolves to
100
+ * "is there a `swarm(task <id>)` commit in HEAD". When undefined
101
+ * the planner falls back to its legacy behavior (cross-batch deps
102
+ * are implicitly satisfied) for backward compatibility.
111
103
  * @returns Complete lane plan with lanes, degraded tasks, and counters
112
104
  */
113
105
  export declare function planLeanTurboLanes(directory: string, phaseNumber: number, plan: {
114
106
  phases: PlanPhase[];
115
- }, config: LeanTurboConfig, scopes?: Record<string, string[]>): LeanTurboLanePlan;
107
+ }, config: LeanTurboConfig, scopes?: Record<string, string[]>, isUpstreamCommitted?: (taskId: string) => boolean): LeanTurboLanePlan;
@@ -1,4 +1,4 @@
1
1
  export { CLIError, ConfigError, HookError, SwarmError, ToolError, } from './errors';
2
- export { error, log, warn } from './logger';
2
+ export { criticalWarn, error, log, warn } from './logger';
3
3
  export { deepMerge, MAX_MERGE_DEPTH } from './merge';
4
4
  export { escapeRegex, simpleGlobToRegex } from './regex';
@@ -1,6 +1,24 @@
1
1
  declare function isDebug(): boolean;
2
2
  export declare function log(message: string, data?: unknown): void;
3
3
  export declare function warn(message: string, data?: unknown): void;
4
+ /**
5
+ * Phase 15 (B34): ALWAYS-EMITTED warning. Use this — not `warn()` — for
6
+ * signals the operator MUST see during a live benchmark or production
7
+ * run: Rule 2 commit failures, Phase 10 predecessor-evidence anomalies,
8
+ * Phase 13 git-log-degraded states, Phase 14 lane-planning-blocked
9
+ * correlations against `epic-promotions.jsonl`, phantom-dep typos.
10
+ *
11
+ * Rationale: `warn()` is gated behind `OPENCODE_SWARM_DEBUG=1`. Until
12
+ * Phase 15 every diagnostic signal Phases 0-14 added was silenced
13
+ * outside debug runs — including the audit-trail correlation log that
14
+ * makes B22 wedges detectable. That defeats the whole point of those
15
+ * signals.
16
+ *
17
+ * `criticalWarn` writes to stderr (so it survives stdout redirection
18
+ * for grading scripts) with a `CRITICAL-WARN` tag distinct from
19
+ * regular `WARN` so log scrapers can filter for must-act-on lines.
20
+ */
21
+ export declare function criticalWarn(message: string, data?: unknown): void;
4
22
  export declare function error(message: string, data?: unknown): void;
5
23
  /**
6
24
  * DI seam for testability. Contains all test-mocked exports.
@@ -10,6 +28,7 @@ export declare const _internals: {
10
28
  isDebug: typeof isDebug;
11
29
  log: typeof log;
12
30
  warn: typeof warn;
31
+ criticalWarn: typeof criticalWarn;
13
32
  error: typeof error;
14
33
  };
15
34
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.86.0",
3
+ "version": "7.87.0",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",