opencode-swarm 7.116.0 → 7.117.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/.opencode/skills/commit-pr/SKILL.md +60 -579
- package/dist/cli/{curator-drift-c0by7063.js → curator-drift-7p2ky1th.js} +2 -2
- package/dist/cli/{curator-7s5yw6hw.js → curator-fr2m5hna.js} +13 -13
- package/dist/cli/{curator-llm-factory-x96dr0zf.js → curator-llm-factory-m0kvna8n.js} +13 -13
- package/dist/cli/{evidence-summary-service-ef6kgtev.js → evidence-summary-service-bwt6drb3.js} +5 -5
- package/dist/cli/{gate-evidence-thqt0beq.js → gate-evidence-j2m4cd85.js} +3 -2
- package/dist/cli/{guardrail-explain-kwqfkwch.js → guardrail-explain-xjgk822d.js} +14 -14
- package/dist/cli/{hive-promoter-rkkx40qv.js → hive-promoter-zpk5jmx0.js} +13 -13
- package/dist/cli/{index-bbsaxnj5.js → index-0pfqcjp6.js} +4 -0
- package/dist/cli/{index-qgeeyy75.js → index-4f4zv8pb.js} +29 -7
- package/dist/cli/{index-a6f8b0vn.js → index-5bcrp3bc.js} +1 -1
- package/dist/cli/{index-81vzywh3.js → index-abjjn4yh.js} +1 -1
- package/dist/cli/{index-8bvh0qfa.js → index-af94ke83.js} +3 -3
- package/dist/cli/{index-k5ey429j.js → index-aws8yhwq.js} +7 -7
- package/dist/cli/{index-jyetmzcn.js → index-c9m5skgs.js} +3 -3
- package/dist/cli/{index-3yh67t1h.js → index-dc3j6jmk.js} +5 -4
- package/dist/cli/{index-jtqkh8jf.js → index-fsrp8wp3.js} +10 -1
- package/dist/cli/{index-s385axt1.js → index-hskmya46.js} +3 -3
- package/dist/cli/{index-wh8949ef.js → index-kzj3fp7c.js} +3 -3
- package/dist/cli/{index-tvgvb5pa.js → index-n3sm9ewn.js} +2 -2
- package/dist/cli/{index-3b8n3dbd.js → index-pgtqxat4.js} +14 -14
- package/dist/cli/{index-me46ffm2.js → index-vkdr12ek.js} +1700 -936
- package/dist/cli/{index-cnrhj56z.js → index-xdsd2hma.js} +6 -6
- package/dist/cli/index.js +13 -13
- package/dist/cli/{knowledge-escalator-0bq62d34.js → knowledge-escalator-bmk725p4.js} +6 -6
- package/dist/cli/{knowledge-events-cwwky393.js → knowledge-events-px14n75v.js} +4 -3
- package/dist/cli/{knowledge-store-q8x4h82m.js → knowledge-store-z9znvtn2.js} +4 -4
- package/dist/cli/{knowledge-validator-zr0djm02.js → knowledge-validator-7r5t821g.js} +5 -5
- package/dist/cli/{pending-delegations-rr9x47rd.js → pending-delegations-9cn17983.js} +2 -2
- package/dist/cli/{pr-subscriptions-cny2jz2d.js → pr-subscriptions-8a6jwek2.js} +3 -3
- package/dist/cli/{skill-generator-mz267btk.js → skill-generator-4d3w8sqt.js} +7 -7
- package/dist/commands/close.d.ts +12 -0
- package/dist/commands/link.d.ts +7 -4
- package/dist/commands/registry.d.ts +6 -6
- package/dist/commands/reset-backup.d.ts +32 -0
- package/dist/commands/reset-session.d.ts +2 -0
- package/dist/commands/reset.d.ts +9 -0
- package/dist/commands/unlink.d.ts +12 -5
- package/dist/evidence/task-file.d.ts +7 -0
- package/dist/hooks/knowledge-events.d.ts +2 -0
- package/dist/hooks/knowledge-link.d.ts +31 -4
- package/dist/index.js +240 -229
- package/dist/knowledge/cohort-identity.d.ts +103 -0
- package/dist/knowledge/config-fingerprint.d.ts +57 -0
- package/dist/knowledge/family-manifest.d.ts +50 -0
- package/dist/knowledge/family-migration.d.ts +109 -0
- package/dist/knowledge/identity.d.ts +12 -2
- package/dist/knowledge/index.d.ts +1 -0
- package/dist/services/knowledge-diagnostics.d.ts +27 -0
- package/dist/services/status-service.d.ts +13 -0
- package/dist/utils/swarm-artifact-cache.d.ts +13 -0
- package/package.json +1 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical cohort-identity resolver for the linked-swarm knowledge system.
|
|
3
|
+
*
|
|
4
|
+
* Problem (issue #1846): the legacy `deriveProjectHash` (in `./identity.ts`)
|
|
5
|
+
* fed the *raw* `git remote get-url origin` string into SHA-256 with only a
|
|
6
|
+
* `.trim()`. Equivalent remote spellings (SSH vs scp vs HTTPS, optional `.git`,
|
|
7
|
+
* slash direction, host/path case, percent-encoding, NFC/NFD) therefore hashed
|
|
8
|
+
* to *different* cohort ids, fragmenting the linked store. When no origin was
|
|
9
|
+
* present it hashed the absolute worktree path, so sibling worktrees of the
|
|
10
|
+
* same repository became unrelated cohorts.
|
|
11
|
+
*
|
|
12
|
+
* This module is the single canonical identity resolver used by linking (and,
|
|
13
|
+
* going forward, status, diagnostics, cache keys, hive provenance, and worktree
|
|
14
|
+
* suggestions). Resolution order (issue #1846 §1):
|
|
15
|
+
*
|
|
16
|
+
* 1. Normalize a configured Git remote into a provider-neutral host/path
|
|
17
|
+
* identity so equivalent spellings converge.
|
|
18
|
+
* 2. If no usable remote exists, derive identity from a repository-stable Git
|
|
19
|
+
* identity shared by sibling worktrees (`git rev-parse --git-common-dir`).
|
|
20
|
+
* This fallback is machine-local (not portable across machines), so it is
|
|
21
|
+
* flagged `degraded: true` with a visible warning.
|
|
22
|
+
* 3. Only then fall back to a normalized absolute path (also `degraded`).
|
|
23
|
+
*
|
|
24
|
+
* Subprocess contract (AGENTS.md invariant 3): array-form `execFile('git', …)`,
|
|
25
|
+
* explicit `git -C <dir>`, `stdin` closed immediately, bounded `maxBuffer`, and
|
|
26
|
+
* a `timeout` — Node's `execFile` sends SIGTERM (then SIGKILL) on timeout, so
|
|
27
|
+
* the child is terminated without a manual `kill()`. A defensive `child.on('error')`
|
|
28
|
+
* guard resolves the promise rather than hanging on a spawn failure. This
|
|
29
|
+
* mirrors the compliant precedent in `src/session/worktree-link-suggestion.ts`.
|
|
30
|
+
*
|
|
31
|
+
* This module performs NO writes and holds NO module-level state (invariant 8).
|
|
32
|
+
* It is NOT imported on the plugin-init path (invariant 1); the only caller is
|
|
33
|
+
* `/swarm link` and, lazily, diagnostics — never `server()` resolution.
|
|
34
|
+
*/
|
|
35
|
+
export type CohortIdentitySource = 'remote' | 'git-common-dir' | 'path';
|
|
36
|
+
export interface CohortIdentity {
|
|
37
|
+
/** 12-hex cohort id (SHA-256 prefix). */
|
|
38
|
+
cohortId: string;
|
|
39
|
+
/** How the id was derived. */
|
|
40
|
+
source: CohortIdentitySource;
|
|
41
|
+
/** Normalized remote (host/owner/repo) when source === 'remote'. */
|
|
42
|
+
normalizedRemote?: string;
|
|
43
|
+
/**
|
|
44
|
+
* True when the id is machine-local rather than portable across machines
|
|
45
|
+
* (git-common-dir or path fallback). A degraded cohort is still a strict
|
|
46
|
+
* improvement over per-worktree isolation, but it is NOT a portable cohort
|
|
47
|
+
* identity and must be surfaced as a visible warning (issue #1846 §1.3).
|
|
48
|
+
*/
|
|
49
|
+
degraded: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Normalize an arbitrary Git remote URL into a canonical `host/owner/repo`
|
|
53
|
+
* string. Equivalent SSH/scp/HTTPS spellings, optional `.git`, slash
|
|
54
|
+
* direction, host/scheme case, path case (for known case-insensitive hosts),
|
|
55
|
+
* percent-encoding, default ports, userinfo, and NFC/NFD all converge.
|
|
56
|
+
*
|
|
57
|
+
* Returns `null` when the input cannot be parsed into a host/owner/repo triple.
|
|
58
|
+
*/
|
|
59
|
+
export declare function normalizeGitRemote(rawUrl: string): string | null;
|
|
60
|
+
/**
|
|
61
|
+
* Run `git -C <dir> <args...>` and return stdout (trimmed) or null on any
|
|
62
|
+
* failure/timeout. Compliant subprocess contract (invariant 3): array form,
|
|
63
|
+
* explicit cwd via `-C`, stdin closed immediately, bounded `maxBuffer`, and a
|
|
64
|
+
* bounded `timeout` — Node's `execFile` sends SIGTERM (then SIGKILL) on
|
|
65
|
+
* timeout, so the child is terminated without a manual `kill()`. A defensive
|
|
66
|
+
* `child.on('error')` guard resolves the promise rather than hanging on a
|
|
67
|
+
* spawn failure.
|
|
68
|
+
*/
|
|
69
|
+
declare function runGit(directory: string, args: string[]): Promise<string | null>;
|
|
70
|
+
/** SHA-256 prefix (12 hex) — matches the legacy `deriveProjectHash` width. */
|
|
71
|
+
declare function cohortHash(input: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Fold a realpath'd absolute path into a stable cohort-id input. On Windows,
|
|
74
|
+
* path separators and drive-letter case are insignificant, and `realpathSync`
|
|
75
|
+
* can emit an extended-length `\\?\` prefix for one spelling of a path but not
|
|
76
|
+
* another; none of these differences should split a cohort, so we fold them
|
|
77
|
+
* all. A trailing separator is likewise insignificant. This is defence in
|
|
78
|
+
* depth: the primary convergence guarantee comes from asking git for the
|
|
79
|
+
* ABSOLUTE common dir (see `resolveCohortId`), which hands every worktree of a
|
|
80
|
+
* repo one identical string; this folding only removes any residual spelling
|
|
81
|
+
* difference that survives realpath.
|
|
82
|
+
*/
|
|
83
|
+
declare function stabilizePath(input: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the canonical cohort identity for a worktree directory.
|
|
86
|
+
*
|
|
87
|
+
* Resolution order:
|
|
88
|
+
* 1. Normalized origin remote (portable cohort identity; not degraded).
|
|
89
|
+
* 2. `git rev-parse --path-format=absolute --git-common-dir` — shared by
|
|
90
|
+
* sibling worktrees of the same repo, but machine-local → degraded.
|
|
91
|
+
* 3. Realpath of the directory — last resort, machine-local → degraded.
|
|
92
|
+
*
|
|
93
|
+
* Never throws. The path fallback always succeeds.
|
|
94
|
+
*/
|
|
95
|
+
export declare function resolveCohortId(directory: string): Promise<CohortIdentity>;
|
|
96
|
+
export declare const _internals: {
|
|
97
|
+
normalizeGitRemote: typeof normalizeGitRemote;
|
|
98
|
+
runGit: typeof runGit;
|
|
99
|
+
cohortHash: typeof cohortHash;
|
|
100
|
+
stabilizePath: typeof stabilizePath;
|
|
101
|
+
GIT_TIMEOUT_MS: number;
|
|
102
|
+
};
|
|
103
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort config fingerprint (issue #1846 §4).
|
|
3
|
+
*
|
|
4
|
+
* @status planned-future-use. The helper and its tests ship in this foundation
|
|
5
|
+
* PR, but it is NOT yet wired into `link`/`unlink` or the diagnostics surfaces.
|
|
6
|
+
* Cohort-agreement enforcement (fail-closed on mismatch for destructive ops)
|
|
7
|
+
* lands with #1847/#1823, which consume the cohort-status source this PR
|
|
8
|
+
* establishes. Shipping the primitive + tests now lets those dependents adopt
|
|
9
|
+
* it without re-deriving the field set.
|
|
10
|
+
*
|
|
11
|
+
* A deterministic hash of the configuration fields that change retrieval,
|
|
12
|
+
* curation, validation, or lifecycle semantics for the swarm knowledge tier.
|
|
13
|
+
* Two linked worktrees SHOULD share the same fingerprint; a mismatch means the
|
|
14
|
+
* cohort members will rank/quarantine/promote lessons differently.
|
|
15
|
+
*
|
|
16
|
+
* Only fields that affect *what the cohort stores and how it behaves* are
|
|
17
|
+
* fingerprinted — not cosmetic or session-local tuning. The set is deliberately
|
|
18
|
+
* conservative: adding a field later only changes the fingerprint when that
|
|
19
|
+
* field's value differs, which is exactly the signal we want.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* The config-shape fingerprint input. Callers project their knowledge config
|
|
23
|
+
* into this loose shape; only the keys present are hashed.
|
|
24
|
+
*/
|
|
25
|
+
export interface CohortConfigFingerprintInput {
|
|
26
|
+
dedup_threshold?: number;
|
|
27
|
+
scope_filter?: readonly string[];
|
|
28
|
+
validation_enabled?: boolean;
|
|
29
|
+
evergreen_confidence?: number;
|
|
30
|
+
evergreen_utility?: number;
|
|
31
|
+
low_utility_threshold?: number;
|
|
32
|
+
default_max_phases?: number;
|
|
33
|
+
todo_max_phases?: number;
|
|
34
|
+
confidence_floor_action?: string;
|
|
35
|
+
contradiction_threshold_action?: string;
|
|
36
|
+
contradiction_quarantine_threshold?: number;
|
|
37
|
+
directive_min_confidence?: number;
|
|
38
|
+
schema_version?: number;
|
|
39
|
+
swarm_max_entries?: number;
|
|
40
|
+
retrieval?: {
|
|
41
|
+
mmr_lambda?: number;
|
|
42
|
+
cold_start_bonus?: number;
|
|
43
|
+
synonym_min_cooccurrence?: number;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Compute a deterministic 12-hex fingerprint for cohort-agreement checks.
|
|
48
|
+
* Stable key ordering (sorted JSON) ensures equivalent configs hash equally
|
|
49
|
+
* regardless of field insertion order.
|
|
50
|
+
*/
|
|
51
|
+
export declare function cohortConfigFingerprint(input: CohortConfigFingerprintInput): string;
|
|
52
|
+
declare function sortKeys(value: unknown): unknown;
|
|
53
|
+
export declare const _internals: {
|
|
54
|
+
cohortConfigFingerprint: typeof cohortConfigFingerprint;
|
|
55
|
+
sortKeys: typeof sortKeys;
|
|
56
|
+
};
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authoritative knowledge-family manifest for the linked-swarm knowledge system.
|
|
3
|
+
*
|
|
4
|
+
* Problem (issue #1846): `link`/`unlink` previously hardcoded a *single* family
|
|
5
|
+
* member (`knowledge.jsonl`) while the link-aware resolvers quietly redirected
|
|
6
|
+
* all seven. The two sources of truth drifted, so pre-link local copies of the
|
|
7
|
+
* other six members were silently orphaned at link time and lost at unlink
|
|
8
|
+
* time. Adding a new family file required editing two commands in lockstep — a
|
|
9
|
+
* classic omission hazard.
|
|
10
|
+
*
|
|
11
|
+
* This manifest is the single source of truth for *which* artifacts participate
|
|
12
|
+
* in link/unlink family migration and *how* each is merged. `link` and `unlink`
|
|
13
|
+
* both iterate it, so a new family member is a one-line edit here.
|
|
14
|
+
*
|
|
15
|
+
* Merge strategies:
|
|
16
|
+
* - `dedup-id-merge`: id-dedup with provenance-preserving near-duplicate merge
|
|
17
|
+
* (union fields, evidence-weighted confidence, preserve losing id in
|
|
18
|
+
* `merged_from`). Used for the active store.
|
|
19
|
+
* - `append-union`: union by the line's stable id field (event id / entry id),
|
|
20
|
+
* appending only lines whose id is not already present on the destination.
|
|
21
|
+
* Idempotent on retry/relink.
|
|
22
|
+
* - `sum-counters`: per-counter field-wise SUM, reusing the existing
|
|
23
|
+
* `mergeRollupInto` primitive (shown/applied/... counts sum; timestamps take
|
|
24
|
+
* the max). Used for the counter baseline JSON.
|
|
25
|
+
*
|
|
26
|
+
* NOT in the manifest (deliberate exceptions, documented in
|
|
27
|
+
* `knowledge-link.ts` "Intentionally NOT redirected"):
|
|
28
|
+
* - `synonym-map.json` — derived state. It is rebuilt deterministically from
|
|
29
|
+
* the linked `knowledge.jsonl` corpus on link rather than migrated, so recall
|
|
30
|
+
* is deterministic across the cohort (issue #1846 §4, critic C4).
|
|
31
|
+
* - `.knowledge-shown.json`, `plan.json`, evidence, session state — per
|
|
32
|
+
* worktree by design.
|
|
33
|
+
*/
|
|
34
|
+
export type FamilyRole = 'store' | 'events' | 'rejected' | 'retractions' | 'counters' | 'quarantine' | 'unactionable' | 'application-legacy';
|
|
35
|
+
export type FamilyMergeStrategy = 'dedup-id-merge' | 'append-union' | 'sum-counters';
|
|
36
|
+
export interface KnowledgeFamilyMember {
|
|
37
|
+
/** Filename within the swarm family directory (e.g. `knowledge.jsonl`). */
|
|
38
|
+
readonly filename: string;
|
|
39
|
+
readonly role: FamilyRole;
|
|
40
|
+
readonly mergeStrategy: FamilyMergeStrategy;
|
|
41
|
+
/** True when unlink may copy this member back to the local worktree. */
|
|
42
|
+
readonly reversible: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The complete knowledge family that participates in cohort linking.
|
|
46
|
+
* Adding a member here automatically includes it in link + unlink migration.
|
|
47
|
+
*/
|
|
48
|
+
export declare const KNOWLEDGE_FAMILY: readonly KnowledgeFamilyMember[];
|
|
49
|
+
/** Filenames of every family member, for quick membership checks. */
|
|
50
|
+
export declare const FAMILY_FILENAMES: readonly string[];
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort family-migration engine for the linked-swarm knowledge system.
|
|
3
|
+
*
|
|
4
|
+
* Drives both `/swarm link` and `/swarm unlink` off the single
|
|
5
|
+
* {@link KNOWLEDGE_FAMILY} manifest (issue #1846 §3). Replaces the prior
|
|
6
|
+
* single-file (`knowledge.jsonl`-only) migration that silently orphaned the
|
|
7
|
+
* other six family members.
|
|
8
|
+
*
|
|
9
|
+
* Design (issue #1846, critic-reviewed plan W3/W4):
|
|
10
|
+
* - One manifest drives link + unlink, so a new family member cannot be
|
|
11
|
+
* silently omitted.
|
|
12
|
+
* - Three merge strategies: `dedup-id-merge` (provenance-preserving store
|
|
13
|
+
* merge), `append-union` (id-keyed union for append-only logs),
|
|
14
|
+
* `sum-counters` (per-counter SUM for the baseline JSON, reusing
|
|
15
|
+
* `mergeRollupInto`).
|
|
16
|
+
* - All-or-nothing commit: stage the entire merged family into a sibling
|
|
17
|
+
* staging directory, validate every file, then commit atomically. The
|
|
18
|
+
* pointer is flipped last by the caller.
|
|
19
|
+
* - Lock discipline: acquire the destination store's directory lock first,
|
|
20
|
+
* read source files under a *brief* source-store lock (released before the
|
|
21
|
+
* long merge/validate work), so a long migration cannot have its lock
|
|
22
|
+
* stolen by `stale` expiry and cannot deadlock against the hot path.
|
|
23
|
+
*
|
|
24
|
+
* No writes happen here on the plugin-init path (invariant 1). Locks are
|
|
25
|
+
* `proper-lockfile` directory locks with a bumped `stale` for the migration
|
|
26
|
+
* critical section (invariant 3, critic C9).
|
|
27
|
+
*/
|
|
28
|
+
import type { CounterRollup } from '../hooks/knowledge-events.js';
|
|
29
|
+
import type { KnowledgeEntryBase } from '../hooks/knowledge-types.js';
|
|
30
|
+
import { type KnowledgeFamilyMember } from './family-manifest.js';
|
|
31
|
+
export interface FamilyMigrationCounts {
|
|
32
|
+
/** Per-member counts (filename → {merged, skipped}). */
|
|
33
|
+
readonly perMember: ReadonlyArray<{
|
|
34
|
+
filename: string;
|
|
35
|
+
merged: number;
|
|
36
|
+
skipped: number;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Provenance-preserving merge of the active store (`dedup-id-merge`).
|
|
41
|
+
*
|
|
42
|
+
* Exact-id duplicates: skip (already present). Near-duplicates (Jaccard bigram
|
|
43
|
+
* similarity ≥ threshold): merge fields rather than drop — union `confirmed_by`,
|
|
44
|
+
* `tags`, `source_refs`; union retrieval outcomes by unique outcome key;
|
|
45
|
+
* confidence becomes an evidence-weighted average; the losing entry's `id` is
|
|
46
|
+
* preserved in `merged_from` for retraction traceability. A `merge` is NOT
|
|
47
|
+
* silent. (Critic C8: this is "provenance-preserving", not "lossless".)
|
|
48
|
+
*/
|
|
49
|
+
declare function mergeStoreEntries(destination: KnowledgeEntryBase[], source: KnowledgeEntryBase[]): {
|
|
50
|
+
merged: KnowledgeEntryBase[];
|
|
51
|
+
added: number;
|
|
52
|
+
skipped: number;
|
|
53
|
+
};
|
|
54
|
+
/** Field-level union of `src` into `target` (mutates target). */
|
|
55
|
+
declare function mergeEntryFields(target: KnowledgeEntryBase, src: KnowledgeEntryBase): void;
|
|
56
|
+
/**
|
|
57
|
+
* Append-union: append source lines whose id is not already present on the
|
|
58
|
+
* destination. Lines without an id field are skipped (we cannot dedup them
|
|
59
|
+
* safely, and every family member here is id-keyed).
|
|
60
|
+
*/
|
|
61
|
+
declare function appendUnionById<T>(destination: T[], source: T[]): {
|
|
62
|
+
merged: T[];
|
|
63
|
+
added: number;
|
|
64
|
+
skipped: number;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Sum-counters: merge two baseline JSON objects (`Record<id, CounterRollup>`)
|
|
68
|
+
* by per-id field-wise sum, reusing the canonical `mergeRollupInto` primitive.
|
|
69
|
+
*/
|
|
70
|
+
declare function sumCounters(destination: Record<string, CounterRollup>, source: Record<string, CounterRollup>): {
|
|
71
|
+
merged: Record<string, CounterRollup>;
|
|
72
|
+
added: number;
|
|
73
|
+
skipped: number;
|
|
74
|
+
};
|
|
75
|
+
/** Serialize a merged family member to its on-disk representation. */
|
|
76
|
+
declare function serialize(member: KnowledgeFamilyMember, data: unknown): string;
|
|
77
|
+
/**
|
|
78
|
+
* Validate a serialized merged member BEFORE commit. This is a real integrity
|
|
79
|
+
* gate, not a vacuous JSON-parseability check: each line must parse AND, for
|
|
80
|
+
* the store member, each entry must carry the required `id`/`lesson` shape so a
|
|
81
|
+
* corrupted merge (e.g. an entry that lost its id) is rejected before it reaches
|
|
82
|
+
* the destination. A failure aborts the migration — the destination stays
|
|
83
|
+
* untouched and the caller never flips the pointer, so a retry is safe.
|
|
84
|
+
*/
|
|
85
|
+
declare function validateSerialized(member: KnowledgeFamilyMember, serialized: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Migrate the complete knowledge family from `sourceDir` into `destinationDir`,
|
|
88
|
+
* merging each member according to its manifest strategy. All-or-nothing:
|
|
89
|
+
* stage → validate → commit. The pointer is NOT touched here (caller flips it).
|
|
90
|
+
*
|
|
91
|
+
* Returns per-member merge counts. Throws on validation failure (caller
|
|
92
|
+
* surfaces the error; the destination is left untouched).
|
|
93
|
+
*
|
|
94
|
+
* @param destinationDir the cohort store that absorbs the merge (link → shared;
|
|
95
|
+
* unlink → local `.swarm`).
|
|
96
|
+
* @param sourceDir the store whose family is merged in (link → local `.swarm`;
|
|
97
|
+
* unlink → shared).
|
|
98
|
+
*/
|
|
99
|
+
export declare function migrateKnowledgeFamily(destinationDir: string, sourceDir: string): Promise<FamilyMigrationCounts>;
|
|
100
|
+
export declare const _internals: {
|
|
101
|
+
mergeStoreEntries: typeof mergeStoreEntries;
|
|
102
|
+
appendUnionById: typeof appendUnionById;
|
|
103
|
+
sumCounters: typeof sumCounters;
|
|
104
|
+
mergeEntryFields: typeof mergeEntryFields;
|
|
105
|
+
serialize: typeof serialize;
|
|
106
|
+
validateSerialized: typeof validateSerialized;
|
|
107
|
+
MIGRATION_LOCK_STALE_MS: number;
|
|
108
|
+
};
|
|
109
|
+
export {};
|
|
@@ -16,11 +16,21 @@ export interface ProjectIdentity {
|
|
|
16
16
|
export declare function resolveIdentityPath(projectHash: string): string;
|
|
17
17
|
/**
|
|
18
18
|
* Derive a deterministic project hash from a directory.
|
|
19
|
-
*
|
|
19
|
+
*
|
|
20
|
+
* @deprecated Since issue #1846. This synchronous helper is retained for
|
|
21
|
+
* backward compatibility (and its existing test coverage) but the canonical,
|
|
22
|
+
* normalization-correct, subprocess-compliant resolver is
|
|
23
|
+
* {@link resolveCohortId} in `./cohort-identity.ts`. New callers MUST use
|
|
24
|
+
* `resolveCohortId`; it normalizes equivalent remotes (SSH/scp/HTTPS, `.git`,
|
|
25
|
+
* case, slashes, percent-encoding, NFC), falls back through
|
|
26
|
+
* `git rev-parse --git-common-dir` before the path, and uses the compliant
|
|
27
|
+
* array-form subprocess contract. This legacy helper is kept only so existing
|
|
28
|
+
* imports keep compiling; it delegates to the legacy un-normalized logic.
|
|
20
29
|
*
|
|
21
30
|
* Worktrees of the same repository share a git remote, so they derive the same
|
|
22
31
|
* hash — which is what lets `/swarm link` (with no name) tie them to one shared
|
|
23
|
-
* knowledge store by default.
|
|
32
|
+
* knowledge store by default. (Note: this legacy form does NOT normalize
|
|
33
|
+
* equivalent remote spellings; `resolveCohortId` does.)
|
|
24
34
|
*/
|
|
25
35
|
export declare function deriveProjectHash(directory: string): string;
|
|
26
36
|
/**
|
|
@@ -46,6 +46,33 @@ export interface KnowledgeDebugMeta {
|
|
|
46
46
|
/** Knowledge-event volume bucketed by type (applied/ignored/violated/...). */
|
|
47
47
|
events_by_type: Record<string, number>;
|
|
48
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Cohort/link health (issue #1846). Makes the linked store and its health
|
|
51
|
+
* obvious to an operator/architect. `null` when link state cannot be read.
|
|
52
|
+
*/
|
|
53
|
+
cohort: {
|
|
54
|
+
/** True when this worktree redirects its knowledge family to a shared store. */
|
|
55
|
+
linked: boolean;
|
|
56
|
+
/** Pointer schema version (1 = legacy, 2 = cohort-aware). */
|
|
57
|
+
pointer_version: 1 | 2 | null;
|
|
58
|
+
/** Link id (shared store directory segment). */
|
|
59
|
+
link_id: string | null;
|
|
60
|
+
/** Canonical cohort id (issue #1846 W1), when known. */
|
|
61
|
+
cohort_id: string | null;
|
|
62
|
+
/** How the cohort id was derived. */
|
|
63
|
+
identity_source: 'remote' | 'git-common-dir' | 'path' | null;
|
|
64
|
+
/** True when the cohort id is machine-local (not portable). */
|
|
65
|
+
degraded: boolean;
|
|
66
|
+
/** Resolved shared root, when linked. */
|
|
67
|
+
shared_root: string | null;
|
|
68
|
+
/** Pointer generation (bumped on each link/unlink), when known. */
|
|
69
|
+
generation: number | null;
|
|
70
|
+
/**
|
|
71
|
+
* True when a local knowledge.jsonl coexists with an active link (the
|
|
72
|
+
* pre-link local store was retained). Benign but worth surfacing.
|
|
73
|
+
*/
|
|
74
|
+
local_orphaned: boolean;
|
|
75
|
+
};
|
|
49
76
|
}
|
|
50
77
|
/**
|
|
51
78
|
* Compute the debug-metadata block for the knowledge system. Best-effort: never
|
|
@@ -78,6 +78,19 @@ export interface StatusData {
|
|
|
78
78
|
unactionableQueueDepth?: number;
|
|
79
79
|
/** #1234 Part 3: pending insight candidates awaiting phase boundary consumption */
|
|
80
80
|
insightCandidatesPending?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Cohort/link status (issue #1846). Makes the linked knowledge store and its
|
|
83
|
+
* health obvious in `/swarm status`. `undefined` when link state is absent.
|
|
84
|
+
*/
|
|
85
|
+
cohort?: {
|
|
86
|
+
linked: boolean;
|
|
87
|
+
linkId?: string;
|
|
88
|
+
cohortId?: string;
|
|
89
|
+
identitySource?: 'remote' | 'git-common-dir' | 'path';
|
|
90
|
+
degraded?: boolean;
|
|
91
|
+
sharedRoot?: string;
|
|
92
|
+
generation?: number;
|
|
93
|
+
};
|
|
81
94
|
}
|
|
82
95
|
/**
|
|
83
96
|
* Get status data from the swarm directory.
|
|
@@ -19,5 +19,18 @@ export declare function readCachedTextFileSync(filePath: string, directRead: ()
|
|
|
19
19
|
export declare function readCachedTextFile(filePath: string, directRead: () => Promise<string | null>): Promise<string | null>;
|
|
20
20
|
export declare function readCachedParsedFileSync<T>(filePath: string, namespace: string, readText: () => string | null, parse: (content: string) => T): T | null;
|
|
21
21
|
export declare function readCachedParsedFile<T>(filePath: string, namespace: string, readText: () => Promise<string | null>, parse: (content: string) => T): Promise<T | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Drop any cached text/parsed entries for `filePath` immediately after a write.
|
|
24
|
+
*
|
|
25
|
+
* The stat-based staleness check (mtimeMs + ctimeMs + size) is a best-effort
|
|
26
|
+
* optimization: a same-size rewrite that lands within one filesystem timestamp
|
|
27
|
+
* tick of a prior cached read can produce an identical stamp, so the very next
|
|
28
|
+
* read-your-own-write can silently return the pre-write value (issue #1729).
|
|
29
|
+
* Writers that read-modify-write the same path twice in quick succession (e.g.
|
|
30
|
+
* a second locked transaction immediately after an atomic write) MUST call
|
|
31
|
+
* this after the write so the next read cannot observe stale content —
|
|
32
|
+
* relying on stat-stamp comparison alone is not sufficient in that window.
|
|
33
|
+
*/
|
|
34
|
+
export declare function invalidateCachedArtifact(filePath: string): void;
|
|
22
35
|
export declare function resetSwarmArtifactCache(): void;
|
|
23
36
|
export declare function getSwarmArtifactCacheStats(): SwarmArtifactCacheStats;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.117.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",
|