opencode-swarm 6.69.0 → 6.70.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/index.js CHANGED
@@ -16947,7 +16947,7 @@ var require_signal_exit = __commonJS((exports, module) => {
16947
16947
  emitter.count -= 1;
16948
16948
  };
16949
16949
  module.exports.unload = unload;
16950
- emit = function emit2(event, code, signal) {
16950
+ emit2 = function emit3(event, code, signal) {
16951
16951
  if (emitter.emitted[event]) {
16952
16952
  return;
16953
16953
  }
@@ -16963,8 +16963,8 @@ var require_signal_exit = __commonJS((exports, module) => {
16963
16963
  var listeners = process3.listeners(sig);
16964
16964
  if (listeners.length === emitter.count) {
16965
16965
  unload();
16966
- emit("exit", null, sig);
16967
- emit("afterexit", null, sig);
16966
+ emit2("exit", null, sig);
16967
+ emit2("afterexit", null, sig);
16968
16968
  if (isWin && sig === "SIGHUP") {
16969
16969
  sig = "SIGINT";
16970
16970
  }
@@ -17000,8 +17000,8 @@ var require_signal_exit = __commonJS((exports, module) => {
17000
17000
  return;
17001
17001
  }
17002
17002
  process3.exitCode = code || 0;
17003
- emit("exit", process3.exitCode, null);
17004
- emit("afterexit", process3.exitCode, null);
17003
+ emit2("exit", process3.exitCode, null);
17004
+ emit2("afterexit", process3.exitCode, null);
17005
17005
  originalProcessReallyExit.call(process3, process3.exitCode);
17006
17006
  };
17007
17007
  originalProcessEmit = process3.emit;
@@ -17011,8 +17011,8 @@ var require_signal_exit = __commonJS((exports, module) => {
17011
17011
  process3.exitCode = arg;
17012
17012
  }
17013
17013
  var ret = originalProcessEmit.apply(this, arguments);
17014
- emit("exit", process3.exitCode, null);
17015
- emit("afterexit", process3.exitCode, null);
17014
+ emit2("exit", process3.exitCode, null);
17015
+ emit2("afterexit", process3.exitCode, null);
17016
17016
  return ret;
17017
17017
  } else {
17018
17018
  return originalProcessEmit.apply(this, arguments);
@@ -17025,7 +17025,7 @@ var require_signal_exit = __commonJS((exports, module) => {
17025
17025
  var EE;
17026
17026
  var emitter;
17027
17027
  var unload;
17028
- var emit;
17028
+ var emit2;
17029
17029
  var sigListeners;
17030
17030
  var loaded;
17031
17031
  var load;
@@ -19205,7 +19205,8 @@ var AgentAuthorityRuleSchema = exports_external.object({
19205
19205
  });
19206
19206
  var AuthorityConfigSchema = exports_external.object({
19207
19207
  enabled: exports_external.boolean().default(true),
19208
- rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({})
19208
+ rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({}),
19209
+ universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([])
19209
19210
  });
19210
19211
  var CouncilConfigSchema = exports_external.object({
19211
19212
  enabled: exports_external.boolean().default(false),
@@ -19464,6 +19465,416 @@ init_manager2();
19464
19465
 
19465
19466
  // src/state.ts
19466
19467
  init_plan_schema();
19468
+
19469
+ // src/hooks/delegation-gate.ts
19470
+ init_telemetry();
19471
+
19472
+ // node_modules/quick-lru/index.js
19473
+ class QuickLRU extends Map {
19474
+ #size = 0;
19475
+ #cache = new Map;
19476
+ #oldCache = new Map;
19477
+ #maxSize;
19478
+ #maxAge;
19479
+ #onEviction;
19480
+ constructor(options = {}) {
19481
+ super();
19482
+ if (!(options.maxSize && options.maxSize > 0)) {
19483
+ throw new TypeError("`maxSize` must be a number greater than 0");
19484
+ }
19485
+ if (typeof options.maxAge === "number" && options.maxAge === 0) {
19486
+ throw new TypeError("`maxAge` must be a number greater than 0");
19487
+ }
19488
+ this.#maxSize = options.maxSize;
19489
+ this.#maxAge = options.maxAge || Number.POSITIVE_INFINITY;
19490
+ this.#onEviction = options.onEviction;
19491
+ }
19492
+ get __oldCache() {
19493
+ return this.#oldCache;
19494
+ }
19495
+ #emitEvictions(cache) {
19496
+ if (typeof this.#onEviction !== "function") {
19497
+ return;
19498
+ }
19499
+ for (const [key, item] of cache) {
19500
+ this.#onEviction(key, item.value);
19501
+ }
19502
+ }
19503
+ #deleteIfExpired(key, item) {
19504
+ if (typeof item.expiry === "number" && item.expiry <= Date.now()) {
19505
+ if (typeof this.#onEviction === "function") {
19506
+ this.#onEviction(key, item.value);
19507
+ }
19508
+ return this.delete(key);
19509
+ }
19510
+ return false;
19511
+ }
19512
+ #getOrDeleteIfExpired(key, item) {
19513
+ const deleted = this.#deleteIfExpired(key, item);
19514
+ if (deleted === false) {
19515
+ return item.value;
19516
+ }
19517
+ }
19518
+ #getItemValue(key, item) {
19519
+ return item.expiry ? this.#getOrDeleteIfExpired(key, item) : item.value;
19520
+ }
19521
+ #peek(key, cache) {
19522
+ const item = cache.get(key);
19523
+ return this.#getItemValue(key, item);
19524
+ }
19525
+ #set(key, value) {
19526
+ this.#cache.set(key, value);
19527
+ this.#size++;
19528
+ if (this.#size >= this.#maxSize) {
19529
+ this.#size = 0;
19530
+ this.#emitEvictions(this.#oldCache);
19531
+ this.#oldCache = this.#cache;
19532
+ this.#cache = new Map;
19533
+ }
19534
+ }
19535
+ #moveToRecent(key, item) {
19536
+ this.#oldCache.delete(key);
19537
+ this.#set(key, item);
19538
+ }
19539
+ *#entriesAscending() {
19540
+ for (const item of this.#oldCache) {
19541
+ const [key, value] = item;
19542
+ if (!this.#cache.has(key)) {
19543
+ const deleted = this.#deleteIfExpired(key, value);
19544
+ if (deleted === false) {
19545
+ yield item;
19546
+ }
19547
+ }
19548
+ }
19549
+ for (const item of this.#cache) {
19550
+ const [key, value] = item;
19551
+ const deleted = this.#deleteIfExpired(key, value);
19552
+ if (deleted === false) {
19553
+ yield item;
19554
+ }
19555
+ }
19556
+ }
19557
+ get(key) {
19558
+ if (this.#cache.has(key)) {
19559
+ const item = this.#cache.get(key);
19560
+ return this.#getItemValue(key, item);
19561
+ }
19562
+ if (this.#oldCache.has(key)) {
19563
+ const item = this.#oldCache.get(key);
19564
+ if (this.#deleteIfExpired(key, item) === false) {
19565
+ this.#moveToRecent(key, item);
19566
+ return item.value;
19567
+ }
19568
+ }
19569
+ }
19570
+ set(key, value, { maxAge = this.#maxAge } = {}) {
19571
+ const expiry = typeof maxAge === "number" && maxAge !== Number.POSITIVE_INFINITY ? Date.now() + maxAge : undefined;
19572
+ if (this.#cache.has(key)) {
19573
+ this.#cache.set(key, {
19574
+ value,
19575
+ expiry
19576
+ });
19577
+ } else {
19578
+ this.#set(key, { value, expiry });
19579
+ }
19580
+ return this;
19581
+ }
19582
+ has(key) {
19583
+ if (this.#cache.has(key)) {
19584
+ return !this.#deleteIfExpired(key, this.#cache.get(key));
19585
+ }
19586
+ if (this.#oldCache.has(key)) {
19587
+ return !this.#deleteIfExpired(key, this.#oldCache.get(key));
19588
+ }
19589
+ return false;
19590
+ }
19591
+ peek(key) {
19592
+ if (this.#cache.has(key)) {
19593
+ return this.#peek(key, this.#cache);
19594
+ }
19595
+ if (this.#oldCache.has(key)) {
19596
+ return this.#peek(key, this.#oldCache);
19597
+ }
19598
+ }
19599
+ expiresIn(key) {
19600
+ const item = this.#cache.get(key) ?? this.#oldCache.get(key);
19601
+ if (item) {
19602
+ return item.expiry ? item.expiry - Date.now() : Number.POSITIVE_INFINITY;
19603
+ }
19604
+ }
19605
+ delete(key) {
19606
+ const deleted = this.#cache.delete(key);
19607
+ if (deleted) {
19608
+ this.#size--;
19609
+ }
19610
+ return this.#oldCache.delete(key) || deleted;
19611
+ }
19612
+ clear() {
19613
+ this.#cache.clear();
19614
+ this.#oldCache.clear();
19615
+ this.#size = 0;
19616
+ }
19617
+ resize(newSize) {
19618
+ if (!(newSize && newSize > 0)) {
19619
+ throw new TypeError("`maxSize` must be a number greater than 0");
19620
+ }
19621
+ const items = [...this.#entriesAscending()];
19622
+ const removeCount = items.length - newSize;
19623
+ if (removeCount < 0) {
19624
+ this.#cache = new Map(items);
19625
+ this.#oldCache = new Map;
19626
+ this.#size = items.length;
19627
+ } else {
19628
+ if (removeCount > 0) {
19629
+ this.#emitEvictions(items.slice(0, removeCount));
19630
+ }
19631
+ this.#oldCache = new Map(items.slice(removeCount));
19632
+ this.#cache = new Map;
19633
+ this.#size = 0;
19634
+ }
19635
+ this.#maxSize = newSize;
19636
+ }
19637
+ evict(count = 1) {
19638
+ const requested = Number(count);
19639
+ if (!requested || requested <= 0) {
19640
+ return;
19641
+ }
19642
+ const items = [...this.#entriesAscending()];
19643
+ const evictCount = Math.trunc(Math.min(requested, Math.max(items.length - 1, 0)));
19644
+ if (evictCount <= 0) {
19645
+ return;
19646
+ }
19647
+ this.#emitEvictions(items.slice(0, evictCount));
19648
+ this.#oldCache = new Map(items.slice(evictCount));
19649
+ this.#cache = new Map;
19650
+ this.#size = 0;
19651
+ }
19652
+ *keys() {
19653
+ for (const [key] of this) {
19654
+ yield key;
19655
+ }
19656
+ }
19657
+ *values() {
19658
+ for (const [, value] of this) {
19659
+ yield value;
19660
+ }
19661
+ }
19662
+ *[Symbol.iterator]() {
19663
+ for (const item of this.#cache) {
19664
+ const [key, value] = item;
19665
+ const deleted = this.#deleteIfExpired(key, value);
19666
+ if (deleted === false) {
19667
+ yield [key, value.value];
19668
+ }
19669
+ }
19670
+ for (const item of this.#oldCache) {
19671
+ const [key, value] = item;
19672
+ if (!this.#cache.has(key)) {
19673
+ const deleted = this.#deleteIfExpired(key, value);
19674
+ if (deleted === false) {
19675
+ yield [key, value.value];
19676
+ }
19677
+ }
19678
+ }
19679
+ }
19680
+ *entriesDescending() {
19681
+ let items = [...this.#cache];
19682
+ for (let i = items.length - 1;i >= 0; --i) {
19683
+ const item = items[i];
19684
+ const [key, value] = item;
19685
+ const deleted = this.#deleteIfExpired(key, value);
19686
+ if (deleted === false) {
19687
+ yield [key, value.value];
19688
+ }
19689
+ }
19690
+ items = [...this.#oldCache];
19691
+ for (let i = items.length - 1;i >= 0; --i) {
19692
+ const item = items[i];
19693
+ const [key, value] = item;
19694
+ if (!this.#cache.has(key)) {
19695
+ const deleted = this.#deleteIfExpired(key, value);
19696
+ if (deleted === false) {
19697
+ yield [key, value.value];
19698
+ }
19699
+ }
19700
+ }
19701
+ }
19702
+ *entriesAscending() {
19703
+ for (const [key, value] of this.#entriesAscending()) {
19704
+ yield [key, value.value];
19705
+ }
19706
+ }
19707
+ get size() {
19708
+ if (!this.#size) {
19709
+ return this.#oldCache.size;
19710
+ }
19711
+ let oldCacheSize = 0;
19712
+ for (const key of this.#oldCache.keys()) {
19713
+ if (!this.#cache.has(key)) {
19714
+ oldCacheSize++;
19715
+ }
19716
+ }
19717
+ return Math.min(this.#size + oldCacheSize, this.#maxSize);
19718
+ }
19719
+ get maxSize() {
19720
+ return this.#maxSize;
19721
+ }
19722
+ get maxAge() {
19723
+ return this.#maxAge;
19724
+ }
19725
+ entries() {
19726
+ return this.entriesAscending();
19727
+ }
19728
+ forEach(callbackFunction, thisArgument = this) {
19729
+ for (const [key, value] of this.entriesAscending()) {
19730
+ callbackFunction.call(thisArgument, value, key, this);
19731
+ }
19732
+ }
19733
+ get [Symbol.toStringTag]() {
19734
+ return "QuickLRU";
19735
+ }
19736
+ toString() {
19737
+ return `QuickLRU(${this.size}/${this.maxSize})`;
19738
+ }
19739
+ [Symbol.for("nodejs.util.inspect.custom")]() {
19740
+ return this.toString();
19741
+ }
19742
+ }
19743
+
19744
+ // src/config/index.ts
19745
+ init_evidence_schema();
19746
+ init_plan_schema();
19747
+
19748
+ // src/config/spec-schema.ts
19749
+ init_zod();
19750
+ var ObligationSchema = exports_external.enum(["MUST", "SHALL", "SHOULD", "MAY"]);
19751
+ var SpecRequirementSchema = exports_external.object({
19752
+ id: exports_external.string().regex(/^FR-(?!000)\d{3}$/, "Requirement ID must match FR-### pattern (e.g., FR-001)"),
19753
+ obligation: ObligationSchema,
19754
+ text: exports_external.string().min(1)
19755
+ });
19756
+ var SpecScenarioSchema = exports_external.object({
19757
+ name: exports_external.string().min(1),
19758
+ given: exports_external.array(exports_external.string()).optional().default([]),
19759
+ when: exports_external.array(exports_external.string()).min(1, 'Scenario must have at least one "when" clause'),
19760
+ thenClauses: exports_external.array(exports_external.string()).min(1, 'Scenario must have at least one "then" clause')
19761
+ });
19762
+ var SpecSectionSchema = exports_external.object({
19763
+ name: exports_external.string().min(1),
19764
+ requirements: exports_external.array(SpecRequirementSchema).default([])
19765
+ });
19766
+ var SwarmSpecSchema = exports_external.object({
19767
+ title: exports_external.string().min(1),
19768
+ purpose: exports_external.string().min(1),
19769
+ sections: exports_external.array(SpecSectionSchema).min(1, "Spec must have at least one section")
19770
+ });
19771
+ var SpecDeltaSchema = exports_external.object({
19772
+ added: exports_external.array(SpecRequirementSchema).default([]),
19773
+ modified: exports_external.array(SpecRequirementSchema).default([]),
19774
+ removed: exports_external.array(SpecRequirementSchema).default([])
19775
+ });
19776
+ var DeltaSpecSchema = exports_external.union([
19777
+ SwarmSpecSchema,
19778
+ SpecDeltaSchema
19779
+ ]);
19780
+ // src/agents/index.ts
19781
+ var warnedAgents = new Set;
19782
+
19783
+ // src/hooks/guardrails.ts
19784
+ init_manager();
19785
+ init_telemetry();
19786
+ init_utils();
19787
+
19788
+ // src/hooks/conflict-resolution.ts
19789
+ init_telemetry();
19790
+
19791
+ // src/hooks/extractors.ts
19792
+ function extractCurrentPhase(planContent) {
19793
+ if (!planContent) {
19794
+ return null;
19795
+ }
19796
+ const lines = planContent.split(`
19797
+ `);
19798
+ for (let i = 0;i < Math.min(20, lines.length); i++) {
19799
+ const line = lines[i].trim();
19800
+ const progressMatch = line.match(/^## Phase (\d+):?\s*(.*?)\s*\[IN PROGRESS\]/i);
19801
+ if (progressMatch) {
19802
+ const phaseNum = progressMatch[1];
19803
+ const description = progressMatch[2]?.trim() || "";
19804
+ return `Phase ${phaseNum}: ${description} [IN PROGRESS]`;
19805
+ }
19806
+ }
19807
+ for (let i = 0;i < Math.min(3, lines.length); i++) {
19808
+ const line = lines[i].trim();
19809
+ const phaseMatch = line.match(/Phase:\s*(\d+)/i);
19810
+ if (phaseMatch) {
19811
+ const phaseNum = phaseMatch[1];
19812
+ return `Phase ${phaseNum} [PENDING]`;
19813
+ }
19814
+ }
19815
+ return null;
19816
+ }
19817
+ function extractCurrentPhaseFromPlan(plan) {
19818
+ const phase = plan.phases.find((p) => p.id === plan.current_phase);
19819
+ if (!phase)
19820
+ return null;
19821
+ const statusMap = {
19822
+ pending: "PENDING",
19823
+ in_progress: "IN PROGRESS",
19824
+ complete: "COMPLETE",
19825
+ blocked: "BLOCKED"
19826
+ };
19827
+ const statusText = statusMap[phase.status] || "PENDING";
19828
+ return `Phase ${phase.id}: ${phase.name} [${statusText}]`;
19829
+ }
19830
+
19831
+ // src/hooks/model-limits.ts
19832
+ init_utils();
19833
+ var loggedFirstCalls = new Set;
19834
+
19835
+ // src/hooks/guardrails.ts
19836
+ var storedInputArgs = new Map;
19837
+ var toolCallsSinceLastWrite = new Map;
19838
+ var noOpWarningIssued = new Set;
19839
+ var consecutiveNoToolTurns = new Map;
19840
+ var DC_SAFE_TARGETS = new Set([
19841
+ "node_modules",
19842
+ ".git",
19843
+ "dist",
19844
+ "build",
19845
+ "coverage",
19846
+ ".next",
19847
+ ".turbo",
19848
+ ".cache",
19849
+ ".venv",
19850
+ "venv",
19851
+ "__pycache__",
19852
+ "target",
19853
+ "out",
19854
+ ".parcel-cache",
19855
+ ".svelte-kit",
19856
+ ".nuxt",
19857
+ ".output",
19858
+ ".angular",
19859
+ ".gradle",
19860
+ "vendor"
19861
+ ]);
19862
+ var DC_FS_ROOTS = new Set(["/", "C:\\", "C:/", "D:\\", "D:/", "E:\\", "E:/"]);
19863
+ var pathNormalizationCache = new QuickLRU({
19864
+ maxSize: 500
19865
+ });
19866
+ var globMatcherCache = new QuickLRU({
19867
+ maxSize: 200
19868
+ });
19869
+
19870
+ // src/hooks/delegation-gate.ts
19871
+ init_utils2();
19872
+ var pendingCoderScopeByTaskId = new Map;
19873
+ function clearPendingCoderScope() {
19874
+ pendingCoderScopeByTaskId.clear();
19875
+ }
19876
+
19877
+ // src/state.ts
19467
19878
  init_telemetry();
19468
19879
  var _rehydrationCache = null;
19469
19880
  var swarmState = {
@@ -19496,6 +19907,7 @@ function resetSwarmState() {
19496
19907
  _rehydrationCache = null;
19497
19908
  swarmState.fullAutoEnabledInConfig = false;
19498
19909
  swarmState.environmentProfiles.clear();
19910
+ clearPendingCoderScope();
19499
19911
  }
19500
19912
  function getAgentSession(sessionId) {
19501
19913
  return swarmState.agentSessions.get(sessionId);
@@ -32178,43 +32590,6 @@ function tool(input) {
32178
32590
  return input;
32179
32591
  }
32180
32592
  tool.schema = exports_external2;
32181
-
32182
- // src/config/index.ts
32183
- init_evidence_schema();
32184
- init_plan_schema();
32185
-
32186
- // src/config/spec-schema.ts
32187
- init_zod();
32188
- var ObligationSchema = exports_external.enum(["MUST", "SHALL", "SHOULD", "MAY"]);
32189
- var SpecRequirementSchema = exports_external.object({
32190
- id: exports_external.string().regex(/^FR-(?!000)\d{3}$/, "Requirement ID must match FR-### pattern (e.g., FR-001)"),
32191
- obligation: ObligationSchema,
32192
- text: exports_external.string().min(1)
32193
- });
32194
- var SpecScenarioSchema = exports_external.object({
32195
- name: exports_external.string().min(1),
32196
- given: exports_external.array(exports_external.string()).optional().default([]),
32197
- when: exports_external.array(exports_external.string()).min(1, 'Scenario must have at least one "when" clause'),
32198
- thenClauses: exports_external.array(exports_external.string()).min(1, 'Scenario must have at least one "then" clause')
32199
- });
32200
- var SpecSectionSchema = exports_external.object({
32201
- name: exports_external.string().min(1),
32202
- requirements: exports_external.array(SpecRequirementSchema).default([])
32203
- });
32204
- var SwarmSpecSchema = exports_external.object({
32205
- title: exports_external.string().min(1),
32206
- purpose: exports_external.string().min(1),
32207
- sections: exports_external.array(SpecSectionSchema).min(1, "Spec must have at least one section")
32208
- });
32209
- var SpecDeltaSchema = exports_external.object({
32210
- added: exports_external.array(SpecRequirementSchema).default([]),
32211
- modified: exports_external.array(SpecRequirementSchema).default([]),
32212
- removed: exports_external.array(SpecRequirementSchema).default([])
32213
- });
32214
- var DeltaSpecSchema = exports_external.union([
32215
- SwarmSpecSchema,
32216
- SpecDeltaSchema
32217
- ]);
32218
32593
  // src/tools/create-tool.ts
32219
32594
  function classifyToolError(error93) {
32220
32595
  const msg = (error93 instanceof Error ? error93.message ?? "" : String(error93)).toLowerCase();
@@ -37537,7 +37912,7 @@ function validatePlanPhases(plan) {
37537
37912
  }
37538
37913
  return true;
37539
37914
  }
37540
- function extractCurrentPhaseFromPlan(plan) {
37915
+ function extractCurrentPhaseFromPlan2(plan) {
37541
37916
  if (!plan) {
37542
37917
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
37543
37918
  }
@@ -37685,7 +38060,7 @@ async function getHandoffData(directory) {
37685
38060
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
37686
38061
  const sessionState = parseSessionState(sessionContent);
37687
38062
  const plan = await loadPlanJsonOnly(directory);
37688
- const planInfo = extractCurrentPhaseFromPlan(plan);
38063
+ const planInfo = extractCurrentPhaseFromPlan2(plan);
37689
38064
  if (!plan) {
37690
38065
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
37691
38066
  if (planMdContent) {
@@ -43524,46 +43899,6 @@ async function handleSpecifyCommand(_directory, args) {
43524
43899
  return "[MODE: SPECIFY] Please enter MODE: SPECIFY and generate a spec for this project.";
43525
43900
  }
43526
43901
 
43527
- // src/hooks/extractors.ts
43528
- function extractCurrentPhase(planContent) {
43529
- if (!planContent) {
43530
- return null;
43531
- }
43532
- const lines = planContent.split(`
43533
- `);
43534
- for (let i = 0;i < Math.min(20, lines.length); i++) {
43535
- const line = lines[i].trim();
43536
- const progressMatch = line.match(/^## Phase (\d+):?\s*(.*?)\s*\[IN PROGRESS\]/i);
43537
- if (progressMatch) {
43538
- const phaseNum = progressMatch[1];
43539
- const description = progressMatch[2]?.trim() || "";
43540
- return `Phase ${phaseNum}: ${description} [IN PROGRESS]`;
43541
- }
43542
- }
43543
- for (let i = 0;i < Math.min(3, lines.length); i++) {
43544
- const line = lines[i].trim();
43545
- const phaseMatch = line.match(/Phase:\s*(\d+)/i);
43546
- if (phaseMatch) {
43547
- const phaseNum = phaseMatch[1];
43548
- return `Phase ${phaseNum} [PENDING]`;
43549
- }
43550
- }
43551
- return null;
43552
- }
43553
- function extractCurrentPhaseFromPlan2(plan) {
43554
- const phase = plan.phases.find((p) => p.id === plan.current_phase);
43555
- if (!phase)
43556
- return null;
43557
- const statusMap = {
43558
- pending: "PENDING",
43559
- in_progress: "IN PROGRESS",
43560
- complete: "COMPLETE",
43561
- blocked: "BLOCKED"
43562
- };
43563
- const statusText = statusMap[phase.status] || "PENDING";
43564
- return `Phase ${phase.id}: ${phase.name} [${statusText}]`;
43565
- }
43566
-
43567
43902
  // src/services/status-service.ts
43568
43903
  init_utils2();
43569
43904
  init_manager();
@@ -43623,7 +43958,7 @@ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
43623
43958
  async function getStatusData(directory, agents) {
43624
43959
  const plan = await loadPlan(directory);
43625
43960
  if (plan && plan.migration_status !== "migration_failed") {
43626
- const currentPhase2 = extractCurrentPhaseFromPlan2(plan) || "Unknown";
43961
+ const currentPhase2 = extractCurrentPhaseFromPlan(plan) || "Unknown";
43627
43962
  let completedTasks2 = 0;
43628
43963
  let totalTasks2 = 0;
43629
43964
  for (const phase of plan.phases) {
@@ -509,6 +509,7 @@ export declare const AuthorityConfigSchema: z.ZodObject<{
509
509
  blockedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
510
510
  allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
511
511
  }, z.core.$strip>>>;
512
+ universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
512
513
  }, z.core.$strip>;
513
514
  export type AuthorityConfig = z.infer<typeof AuthorityConfigSchema>;
514
515
  export declare const CouncilConfigSchema: z.ZodObject<{
@@ -699,6 +700,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
699
700
  blockedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
700
701
  allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
701
702
  }, z.core.$strip>>>;
703
+ universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
702
704
  }, z.core.$strip>>;
703
705
  plan_cursor: z.ZodOptional<z.ZodObject<{
704
706
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -11,8 +11,19 @@ import type { DelegationEnvelope, EnvelopeValidationResult } from '../types/dele
11
11
  * When messagesTransform sets declaredCoderScope on the architect session,
12
12
  * the coder session may not exist yet. This map allows scope-guard to look up
13
13
  * the scope by taskId when the session's declaredCoderScope is null.
14
+ *
15
+ * v6.70.0 gap-closure: this map is module-scoped (not inside `swarmState`) and
16
+ * is cleared by `resetSwarmState` via `clearPendingCoderScope()` below. Without
17
+ * that cleanup, a `/swarm close` followed by a new session with a colliding
18
+ * taskId (e.g. "1.1") would inherit stale scope from the previous swarm.
14
19
  */
15
20
  export declare const pendingCoderScopeByTaskId: Map<string, string[]>;
21
+ /**
22
+ * v6.70.0 gap-closure: clears the pending coder-scope map. Exported as a
23
+ * helper (rather than importing the map directly from state.ts) to avoid the
24
+ * circular import `state.ts ↔ delegation-gate.ts`. Called by `resetSwarmState`.
25
+ */
26
+ export declare function clearPendingCoderScope(): void;
16
27
  /**
17
28
  * Parses a string to extract a DelegationEnvelope.
18
29
  * Returns null if no valid envelope is found.
@@ -6,6 +6,7 @@
6
6
  * - Layer 1 (Soft Warning @ warning_threshold): Sets warning flag for messagesTransform to inject warning
7
7
  * - Layer 2 (Hard Block @ 100%): Throws error in toolBefore to block further calls, injects STOP message
8
8
  */
9
+ import * as path from 'node:path';
9
10
  import { type AuthorityConfig, type GuardrailsConfig } from '../config/schema';
10
11
  import { type FileZone } from '../context/zone-classifier';
11
12
  /**
@@ -119,10 +120,44 @@ type AgentRule = {
119
120
  allowedGlobs?: string[];
120
121
  };
121
122
  export declare const DEFAULT_AGENT_AUTHORITY_RULES: Record<string, AgentRule>;
123
+ /**
124
+ * Checks whether a write target path (or any ancestor strictly inside cwd)
125
+ * is a symlink. Writing through a symlink can redirect the write to a
126
+ * location outside the working directory, bypassing scope containment.
127
+ *
128
+ * The walk stops at cwd — cwd itself is NOT lstat'd. A user's chosen
129
+ * working directory may legitimately be reached via a symlink (e.g.,
130
+ * macOS's /tmp → /private/tmp), and that symlink does not constitute a
131
+ * redirect *within* the workspace. Only attacker-plantable symlinks
132
+ * BELOW cwd are relevant to this guard.
133
+ *
134
+ * ENOENT on any node in the chain is allowed — the file/dir doesn't exist yet.
135
+ * Any other lstat error (EPERM, EACCES, ENAMETOOLONG, …) fails closed:
136
+ * an unverifiable ancestor must not be written through, even if the OS
137
+ * would eventually reject the write. Defense-in-depth over optimism.
138
+ *
139
+ * @returns A block reason string if a symlink is detected, null if all clear.
140
+ */
141
+ export declare function checkWriteTargetForSymlink(targetPath: string, cwd: string): string | null;
142
+ /**
143
+ * Returns true when `targetAbsolute` and `cwdAbsolute` resolve to different
144
+ * filesystem roots. On POSIX this is always false (single root `/`); on
145
+ * Windows it is true when the two paths sit on different drive letters or
146
+ * different UNC roots — the symptom Codex flagged on PR #501, where
147
+ * `path.relative('C:\\repo', 'D:\\secret.txt')` returns the absolute
148
+ * `'D:\\secret.txt'` and slips past `startsWith('../')` containment.
149
+ *
150
+ * Exposed (and accepts an injectable `pathLib`) so the cross-drive guard
151
+ * is falsifiable on Linux CI without depending on a Windows runner: tests
152
+ * pass `path.win32` / `path.posix` directly.
153
+ */
154
+ export declare function isOnDifferentFilesystemRoot(targetAbsolute: string, cwdAbsolute: string, pathLib?: Pick<typeof path, 'parse'>): boolean;
122
155
  /**
123
156
  * Checks whether the given agent is authorised to write to the given file path.
124
157
  */
125
- export declare function checkFileAuthority(agentName: string, filePath: string, cwd: string, authorityConfig?: AuthorityConfig): {
158
+ export declare function checkFileAuthority(agentName: string, filePath: string, cwd: string, authorityConfig?: AuthorityConfig, options?: {
159
+ declaredScope?: string[] | null;
160
+ }): {
126
161
  allowed: true;
127
162
  } | {
128
163
  allowed: false;