opencode-swarm 7.170.2 → 7.171.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 (80) hide show
  1. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  2. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  3. package/dist/background/delegation-lifecycle.d.ts +5 -0
  4. package/dist/cli/{coder-settlement-rrm3ngsa.js → coder-settlement-pn26zx36.js} +7 -7
  5. package/dist/cli/{config-doctor-rnfyv55m.js → config-doctor-jrhpq41y.js} +2 -2
  6. package/dist/cli/{core-b161yfjy.js → core-r0nbh1k2.js} +1 -1
  7. package/dist/cli/{curation-policy-tg84dnnd.js → curation-policy-qemp257w.js} +4 -4
  8. package/dist/cli/{curator-dfcpzqwr.js → curator-0g733bka.js} +28 -28
  9. package/dist/cli/{curator-llm-factory-cjrh0sa3.js → curator-llm-factory-89yjg1m4.js} +28 -28
  10. package/dist/cli/{evidence-summary-service-7jfq6dax.js → evidence-summary-service-4r7sqb2h.js} +11 -11
  11. package/dist/cli/{gate-evidence-0e70dqjg.js → gate-evidence-f13tm63x.js} +4 -4
  12. package/dist/cli/{guardrail-explain-a40pmzzc.js → guardrail-explain-kt4w2rt8.js} +29 -29
  13. package/dist/cli/{guardrail-log-71wvwyd0.js → guardrail-log-18wdr04f.js} +6 -6
  14. package/dist/cli/{guardrail-reset-znw5636e.js → guardrail-reset-795t6nah.js} +28 -28
  15. package/dist/cli/{hive-promoter-pznn5yfn.js → hive-promoter-gwtvg5vc.js} +28 -28
  16. package/dist/cli/{index-we9jztxd.js → index-003d071j.js} +4 -4
  17. package/dist/cli/{index-w79t20a6.js → index-0qa2cqyv.js} +3 -3
  18. package/dist/cli/{index-4m9hfbhe.js → index-4dpsvbdt.js} +3 -3
  19. package/dist/cli/{index-70avfxnw.js → index-4m7q9hqd.js} +3 -3
  20. package/dist/cli/{index-19xctk9g.js → index-7c0e181h.js} +1 -1
  21. package/dist/cli/{index-24pamt0h.js → index-7s5cm87j.js} +2 -2
  22. package/dist/cli/{index-zr6ev5kt.js → index-9fxnn8xg.js} +1 -1
  23. package/dist/cli/{index-45x6meqp.js → index-ak3ca0nv.js} +5 -5
  24. package/dist/cli/{index-2q6qj0vw.js → index-b3nw1bzp.js} +3 -3
  25. package/dist/cli/{index-g0q47r3r.js → index-bvr0p6ns.js} +1 -1
  26. package/dist/cli/{index-sf32ny5w.js → index-cex3emb2.js} +1 -1
  27. package/dist/cli/{index-7sz2rkx3.js → index-cravqkxf.js} +65 -48
  28. package/dist/cli/{index-gs4m1dxw.js → index-d7yc4ys8.js} +3 -3
  29. package/dist/cli/{index-9g3c0w22.js → index-dgpdnve5.js} +1 -1
  30. package/dist/cli/{index-5y7kqjyt.js → index-fdz0076x.js} +1 -1
  31. package/dist/cli/{index-9vxaf499.js → index-g93g1c5r.js} +1 -1
  32. package/dist/cli/{index-g2sc35qk.js → index-gxbesz2h.js} +3 -3
  33. package/dist/cli/{index-8v2k9xqv.js → index-h17tpj0y.js} +4 -4
  34. package/dist/cli/{index-3q7bb7qz.js → index-j92fe86t.js} +7 -7
  35. package/dist/cli/{index-29gnavqx.js → index-k2cpsr0d.js} +1 -1
  36. package/dist/cli/{index-7htmxmjp.js → index-mvcjc28t.js} +2541 -1588
  37. package/dist/cli/{index-7pgzjj3z.js → index-nmffafb0.js} +28 -28
  38. package/dist/cli/{index-7a180w76.js → index-npst1d4g.js} +30 -30
  39. package/dist/cli/{index-4say55ww.js → index-sz75avt3.js} +1 -1
  40. package/dist/cli/{index-j1tjd6aq.js → index-sz9qnjd6.js} +5 -5
  41. package/dist/cli/{index-1kt9xbrt.js → index-ttyvcxxb.js} +2 -2
  42. package/dist/cli/{index-a0vggadp.js → index-v3e19zzm.js} +1 -1
  43. package/dist/cli/{index-dbg2g834.js → index-wp0396m1.js} +4 -4
  44. package/dist/cli/{index-d1sdve0x.js → index-wy4txsws.js} +7 -7
  45. package/dist/cli/{index-z4ewmn1h.js → index-xdw0m34m.js} +1 -1
  46. package/dist/cli/{index-x067zyvp.js → index-yj0qrgyc.js} +6 -6
  47. package/dist/cli/{index-efkxjmdb.js → index-zjkkz9qh.js} +2 -2
  48. package/dist/cli/{index-p6zt0qm1.js → index-znf55hyt.js} +2 -2
  49. package/dist/cli/index.js +28 -28
  50. package/dist/cli/{knowledge-escalator-95gqgg8e.js → knowledge-escalator-kpfm536v.js} +10 -10
  51. package/dist/cli/{knowledge-events-hcx770h3.js → knowledge-events-t3e721m2.js} +8 -8
  52. package/dist/cli/{knowledge-link-twmzh8cf.js → knowledge-link-refyc1fz.js} +3 -3
  53. package/dist/cli/{knowledge-store-ppmrqs41.js → knowledge-store-sk2bhh52.js} +4 -4
  54. package/dist/cli/{knowledge-validator-63rfvqmw.js → knowledge-validator-nmc56pbg.js} +6 -6
  55. package/dist/cli/{pending-delegations-dqdetx92.js → pending-delegations-ckshrtar.js} +6 -6
  56. package/dist/cli/{pr-subscriptions-z9t7f7m0.js → pr-subscriptions-h81nme2p.js} +6 -6
  57. package/dist/cli/{pr-workflow-gate-wqrcb5m8.js → pr-workflow-gate-m1k4b8mr.js} +28 -28
  58. package/dist/cli/{runner-2r5j33tm.js → runner-kzs5wbqh.js} +4 -4
  59. package/dist/cli/{scan-cursor-xzmmf7r4.js → scan-cursor-e7varrte.js} +5 -5
  60. package/dist/cli/{schema-6bn7mj29.js → schema-nsb0saad.js} +1 -1
  61. package/dist/cli/{scope-persistence-wyg0rb07.js → scope-persistence-2s5h5ry7.js} +10 -10
  62. package/dist/cli/{skill-generator-kwnwapfn.js → skill-generator-wpq9j1nf.js} +12 -12
  63. package/dist/cli/{snapshot-coordination-init-ajvmd1z6.js → snapshot-coordination-init-8nhmhefs.js} +28 -28
  64. package/dist/cli/{telemetry-yst95z2f.js → telemetry-z9scwfbz.js} +1 -1
  65. package/dist/cli/{worktree-collision-ownership-dm6nq9yw.js → worktree-collision-ownership-2kmajcc9.js} +6 -6
  66. package/dist/cli/{worktree-isolation-b10h20sv.js → worktree-isolation-kepgr7j2.js} +28 -28
  67. package/dist/commands/dataset.d.ts +20 -0
  68. package/dist/commands/registry.d.ts +39 -0
  69. package/dist/index.js +341 -324
  70. package/dist/observability/catalog.d.ts +3 -3
  71. package/dist/telemetry.d.ts +13 -1
  72. package/dist/tools/repo-map.d.ts +5 -0
  73. package/dist/training/capture.d.ts +37 -0
  74. package/dist/training/consent.d.ts +96 -0
  75. package/dist/training/disk.d.ts +16 -0
  76. package/dist/training/exporter.d.ts +88 -0
  77. package/dist/training/paths.d.ts +20 -0
  78. package/dist/training/redact.d.ts +29 -0
  79. package/dist/training/vault.d.ts +177 -0
  80. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The event catalog (issue #2029).
3
3
  *
4
- * Exactly 61 entries, matching the `TelemetryEvent` union at
4
+ * Exactly 62 entries, matching the `TelemetryEvent` union at
5
5
  * `src/telemetry.ts:20-172`. Thirty-eight predate the #2029 contract; the 39th is
6
6
  * `agent_conflict_detected` (previously emitted through a force-cast past the
7
7
  * type system), the 40th is `close_archive_result` (issue #2030 — the
@@ -29,7 +29,7 @@
29
29
  * (issue #2046 item 9 — canonical council attempt / accepted-transition
30
30
  * observations joined to the lifecycle correlation system via the
31
31
  * server-derived `councilRoundId`). The 60th is
32
- * `context_source_attribution` and the 61st is `verdict_row_pipe_recovery`
32
+ * `context_source_attribution` and the 61st is `verdict_row_pipe_recovery` and the 62nd is `training_vault_health`
33
33
  * (issue #2482 — D3: honest savings attribution with the omit-when-unknown
34
34
  * rule, and the #2184 verdict-row pipe-recovery fidelity class in the event
35
35
  * lifecycle). These late
@@ -88,7 +88,7 @@ export interface CatalogEntry {
88
88
  /**
89
89
  * Whether an event of this kind must carry `trace.parentSpanId`.
90
90
  *
91
- * `false` for all 61 entries today, and that is a truthful statement about
91
+ * `false` for all 62 entries today, and that is a truthful statement about
92
92
  * the current system rather than a placeholder: no producer supplies a
93
93
  * parent span, so `createObservation` never sets one. Setting this to `true`
94
94
  * for a kind whose producer cannot supply a parent would make every
@@ -33,7 +33,7 @@ export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activa
33
33
  * `prm_hard_stop` TRIGGER emitted by `src/prm/escalation.ts`. A trigger with
34
34
  * no matching delivery means the containment never reached the agent.
35
35
  */
36
- | 'prm_hard_stop_delivered' | 'agent_conflict_detected' | 'close_archive_result' | 'knowledge_receipt_transition' | 'knowledge_maintenance' | 'residue_health' | 'context_telemetry_health' | 'skill_usage_health' | 'core_events_health' | 'shell_audit_health' | 'trajectory_health' | 'learning_health_alarm' | 'pr_subscription_health' | 'council_attempt' | 'council_round_transition' | 'council_attempt_unscoped' | 'context_source_attribution' | 'verdict_row_pipe_recovery';
36
+ | 'prm_hard_stop_delivered' | 'agent_conflict_detected' | 'close_archive_result' | 'knowledge_receipt_transition' | 'knowledge_maintenance' | 'residue_health' | 'context_telemetry_health' | 'skill_usage_health' | 'core_events_health' | 'shell_audit_health' | 'trajectory_health' | 'learning_health_alarm' | 'pr_subscription_health' | 'council_attempt' | 'council_round_transition' | 'council_attempt_unscoped' | 'context_source_attribution' | 'verdict_row_pipe_recovery' | 'training_vault_health';
37
37
  /** Stable classification for how a reviewer-gate decision was established. */
38
38
  export type ReviewerGateEvidenceKind = 'genuine' | 'fallback' | 'data_quality' | 'block';
39
39
  /**
@@ -293,6 +293,18 @@ export declare const telemetry: {
293
293
  * contract's no-content-in-metrics rule. Enables PR 16 to alarm and PR 20 to
294
294
  * report without leaking workspace layout or capsule contents.
295
295
  */
296
+ /**
297
+ * Training vault health (issue #2486). Emitted on capture-stop transitions
298
+ * (quota/disk/consent), quarantine aggregates, and withdrawals for the
299
+ * consented training-content vault. Bounded payload: the pseudonymous
300
+ * project ref, a reason enum, and a count — no vault content, no raw
301
+ * paths, matching the observability contract's no-content rule.
302
+ */
303
+ trainingVaultHealth(data: {
304
+ project_ref: string;
305
+ reason: "quota_bytes" | "quota_records" | "disk_floor" | "consent_missing" | "withdrawal_executed";
306
+ count: number;
307
+ }): void;
296
308
  contextTelemetryHealth(data: {
297
309
  trigger: "compaction" | "close";
298
310
  accepted_count: number;
@@ -87,6 +87,11 @@ export declare const _internals: {
87
87
  oldest_age_ms: number;
88
88
  grammar_counts: Record<string, number>;
89
89
  }): void;
90
+ trainingVaultHealth(data: {
91
+ project_ref: string;
92
+ reason: "quota_bytes" | "quota_records" | "disk_floor" | "consent_missing" | "withdrawal_executed";
93
+ count: number;
94
+ }): void;
90
95
  contextTelemetryHealth(data: {
91
96
  trigger: "compaction" | "close";
92
97
  accepted_count: number;
@@ -0,0 +1,37 @@
1
+ import { type TrainingConsent } from './consent';
2
+ import { appendTrainingVaultRecord, buildTrainingVaultRecord } from './vault';
3
+ interface MessageLike {
4
+ info?: {
5
+ role?: string;
6
+ id?: string;
7
+ sessionID?: string;
8
+ };
9
+ parts?: Array<{
10
+ type?: string;
11
+ text?: string;
12
+ }>;
13
+ }
14
+ interface ToolExecutionLike {
15
+ tool: string;
16
+ sessionID?: string;
17
+ input?: unknown;
18
+ output?: unknown;
19
+ error?: unknown;
20
+ }
21
+ export interface TrainingCaptureObserver {
22
+ observeMessages(output: {
23
+ messages?: MessageLike[];
24
+ }): Promise<void>;
25
+ observeToolExecution(event: ToolExecutionLike): Promise<void>;
26
+ }
27
+ export declare const _internals: {
28
+ appendRecord: typeof appendTrainingVaultRecord;
29
+ readConsent: (directory: string) => TrainingConsent | null;
30
+ buildRecord: typeof buildTrainingVaultRecord;
31
+ };
32
+ /**
33
+ * Create the observer. Pure construction — no filesystem access until the
34
+ * first observation (which itself only reads when a message actually arrives).
35
+ */
36
+ export declare function createTrainingCaptureObserver(directory: string): TrainingCaptureObserver;
37
+ export {};
@@ -0,0 +1,96 @@
1
+ import { z } from 'zod';
2
+ export declare const TRAINING_CONSENT_SCHEMA_VERSION = 1;
3
+ /** Version of the consent TERMS presented to the human (bump when terms change). */
4
+ export declare const TRAINING_CONSENT_CURRENT_VERSION = 1;
5
+ /** Hard per-project vault maxima (source contract #2050 §6). Lower is allowed; higher is not. */
6
+ export declare const TRAINING_QUOTA_CEILINGS: {
7
+ readonly maxBytes: 1073741824;
8
+ readonly maxRecords: 250000;
9
+ readonly retentionDays: 30;
10
+ };
11
+ /** Hard per-project export maxima. */
12
+ export declare const TRAINING_EXPORT_QUOTA_CEILINGS: {
13
+ readonly maxBytes: 1073741824;
14
+ readonly maxExports: 20;
15
+ readonly retentionDays: 30;
16
+ };
17
+ export declare const TrainingProjectBindingSchema: z.ZodObject<{
18
+ rootDigest: z.ZodString;
19
+ projectRef: z.ZodString;
20
+ }, z.core.$strict>;
21
+ export declare const TrainingConsentSchema: z.ZodObject<{
22
+ schema_version: z.ZodLiteral<1>;
23
+ consent_id: z.ZodString;
24
+ state: z.ZodEnum<{
25
+ granted: "granted";
26
+ withdrawn: "withdrawn";
27
+ }>;
28
+ consent_version: z.ZodLiteral<1>;
29
+ granted_at: z.ZodString;
30
+ withdrawn_at: z.ZodOptional<z.ZodString>;
31
+ expires_at: z.ZodString;
32
+ purpose: z.ZodString;
33
+ content_classes: z.ZodArray<z.ZodString>;
34
+ quotas: z.ZodObject<{
35
+ maxBytes: z.ZodNumber;
36
+ maxRecords: z.ZodNumber;
37
+ retentionDays: z.ZodNumber;
38
+ }, z.core.$strip>;
39
+ redaction_version: z.ZodLiteral<1>;
40
+ project_binding: z.ZodObject<{
41
+ rootDigest: z.ZodString;
42
+ projectRef: z.ZodString;
43
+ }, z.core.$strict>;
44
+ }, z.core.$strict>;
45
+ export type TrainingConsent = z.infer<typeof TrainingConsentSchema>;
46
+ export interface GrantTrainingConsentInput {
47
+ quotas?: Partial<{
48
+ maxBytes: number;
49
+ maxRecords: number;
50
+ retentionDays: number;
51
+ }>;
52
+ expiresAt?: string;
53
+ now?: Date;
54
+ }
55
+ /**
56
+ * The project identity a consent is bound to. `rootDigest` pins the canonical
57
+ * absolute root (clone/copy produces a different digest); `projectRef` reuses
58
+ * the observability lineage pseudonym so vault records correlate with the
59
+ * metadata-only event stream without carrying raw paths.
60
+ */
61
+ export declare function computeProjectBinding(directory: string): {
62
+ rootDigest: string;
63
+ projectRef: string;
64
+ };
65
+ /**
66
+ * Write a new granted consent record (atomically). A prior record — granted or
67
+ * withdrawn — is replaced; each grant carries a fresh consent_id so vault
68
+ * records remain attributable to the exact grant they were captured under.
69
+ */
70
+ export declare function grantTrainingConsent(directory: string, input?: GrantTrainingConsentInput): TrainingConsent;
71
+ /**
72
+ * Mark the consent withdrawn. Capture stops immediately (every observation
73
+ * re-reads the active consent); physical content deletion is the withdraw
74
+ * command's confirmed step, not this write.
75
+ */
76
+ export declare function revokeTrainingConsent(directory: string, options?: {
77
+ now?: Date;
78
+ }): void;
79
+ /**
80
+ * The capture-gating consent read. Fail-closed: missing file, malformed JSON,
81
+ * schema mismatch, `state !== 'granted'`, expiry, or a project binding issued
82
+ * for a different canonical root all return null.
83
+ */
84
+ export declare function readActiveTrainingConsent(directory: string, options?: {
85
+ now?: Date;
86
+ }): TrainingConsent | null;
87
+ /**
88
+ * Read a granted, project-bound consent WITHOUT the wall-clock expiry check.
89
+ * The capture observer uses `readActiveTrainingConsent` (expiry-aware); the
90
+ * vault's append gate instead validates that the consent was active AT THE
91
+ * RECORD'S captured_at, so a record legitimately captured before expiry still
92
+ * lands while any capture attempted under an expired grant is refused.
93
+ */
94
+ export declare function readGrantedTrainingConsent(directory: string): TrainingConsent | null;
95
+ /** Read the raw consent state for status reporting (never throws). */
96
+ export declare function readTrainingConsentState(directory: string): 'granted' | 'withdrawn' | 'absent';
@@ -0,0 +1,16 @@
1
+ /** Hard free-space floor: max(2 GiB, 10% of the volume size). */
2
+ export declare const TRAINING_DISK_FLOOR_BYTES = 2147483648;
3
+ export interface DiskFloorCheck {
4
+ ok: boolean;
5
+ freeBytes?: number;
6
+ floorBytes: number;
7
+ reason?: 'disk_floor';
8
+ }
9
+ /**
10
+ * Check the free-space floor for the volume holding the training tree.
11
+ * The reported `floorBytes` is the guaranteed constant floor; the ok/not-ok
12
+ * decision uses the stricter of that floor and 10% of the volume size.
13
+ * Never throws: an unprobeable volume reports ok with the byte caps as the
14
+ * remaining bound (see module doc).
15
+ */
16
+ export declare function checkTrainingDiskFloor(directory: string): DiskFloorCheck;
@@ -0,0 +1,88 @@
1
+ import { z } from 'zod';
2
+ import { listTrainingTombstones, type TrainingVaultRecord } from './vault';
3
+ export declare const TRAINING_EXPORT_SCHEMA_VERSION = 1;
4
+ export declare const TrainingExportFiltersSchema: z.ZodObject<{
5
+ kinds: z.ZodOptional<z.ZodArray<z.ZodEnum<{
6
+ user_message: "user_message";
7
+ assistant_message: "assistant_message";
8
+ tool_call: "tool_call";
9
+ tool_result: "tool_result";
10
+ }>>>;
11
+ sessionId: z.ZodOptional<z.ZodString>;
12
+ taskId: z.ZodOptional<z.ZodString>;
13
+ since: z.ZodOptional<z.ZodString>;
14
+ validationRatio: z.ZodOptional<z.ZodNumber>;
15
+ }, z.core.$strict>;
16
+ export type TrainingExportFilters = z.infer<typeof TrainingExportFiltersSchema>;
17
+ export interface ExportPreview {
18
+ exportId: string;
19
+ recordCount: number;
20
+ estimatedBytes: number;
21
+ destination: string;
22
+ split: {
23
+ train: number;
24
+ validation: number;
25
+ };
26
+ quarantinedExcluded: number;
27
+ expiredExcluded: number;
28
+ requiresConfirm: true;
29
+ }
30
+ export interface ExportExecution {
31
+ written: boolean;
32
+ exportId?: string;
33
+ destination?: string;
34
+ reason?: 'token_mismatch' | 'token_expired' | 'scope_changed' | 'empty' | 'export_quota' | 'export_revoked';
35
+ }
36
+ export type ExportFiles = Record<'records.jsonl' | 'train.jsonl' | 'validation.jsonl' | 'manifest.json', string>;
37
+ export interface ExportBundle {
38
+ exportId: string;
39
+ files: ExportFiles;
40
+ }
41
+ interface PendingOpRecord {
42
+ schema_version: 1;
43
+ kind: 'export' | 'withdraw' | 'consent';
44
+ scope_digest: string;
45
+ confirm_token: string;
46
+ created_at: number;
47
+ }
48
+ /**
49
+ * Build the deterministic export bundle. The export id hashes the schema
50
+ * versions, the canonical filters, and each included record's id + consent id
51
+ * (so an identical re-export of identical content under the same consent is
52
+ * idempotent, while a fresh consent cycle yields a fresh id).
53
+ */
54
+ export declare function buildTrainingExportBundle(records: TrainingVaultRecord[], filters?: TrainingExportFilters, options?: {
55
+ quarantinedExcluded?: number;
56
+ expiredExcluded?: number;
57
+ }): ExportBundle;
58
+ /** Side-effect-free export preview: no files written, no token issued. */
59
+ export declare function previewTrainingExport(directory: string, filters?: TrainingExportFilters): ExportPreview;
60
+ export declare function consumeTrainingPendingOp(directory: string): void;
61
+ /** Arm the single pending-op slot and return the 24-hex confirmation token. */
62
+ export declare function issueTrainingConfirmToken(directory: string, scope: {
63
+ kind: 'export' | 'withdraw' | 'consent';
64
+ digest: string;
65
+ }): string;
66
+ type TokenCheck = {
67
+ ok: true;
68
+ record: PendingOpRecord;
69
+ } | {
70
+ ok: false;
71
+ reason: 'token_mismatch' | 'token_expired';
72
+ };
73
+ export declare function checkTrainingConfirmToken(directory: string, kind: 'export' | 'withdraw' | 'consent', token: string): TokenCheck;
74
+ declare function countExportDirs(directory: string): number;
75
+ export declare const _internals: {
76
+ countExportDirs: typeof countExportDirs;
77
+ listTombstones: typeof listTrainingTombstones;
78
+ };
79
+ /**
80
+ * Execute the confirmed export: consumes the token (single use), re-derives
81
+ * the CURRENT scope digest from the vault + filters, writes the bundle
82
+ * atomically under `<root>/exports/<exportId>/`. Identical re-exports are
83
+ * idempotent (same destination, same bytes).
84
+ */
85
+ export declare function executeTrainingExport(directory: string, filters: TrainingExportFilters | undefined, options: {
86
+ confirmToken: string;
87
+ }): ExportExecution;
88
+ export {};
@@ -0,0 +1,20 @@
1
+ /** Root directory name of the governed training tree, relative to `.swarm/`. */
2
+ export declare const TRAINING_ROOT_NAME = ".swarm/training/v1";
3
+ /** Resolved absolute root of the training tree for a project directory. */
4
+ export declare function trainingRootDir(directory: string): string;
5
+ /** `<root>/vault/records.jsonl` — the append-only vault record store. */
6
+ export declare function trainingVaultRecordsPath(directory: string): string;
7
+ /** `<root>/vault/quarantine.jsonl` — journal of quarantined corrupt lines. */
8
+ export declare function trainingQuarantinePath(directory: string): string;
9
+ /** `<root>/consent.json` — the durable, separately-consented grant record. */
10
+ export declare function trainingConsentPath(directory: string): string;
11
+ /** `<root>/tombstones.jsonl` — append-only withdrawal tombstones (never pruned). */
12
+ export declare function trainingTombstonesPath(directory: string): string;
13
+ /** `<root>/health.json` — bounded capture-health state (stop reasons, counters). */
14
+ export declare function trainingHealthPath(directory: string): string;
15
+ /** `<root>/exports` — contained dataset export bundles (`<exports>/<exportId>/`). */
16
+ export declare function trainingExportsDir(directory: string): string;
17
+ /** `<root>/pending-op.json` — single-slot confirmation token store. */
18
+ export declare function trainingPendingOpPath(directory: string): string;
19
+ /** Directory portion of a resolved training path (for mkdir before writes). */
20
+ export declare function parentDirOf(filePath: string): string;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Issue #2486: capture-time defense-in-depth redaction for training content.
3
+ *
4
+ * Mirrors the URL / credential-pattern classes of
5
+ * `sanitizeFailureEvidenceDisplay` (`src/failures/invocation-failure.ts`)
6
+ * WITHOUT that function's 512-byte display bounding — vault records keep the
7
+ * contracted 4096-char content budget. This is defense-in-depth, not a
8
+ * security boundary (same honest framing as #2369): the human consenting to
9
+ * capture is trusting the redactor class, and the recorded
10
+ * `redaction.version` pins which revision produced each stored record.
11
+ */
12
+ /** Bumped when the pattern set changes; recorded on every vault record.
13
+ * v1's pattern set was extended pre-release (quoted-JSON credential shapes,
14
+ * scheme-prefixed tokens) before any v1 record shipped, so the first released
15
+ * revision covers the full set and no migration surface exists. */
16
+ export declare const TRAINING_REDACTION_VERSION = 1;
17
+ export interface RedactionResult {
18
+ content: string;
19
+ applied: boolean;
20
+ redactions: number;
21
+ }
22
+ /**
23
+ * Redact URL and credential patterns from already-bounded capture content
24
+ * (callers bound FIRST — a placeholder can be longer than the span it
25
+ * replaces, and truncating after redaction would collapse distinct inputs
26
+ * onto one identity). Pure; never throws (on internal failure the content is
27
+ * withheld rather than stored raw).
28
+ */
29
+ export declare function redactTrainingContent(content: string): RedactionResult;
@@ -0,0 +1,177 @@
1
+ import { z } from 'zod';
2
+ import { type TrainingConsent } from './consent';
3
+ import { type DiskFloorCheck } from './disk';
4
+ export declare const TRAINING_VAULT_SCHEMA_VERSION = 1;
5
+ /** Re-exported alias recorded on every vault record (see `./redact.ts`). */
6
+ export declare const REDACTION_VERSION = 1;
7
+ export declare const TrainingVaultKindSchema: z.ZodEnum<{
8
+ user_message: "user_message";
9
+ assistant_message: "assistant_message";
10
+ tool_call: "tool_call";
11
+ tool_result: "tool_result";
12
+ }>;
13
+ export type TrainingVaultKind = z.infer<typeof TrainingVaultKindSchema>;
14
+ export declare const TrainingVaultRecordSchema: z.ZodObject<{
15
+ record_id: z.ZodString;
16
+ schema_version: z.ZodLiteral<1>;
17
+ kind: z.ZodEnum<{
18
+ user_message: "user_message";
19
+ assistant_message: "assistant_message";
20
+ tool_call: "tool_call";
21
+ tool_result: "tool_result";
22
+ }>;
23
+ role: z.ZodString;
24
+ content: z.ZodString;
25
+ content_digest: z.ZodString;
26
+ lineage: z.ZodObject<{
27
+ session_id: z.ZodString;
28
+ task_id: z.ZodOptional<z.ZodString>;
29
+ trace_id: z.ZodOptional<z.ZodString>;
30
+ project_ref: z.ZodString;
31
+ captured_at: z.ZodString;
32
+ }, z.core.$strict>;
33
+ labels: z.ZodArray<z.ZodObject<{
34
+ name: z.ZodString;
35
+ value: z.ZodString;
36
+ provenance: z.ZodString;
37
+ confidence: z.ZodNumber;
38
+ }, z.core.$strict>>;
39
+ provenance: z.ZodObject<{
40
+ plugin_version: z.ZodString;
41
+ source: z.ZodEnum<{
42
+ tool: "tool";
43
+ chat: "chat";
44
+ }>;
45
+ }, z.core.$strict>;
46
+ redaction: z.ZodObject<{
47
+ version: z.ZodLiteral<1>;
48
+ applied: z.ZodBoolean;
49
+ redactions: z.ZodNumber;
50
+ }, z.core.$strict>;
51
+ consent: z.ZodObject<{
52
+ id: z.ZodString;
53
+ version: z.ZodNumber;
54
+ }, z.core.$strict>;
55
+ retention: z.ZodObject<{
56
+ expires_at: z.ZodString;
57
+ }, z.core.$strict>;
58
+ }, z.core.$strict>;
59
+ export type TrainingVaultRecord = z.infer<typeof TrainingVaultRecordSchema>;
60
+ export declare const TrainingWithdrawalTombstoneSchema: z.ZodObject<{
61
+ schema_version: z.ZodLiteral<1>;
62
+ tombstone_id: z.ZodString;
63
+ withdrawn_at: z.ZodString;
64
+ purged_records: z.ZodNumber;
65
+ purged_record_ids_digest: z.ZodString;
66
+ revoked_export_ids: z.ZodArray<z.ZodString>;
67
+ }, z.core.$strict>;
68
+ export type TrainingWithdrawalTombstone = z.infer<typeof TrainingWithdrawalTombstoneSchema>;
69
+ export type TrainingStopReason = 'quota_bytes' | 'quota_records' | 'disk_floor' | 'consent_missing';
70
+ export interface AppendResult {
71
+ appended: boolean;
72
+ stopReason?: TrainingStopReason;
73
+ }
74
+ export interface QuarantinedItem {
75
+ line: number;
76
+ reason: 'malformed_json' | 'schema_invalid';
77
+ }
78
+ export interface VaultRead {
79
+ records: TrainingVaultRecord[];
80
+ quarantined: QuarantinedItem[];
81
+ }
82
+ export interface VaultStatus {
83
+ recordCount: number;
84
+ vaultBytes: number;
85
+ consentState: 'granted' | 'withdrawn' | 'absent';
86
+ lastStopReason?: string;
87
+ tombstoneCount: number;
88
+ quarantinedCount: number;
89
+ }
90
+ export interface PurgeResult {
91
+ purgedRecords: number;
92
+ tombstone: TrainingWithdrawalTombstone;
93
+ revokedExports: string[];
94
+ }
95
+ export interface LabelInput {
96
+ name: string;
97
+ value: string;
98
+ provenance: string;
99
+ confidence: number;
100
+ }
101
+ export interface BuildRecordInput {
102
+ directory: string;
103
+ kind: TrainingVaultKind;
104
+ role: string;
105
+ content: string;
106
+ sessionId: string;
107
+ taskId?: string;
108
+ traceId?: string;
109
+ pluginVersion: string;
110
+ source: 'chat' | 'tool';
111
+ consent: TrainingConsent;
112
+ labels?: LabelInput[];
113
+ now?: Date;
114
+ }
115
+ /**
116
+ * Build a vault record per the frozen contract: content is bounded FIRST
117
+ * (4096 chars) then redacted (redaction placeholders can outgrow the spans
118
+ * they replace; bounding after redaction would collapse distinct inputs onto
119
+ * one identity); `content_digest` hashes the final stored content;
120
+ * `record_id` binds projectRef + session + kind + role + digest so repeat
121
+ * observations of the same surface dedup to one record id; retention is the
122
+ * earlier of captured_at + retentionDays and the consent's own expiry.
123
+ */
124
+ export declare function buildTrainingVaultRecord(input: BuildRecordInput): TrainingVaultRecord;
125
+ export declare const _internals: {
126
+ statfsCheck: (directory: string) => DiskFloorCheck;
127
+ appendFile: (target: string, data: string) => void | Promise<void>;
128
+ readFile: (target: string) => string;
129
+ now: () => Date;
130
+ };
131
+ /**
132
+ * The ONLY vault write path. Gates, in order: active consent for THIS root
133
+ * (fail-closed, no file creation on refusal), disk floor, byte cap, record
134
+ * cap. A write is only accepted when it is synchronously confirmed durable
135
+ * (the vault file grew) — an async/unconfirmed seam result or a write error
136
+ * fails closed as `disk_floor`. Unexpired records are never evicted.
137
+ */
138
+ export declare function appendTrainingVaultRecord(directory: string, record: TrainingVaultRecord): AppendResult;
139
+ /**
140
+ * Read the vault. Corrupt items are quarantined with a typed reason, journaled
141
+ * to `<root>/vault/quarantine.jsonl` (deduped in-process by line content), and
142
+ * excluded from `records`. Never throws on corrupt content.
143
+ */
144
+ export declare function readTrainingVault(directory: string): VaultRead;
145
+ /** Current valid + quarantined counts without journaling (status surfaces). */
146
+ export declare function getTrainingVaultStatus(directory: string): VaultStatus;
147
+ /**
148
+ * Physically purge records past their retention expiry (honored retention —
149
+ * distinct from quota stops, which never delete). Tombstones are untouched.
150
+ */
151
+ export declare function sweepTrainingVaultExpiry(directory: string, options?: {
152
+ now?: Date;
153
+ }): {
154
+ purged: number;
155
+ };
156
+ /**
157
+ * Physically delete ALL vault content, append a durable withdrawal tombstone,
158
+ * and revoke every export still under plugin control with a `REVOKED.json`
159
+ * revocation manifest. Tombstones from prior withdrawals are never touched.
160
+ *
161
+ * The export listing happens BEFORE any destruction: if the exports dir is
162
+ * unreadable (not merely absent), the purge refuses rather than truncating
163
+ * records and then silently writing a tombstone that under-reports the
164
+ * revocation set.
165
+ */
166
+ export declare function purgeTrainingVaultContent(directory: string, options?: {
167
+ now?: Date;
168
+ }): PurgeResult;
169
+ /** All durable withdrawal tombstones (corrupt lines skipped). */
170
+ export declare function listTrainingTombstones(directory: string): TrainingWithdrawalTombstone[];
171
+ export interface TrainingExportRevocation {
172
+ exportId: string;
173
+ revokedAt: string;
174
+ tombstoneId: string;
175
+ }
176
+ /** Revocation manifests for exports still under plugin control. */
177
+ export declare function readTrainingExportRevocations(directory: string): TrainingExportRevocation[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.170.2",
3
+ "version": "7.171.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",