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.
- package/dist/cli/{capability-probe-jevmgwmf.js → capability-probe-wsjzcp48.js} +2 -2
- package/dist/cli/{config-doctor-zejarrr6.js → config-doctor-6h64pn8n.js} +4 -4
- package/dist/cli/{dispatch-k86d928w.js → dispatch-kb69qw40.js} +3 -3
- package/dist/cli/{evidence-summary-service-g2znnd33.js → evidence-summary-service-gg5m9z57.js} +4 -4
- package/dist/cli/{guardrail-explain-rtd1x26f.js → guardrail-explain-wb1cj312.js} +13 -13
- package/dist/cli/{guardrail-log-80116wmz.js → guardrail-log-eegabqcp.js} +5 -5
- package/dist/cli/{index-jwz50183.js → index-0m44n5qv.js} +14 -14
- package/dist/cli/{index-0sxvwjt0.js → index-1cb4wxnm.js} +2 -2
- package/dist/cli/{index-zfsbaaqh.js → index-5e4e2hvv.js} +1 -1
- package/dist/cli/{index-vq2321gg.js → index-5hvbw5xh.js} +2 -2
- package/dist/cli/{index-5cb86007.js → index-5vpe6vq9.js} +1 -1
- package/dist/cli/{index-red8fm8p.js → index-89xjr3h4.js} +1162 -214
- package/dist/cli/{index-f8r50m3h.js → index-adz3nk9b.js} +2 -2
- package/dist/cli/{index-7r2b453y.js → index-f13d3b69.js} +2 -2
- package/dist/cli/{index-ckntc5gf.js → index-gn8n22th.js} +2 -2
- package/dist/cli/{index-hw9b2xng.js → index-q9h0wb04.js} +36 -3
- package/dist/cli/{index-d9fbxaqd.js → index-s8bj492g.js} +1 -1
- package/dist/cli/{index-hz59hg4h.js → index-v4fcn4tr.js} +1 -1
- package/dist/cli/{index-eb85wtx9.js → index-vqyfscxd.js} +2 -2
- package/dist/cli/{index-5q66xc88.js → index-wv2yj8ka.js} +2598 -1406
- package/dist/cli/{index-yx44zd0p.js → index-zgwm4ryv.js} +9 -1
- package/dist/cli/index.js +12 -12
- package/dist/cli/{pending-delegations-rd40tv9s.js → pending-delegations-35fvcj7z.js} +3 -3
- package/dist/cli/{pr-subscriptions-y1nn36e5.js → pr-subscriptions-b18n1yd8.js} +4 -4
- package/dist/cli/{schema-8d32b2v6.js → schema-84146tvk.js} +3 -1
- package/dist/cli/{skill-generator-a5ehggyg.js → skill-generator-3pvpk4y2.js} +2 -2
- package/dist/commands/coupling.d.ts +36 -0
- package/dist/commands/epic.d.ts +52 -0
- package/dist/commands/registry.d.ts +18 -2
- package/dist/config/constants.d.ts +1 -0
- package/dist/config/schema.d.ts +145 -0
- package/dist/git/branch.d.ts +22 -1
- package/dist/hooks/delegation-gate/worktree-merge-status.d.ts +86 -0
- package/dist/index.js +8401 -5792
- package/dist/memory/schema.d.ts +3 -3
- package/dist/plan/manager.d.ts +10 -0
- package/dist/state.d.ts +16 -0
- package/dist/tools/epic-plan-waves.d.ts +79 -0
- package/dist/tools/epic-record-divergence.d.ts +73 -0
- package/dist/tools/epic-run-phase.d.ts +179 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/manifest.d.ts +3 -0
- package/dist/tools/tool-metadata.d.ts +12 -0
- package/dist/turbo/epic/activation.d.ts +193 -0
- package/dist/turbo/epic/calibration-engine.d.ts +88 -0
- package/dist/turbo/epic/calibration.d.ts +65 -0
- package/dist/turbo/epic/cochange-conflict.d.ts +79 -0
- package/dist/turbo/epic/cochange-source.d.ts +80 -0
- package/dist/turbo/epic/coupling-report.d.ts +85 -0
- package/dist/turbo/epic/divergence-recorder.d.ts +112 -0
- package/dist/turbo/epic/index.d.ts +24 -0
- package/dist/turbo/epic/promotion-evidence.d.ts +42 -0
- package/dist/turbo/epic/state.d.ts +85 -0
- package/dist/turbo/epic/task-commit.d.ts +110 -0
- package/dist/turbo/epic/upstream-commits.d.ts +82 -0
- package/dist/turbo/epic/wave-planner.d.ts +83 -0
- package/dist/turbo/lean/partition-common.d.ts +85 -0
- package/dist/turbo/lean/planner.d.ts +12 -20
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/logger.d.ts +19 -0
- 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[]
|
|
107
|
+
}, config: LeanTurboConfig, scopes?: Record<string, string[]>, isUpstreamCommitted?: (taskId: string) => boolean): LeanTurboLanePlan;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -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.
|
|
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",
|