@quantiya/codevibe-claude-plugin 2.0.17 → 2.0.19

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 (47) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/server.js +18 -18
  3. package/node_modules/@quantiya/codevibe-core/dist/__tests__/mobile-prompt-input.test.d.ts +1 -0
  4. package/node_modules/@quantiya/codevibe-core/dist/appsync/__tests__/group-operation-result.test.d.ts +1 -0
  5. package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +155 -0
  6. package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.d.ts +14 -0
  7. package/node_modules/@quantiya/codevibe-core/dist/crypto/__tests__/crypto-service.test.d.ts +1 -0
  8. package/node_modules/@quantiya/codevibe-core/dist/crypto/crypto-service.d.ts +7 -0
  9. package/node_modules/@quantiya/codevibe-core/dist/index.d.ts +2 -0
  10. package/node_modules/@quantiya/codevibe-core/dist/index.js +525 -304
  11. package/node_modules/@quantiya/codevibe-core/dist/local-executor/local-executor-impl.d.ts +34 -0
  12. package/node_modules/@quantiya/codevibe-core/dist/local-executor/snapshot-merge.d.ts +6 -0
  13. package/node_modules/@quantiya/codevibe-core/dist/local-executor/types.d.ts +6 -0
  14. package/node_modules/@quantiya/codevibe-core/dist/mobile-prompt-input.d.ts +13 -0
  15. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/decision-attempt-live-handoff.test.d.ts +1 -0
  16. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/decision-attempt-recovery.test.d.ts +1 -0
  17. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/decision-attempt-session-serialization.test.d.ts +1 -0
  18. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/decision-attempt.test.d.ts +1 -0
  19. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/decision-effect.test.d.ts +1 -0
  20. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/gate-resolution-event.test.d.ts +1 -0
  21. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/supervision-catch-up.test.d.ts +1 -0
  22. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/workspace-outcome.test.d.ts +1 -0
  23. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/workspace-terminal-coordinator.test.d.ts +1 -0
  24. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.d.ts +3 -0
  25. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +5621 -1758
  26. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/components/ConversationPane.d.ts +2 -1
  27. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/components/GatePromptEntry.d.ts +1 -0
  28. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/decision-attempt-recovery.d.ts +70 -0
  29. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/decision-attempt.d.ts +211 -0
  30. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/decision-effect.d.ts +39 -0
  31. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/emit-shell-event.d.ts +20 -2
  32. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/gate-decision-submit.d.ts +20 -2
  33. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/gate-prompts.d.ts +4 -0
  34. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/gate-resolution-event.d.ts +10 -0
  35. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/index.d.ts +6 -2
  36. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/quorum-loop.d.ts +11 -0
  37. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/supervision-catch-up.d.ts +7 -0
  38. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/types.d.ts +57 -0
  39. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/workspace-outcome.d.ts +20 -0
  40. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/workspace-terminal-coordinator.d.ts +114 -0
  41. package/node_modules/@quantiya/codevibe-core/dist/types/events.d.ts +7 -0
  42. package/node_modules/@quantiya/codevibe-core/dist/types/session.d.ts +2 -0
  43. package/node_modules/@quantiya/codevibe-core/package.json +1 -1
  44. package/node_modules/fs-ext/build/Makefile +1 -1
  45. package/node_modules/fs-ext/build/Release/fs_ext.node +0 -0
  46. package/node_modules/fs-ext/build/config.gypi +0 -2
  47. package/package.json +2 -2
@@ -32,6 +32,28 @@ export type PostDecisionAction = {
32
32
  kind: 'continuation_switch_declined';
33
33
  offer_id: string;
34
34
  };
35
+ /** Strictly classified server-authored P16/P20 gate-resolution fact. */
36
+ export interface DurableGateResolution {
37
+ eventId: string;
38
+ sessionId: string;
39
+ promptId: string;
40
+ decisionClaimId: string;
41
+ subjectKind: 'TASK' | 'TASK_GROUP';
42
+ subjectId: string;
43
+ decision: string;
44
+ label: string;
45
+ resolvedAt: string;
46
+ effectRecipe: Record<string, unknown>;
47
+ gateId?: string;
48
+ taskId?: string;
49
+ taskGroupId?: string;
50
+ groupGeneration?: number;
51
+ notesEncrypted?: {
52
+ ciphertextB64: string;
53
+ sessionId: string;
54
+ keyVersion: 1;
55
+ };
56
+ }
35
57
  /**
36
58
  * CP-1.f execute-first (D5): does this `applyUserDecision` outcome mean the
37
59
  * task's workspace shadow must be DISCARDED?
@@ -369,6 +391,14 @@ export type ConversationEntry = {
369
391
  decisionDraft: string;
370
392
  } | {
371
393
  phase: 'submitting';
394
+ } | {
395
+ phase: 'confirming';
396
+ decisionAttemptId: string;
397
+ canonicalRequestHash: string;
398
+ decisionClaimId: string | null;
399
+ } | {
400
+ phase: 'claimed';
401
+ decisionClaimId: string | null;
372
402
  } | {
373
403
  phase: 'resolved';
374
404
  postAction: PostDecisionAction;
@@ -377,6 +407,10 @@ export type ConversationEntry = {
377
407
  phase: 'resolved';
378
408
  resolvedBy: 'server';
379
409
  serverDecision: string | null;
410
+ } | {
411
+ phase: 'resolved';
412
+ resolvedBy: 'durable';
413
+ resolution: DurableGateResolution;
380
414
  };
381
415
  reviewSummary?: ReviewSummaryPanelModel;
382
416
  queuedReviewSummaries?: Readonly<Record<string, ReviewSummaryPanelModel>>;
@@ -679,6 +713,12 @@ export interface OrchestrationState {
679
713
  * enum labels only — never decrypted payload content.
680
714
  */
681
715
  auditFlagIndex: AuditFlagIndex | null;
716
+ /** P16/P20 authoritative resolution union, keyed by retained promptId. */
717
+ gateResolutions: Map<string, DurableGateResolution>;
718
+ /** P16/P20 claim-time action fences, keyed by retained promptId. */
719
+ gateActionClaims: Map<string, string | null>;
720
+ /** True while prompt-action catch-up is not authoritative after a disconnect. */
721
+ gateActionRecoveryBlocked: boolean;
682
722
  }
683
723
  /**
684
724
  * One retained `/audit` listing row, keyed by its audit `entry_id` in
@@ -839,6 +879,13 @@ export type OrchestrationAction = {
839
879
  } | {
840
880
  type: 'GATE_PROMPT_SUBMIT_STARTED';
841
881
  promptEntryId: string;
882
+ } | {
883
+ type: 'GATE_PROMPT_DECISION_FENCED';
884
+ promptEntryId: string;
885
+ gateId: string;
886
+ decisionAttemptId: string;
887
+ canonicalRequestHash: string;
888
+ decisionClaimId: string | null;
842
889
  } | {
843
890
  type: 'GATE_PROMPT_RESOLVED';
844
891
  promptEntryId: string;
@@ -854,6 +901,16 @@ export type OrchestrationAction = {
854
901
  promptEntryId: string;
855
902
  gateId: string;
856
903
  serverDecision: string | null;
904
+ } | {
905
+ type: 'GATE_RESOLUTION_RECEIVED';
906
+ resolution: DurableGateResolution;
907
+ } | {
908
+ type: 'GATE_PROMPT_ACTION_FENCED';
909
+ gateId: string;
910
+ decisionClaimId: string | null;
911
+ } | {
912
+ type: 'GATE_ACTION_RECOVERY_CHANGED';
913
+ blocked: boolean;
857
914
  } | {
858
915
  type: 'SHELL_ADVISORY';
859
916
  text: string;
@@ -0,0 +1,20 @@
1
+ import type { Event } from '../types/events';
2
+ export type WorkspaceOutcomeKind = 'applied' | 'not_applied' | 'discarded' | 'apply_failed' | 'kept' | 'reverted' | 'partially_reverted';
3
+ export interface DurableWorkspaceOutcome {
4
+ eventId: string;
5
+ sessionId: string;
6
+ sessionGenerationId: string;
7
+ subjectKind: 'TASK' | 'TASK_GROUP';
8
+ subjectId: string;
9
+ groupGeneration?: number;
10
+ outcome: WorkspaceOutcomeKind;
11
+ message: string;
12
+ filesApplied?: number;
13
+ filesRetained?: number;
14
+ filesReverted?: number;
15
+ filesConflicted?: number;
16
+ timestamp: string;
17
+ }
18
+ export declare function deterministicWorkspaceOutcomeNonce(sessionId: string, subjectKind: 'task' | 'task_group', subjectId: string): string;
19
+ /** Strictly classify a backend-attested, successfully decrypted outcome row. */
20
+ export declare function classifyDurableWorkspaceOutcome(event: Event, displayedSessionId: string, decryptedMetadata: unknown, expectedSessionGenerationId?: string): DurableWorkspaceOutcome | null;
@@ -0,0 +1,114 @@
1
+ import { type AppSyncClient } from '../appsync';
2
+ import { type Session } from '../types';
3
+ import { type EmitShellEventDeps } from './emit-shell-event';
4
+ import type { DurableGateResolution } from './types';
5
+ import { type WorkspaceOutcomeKind } from './workspace-outcome';
6
+ export type TaskTerminalOperation = 'PROMOTE' | 'CANCEL' | 'ABORT';
7
+ export type TaskTerminalOutcome = Extract<WorkspaceOutcomeKind, 'applied' | 'not_applied' | 'discarded' | 'apply_failed'>;
8
+ export type GroupTerminalOperation = 'KEEP' | 'REVERT' | 'PROMOTE';
9
+ export type GroupTerminalOutcome = Extract<WorkspaceOutcomeKind, 'applied' | 'apply_failed' | 'kept' | 'reverted' | 'partially_reverted'>;
10
+ export interface GroupTerminalAuthority {
11
+ anchorId: string;
12
+ anchorTimestamp: string;
13
+ manifestHash: string;
14
+ memberCount: number;
15
+ operationHash: string;
16
+ /** Present when the server has already begun a PROMOTE replay. */
17
+ operationToken?: string;
18
+ }
19
+ export interface GroupTerminalReservation extends GroupTerminalAuthority {
20
+ /** Persisted locally before beginGroupPromotion; absent for KEEP/REVERT. */
21
+ operationToken?: string;
22
+ }
23
+ export interface GroupTerminalDetails {
24
+ filesApplied?: number;
25
+ filesRetained?: number;
26
+ filesReverted?: number;
27
+ filesConflicted?: number;
28
+ }
29
+ export interface WorkspaceOutcomeSink {
30
+ registerResolution(resolution: DurableGateResolution): Promise<void>;
31
+ hasTaskResolution(taskId: string): boolean;
32
+ hasPendingTask(taskId: string): Promise<boolean>;
33
+ reserveTask(taskId: string, operation: TaskTerminalOperation): Promise<void>;
34
+ completeTask(taskId: string, outcome: TaskTerminalOutcome, details?: {
35
+ filesApplied?: number;
36
+ }): Promise<void>;
37
+ reserveGroup(taskGroupId: string, groupGeneration: number, operation: GroupTerminalOperation, authority: GroupTerminalAuthority): Promise<GroupTerminalReservation>;
38
+ cancelGroupReservation(taskGroupId: string, groupGeneration: number, operation: GroupTerminalOperation, authority: GroupTerminalAuthority): Promise<void>;
39
+ prepareGroupOutcome(taskGroupId: string, outcome: GroupTerminalOutcome, details: GroupTerminalDetails): Promise<void>;
40
+ publishGroupOutcome(taskGroupId: string): Promise<void>;
41
+ completeGroup(taskGroupId: string, outcome: GroupTerminalOutcome, details: GroupTerminalDetails): Promise<void>;
42
+ }
43
+ /** Bootstrap bridge between the shell-owned coordinator and the team LE. */
44
+ export interface WorkspaceOutcomeSinkTap {
45
+ sink?: WorkspaceOutcomeSink;
46
+ }
47
+ export interface WorkspaceTerminalCoordinatorOptions {
48
+ session: Session;
49
+ appsyncClient: Pick<AppSyncClient, 'createEvent'>;
50
+ getSessionKey: EmitShellEventDeps['getSessionKey'];
51
+ rootDir?: string;
52
+ now?: () => Date;
53
+ onSyncIssue?: (message: string) => void;
54
+ }
55
+ /**
56
+ * Crash-safe owner for the single-task terminal edge. The local receipt is the
57
+ * pre-effect capacity reservation; the outbox contains the exact encrypted and
58
+ * signed CreateEvent input captured before its first network attempt.
59
+ */
60
+ export declare class WorkspaceTerminalCoordinator implements WorkspaceOutcomeSink {
61
+ private readonly session;
62
+ private readonly appsyncClient;
63
+ private readonly getSessionKey;
64
+ private readonly rootDir;
65
+ private readonly now;
66
+ private readonly onSyncIssue?;
67
+ private readonly resolutions;
68
+ private operationChain;
69
+ constructor(options: WorkspaceTerminalCoordinatorOptions);
70
+ private generation;
71
+ private intentRoot;
72
+ private outboxRoot;
73
+ private draftRoot;
74
+ private quarantineRoot;
75
+ private intentDir;
76
+ private outboxDir;
77
+ private draftDir;
78
+ private quarantineDir;
79
+ private intentPath;
80
+ private outboxPath;
81
+ private draftPath;
82
+ private serialize;
83
+ private readJson;
84
+ private listRecords;
85
+ private listGenerationDirectories;
86
+ private listRecordsAcrossGenerations;
87
+ private cleanTemporaryFiles;
88
+ private cleanTemporaryFilesAcrossGenerations;
89
+ private assertCapacity;
90
+ private chain;
91
+ registerResolution(resolution: DurableGateResolution): Promise<void>;
92
+ hasTaskResolution(taskId: string): boolean;
93
+ hasPendingTask(taskId: string): Promise<boolean>;
94
+ reserveTask(taskId: string, operation: TaskTerminalOperation): Promise<void>;
95
+ completeTask(taskId: string, outcome: TaskTerminalOutcome, details?: {
96
+ filesApplied?: number;
97
+ }): Promise<void>;
98
+ reserveGroup(taskGroupId: string, groupGeneration: number, operation: GroupTerminalOperation, authority: GroupTerminalAuthority): Promise<GroupTerminalReservation>;
99
+ cancelGroupReservation(taskGroupId: string, groupGeneration: number, operation: GroupTerminalOperation, authority: GroupTerminalAuthority): Promise<void>;
100
+ private groupTerminal;
101
+ prepareGroupOutcome(taskGroupId: string, outcome: GroupTerminalOutcome, details: GroupTerminalDetails): Promise<void>;
102
+ publishGroupOutcome(taskGroupId: string): Promise<void>;
103
+ completeGroup(taskGroupId: string, outcome: GroupTerminalOutcome, details: GroupTerminalDetails): Promise<void>;
104
+ private persistExactInput;
105
+ private outcomePayload;
106
+ private prepareExactInput;
107
+ private promoteDraftToOutbox;
108
+ private flushTerminalIntent;
109
+ private acknowledge;
110
+ private quarantine;
111
+ private sendOutbox;
112
+ /** Reconcile terminal receipts first, then replay exact encrypted bytes. */
113
+ replayPending(): Promise<void>;
114
+ }
@@ -75,6 +75,9 @@ export interface Event {
75
75
  encryptionVersion?: number;
76
76
  writerAuthenticated?: boolean | null;
77
77
  writerEventNonce?: string | null;
78
+ writerEventKind?: 'WORKSPACE_OUTCOME' | null;
79
+ writerSessionGenerationId?: string | null;
80
+ emittedBy?: 'SYSTEM' | 'IMPLEMENTOR' | null;
78
81
  }
79
82
  export interface WriterEventAttestationInput {
80
83
  schema: 'codevibe.encrypted_desktop_event.writer.v1';
@@ -104,6 +107,10 @@ export interface CreateEventInput {
104
107
  expectedSessionKeyGen?: string;
105
108
  encryptionVersion?: number;
106
109
  writerAttestation?: WriterEventAttestationInput;
110
+ writerEventKind?: 'WORKSPACE_OUTCOME';
111
+ writerSessionGenerationId?: string;
112
+ writerOutcomeSubject?: Record<string, unknown>;
113
+ writerCausalPredecessor?: Record<string, unknown>;
107
114
  }
108
115
  /**
109
116
  * GraphQL input for updating event status
@@ -52,6 +52,8 @@ export interface Session {
52
52
  writerAttestationEligible?: boolean | null;
53
53
  /** SHA-256 of the raw 64-byte creator signing public key. */
54
54
  creatorSigningKeySha256?: string | null;
55
+ /** Opaque server generation bound into durable desktop outcome signatures. */
56
+ sessionGenerationId?: string | null;
55
57
  /**
56
58
  * Quorum 2.0 opt-in flag (2f.0.a.3). True routes the session to the
57
59
  * 2.0 orchestration flow once 2f.3 Lambda is live; null/false keeps
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -332,7 +332,7 @@ endif
332
332
 
333
333
  quiet_cmd_regen_makefile = ACTION Regenerating $@
334
334
  cmd_regen_makefile = cd $(srcdir); /opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/hendryyeh/Library/Caches/node-gyp/24.4.0" "-Dnode_gyp_dir=/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/Users/hendryyeh/Library/Caches/node-gyp/24.4.0/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/hendryyeh/Workspace/CodeVibe/codevibe-claude-plugin/node_modules/fs-ext" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/Users/hendryyeh/Workspace/CodeVibe/codevibe-claude-plugin/node_modules/fs-ext/build/config.gypi -I/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/hendryyeh/Library/Caches/node-gyp/24.4.0/include/node/common.gypi "--toplevel-dir=." binding.gyp
335
- Makefile: $(srcdir)/../../../../../Library/Caches/node-gyp/24.4.0/include/node/common.gypi $(srcdir)/../../../../../../../opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp
335
+ Makefile: $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/../../../../../Library/Caches/node-gyp/24.4.0/include/node/common.gypi
336
336
  $(call do_cmd,regen_makefile)
337
337
 
338
338
  # "all" is a concatenation of the "all" targets from all the included
@@ -489,7 +489,6 @@
489
489
  "nodedir": "/Users/hendryyeh/Library/Caches/node-gyp/24.4.0",
490
490
  "python": "/opt/homebrew/opt/python@3.14/bin/python3.14",
491
491
  "standalone_static_library": 1,
492
- "audit": "",
493
492
  "global_prefix": "/opt/homebrew",
494
493
  "local_prefix": "/Users/hendryyeh/Workspace/CodeVibe/codevibe-claude-plugin",
495
494
  "globalconfig": "/opt/homebrew/etc/npmrc",
@@ -498,7 +497,6 @@
498
497
  "npm_version": "11.4.2",
499
498
  "node_gyp": "/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js",
500
499
  "cache": "/Users/hendryyeh/.npm",
501
- "fund": "",
502
500
  "user_agent": "npm/11.4.2 node/v24.4.0 darwin arm64 workspaces/false",
503
501
  "prefix": "/opt/homebrew"
504
502
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-claude-plugin",
3
- "version": "2.0.17",
3
+ "version": "2.0.19",
4
4
  "description": "Control Claude Code from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "codevibe": {
@@ -47,7 +47,7 @@
47
47
  "node": ">=22.0.0"
48
48
  },
49
49
  "dependencies": {
50
- "@quantiya/codevibe-core": "2.0.14",
50
+ "@quantiya/codevibe-core": "2.0.16",
51
51
  "@quantiya/quorum-core": "^1.0.1",
52
52
  "dotenv": "^16.6.1",
53
53
  "express": "^5.1.0",