@mc1global/opencode-jarvis 0.9.0 → 0.10.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 (82) hide show
  1. package/dist/application/azure-sync/push-use-cases.d.ts +6 -1
  2. package/dist/application/azure-sync/push-use-cases.d.ts.map +1 -1
  3. package/dist/application/azure-sync/push-use-cases.js +31 -5
  4. package/dist/application/azure-sync/push-use-cases.js.map +1 -1
  5. package/dist/application/config/config-write-service.d.ts +86 -0
  6. package/dist/application/config/config-write-service.d.ts.map +1 -0
  7. package/dist/application/config/config-write-service.js +237 -0
  8. package/dist/application/config/config-write-service.js.map +1 -0
  9. package/dist/application/config/index.d.ts +2 -0
  10. package/dist/application/config/index.d.ts.map +1 -1
  11. package/dist/application/config/index.js +1 -0
  12. package/dist/application/config/index.js.map +1 -1
  13. package/dist/application/context-memory/execution-journal-use-cases.d.ts +69 -0
  14. package/dist/application/context-memory/execution-journal-use-cases.d.ts.map +1 -0
  15. package/dist/application/context-memory/execution-journal-use-cases.js +89 -0
  16. package/dist/application/context-memory/execution-journal-use-cases.js.map +1 -0
  17. package/dist/cli/config-wizard.d.ts +14 -0
  18. package/dist/cli/config-wizard.d.ts.map +1 -0
  19. package/dist/cli/config-wizard.js +120 -0
  20. package/dist/cli/config-wizard.js.map +1 -0
  21. package/dist/cli/section-editors.d.ts +33 -0
  22. package/dist/cli/section-editors.d.ts.map +1 -0
  23. package/dist/cli/section-editors.js +286 -0
  24. package/dist/cli/section-editors.js.map +1 -0
  25. package/dist/cli/wizard-prompts.d.ts +76 -0
  26. package/dist/cli/wizard-prompts.d.ts.map +1 -0
  27. package/dist/cli/wizard-prompts.js +98 -0
  28. package/dist/cli/wizard-prompts.js.map +1 -0
  29. package/dist/domain/azure-sync/value-objects.d.ts +10 -0
  30. package/dist/domain/azure-sync/value-objects.d.ts.map +1 -1
  31. package/dist/domain/azure-sync/value-objects.js +24 -0
  32. package/dist/domain/azure-sync/value-objects.js.map +1 -1
  33. package/dist/domain/config/index.d.ts +1 -1
  34. package/dist/domain/config/index.d.ts.map +1 -1
  35. package/dist/domain/config/repositories.d.ts +26 -6
  36. package/dist/domain/config/repositories.d.ts.map +1 -1
  37. package/dist/domain/config/repositories.js +6 -6
  38. package/dist/domain/context-memory/entities.d.ts +50 -2
  39. package/dist/domain/context-memory/entities.d.ts.map +1 -1
  40. package/dist/domain/context-memory/entities.js +92 -2
  41. package/dist/domain/context-memory/entities.js.map +1 -1
  42. package/dist/domain/context-memory/repositories.d.ts +15 -2
  43. package/dist/domain/context-memory/repositories.d.ts.map +1 -1
  44. package/dist/domain/context-memory/value-objects.d.ts +18 -1
  45. package/dist/domain/context-memory/value-objects.d.ts.map +1 -1
  46. package/dist/domain/context-memory/value-objects.js +39 -1
  47. package/dist/domain/context-memory/value-objects.js.map +1 -1
  48. package/dist/hooks/config-command.d.ts +37 -0
  49. package/dist/hooks/config-command.d.ts.map +1 -0
  50. package/dist/hooks/config-command.js +68 -0
  51. package/dist/hooks/config-command.js.map +1 -0
  52. package/dist/hooks/execution-journal.d.ts +40 -0
  53. package/dist/hooks/execution-journal.d.ts.map +1 -0
  54. package/dist/hooks/execution-journal.js +102 -0
  55. package/dist/hooks/execution-journal.js.map +1 -0
  56. package/dist/hooks/first-run-guide.d.ts +2 -0
  57. package/dist/hooks/first-run-guide.d.ts.map +1 -1
  58. package/dist/hooks/first-run-guide.js +9 -0
  59. package/dist/hooks/first-run-guide.js.map +1 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +58 -3
  62. package/dist/index.js.map +1 -1
  63. package/dist/infrastructure/azure-sync/azure-devops-client.d.ts.map +1 -1
  64. package/dist/infrastructure/azure-sync/azure-devops-client.js +9 -10
  65. package/dist/infrastructure/azure-sync/azure-devops-client.js.map +1 -1
  66. package/dist/infrastructure/config/index.d.ts +1 -0
  67. package/dist/infrastructure/config/index.d.ts.map +1 -1
  68. package/dist/infrastructure/config/index.js +1 -0
  69. package/dist/infrastructure/config/index.js.map +1 -1
  70. package/dist/infrastructure/config/yaml-config-writer.d.ts +16 -0
  71. package/dist/infrastructure/config/yaml-config-writer.d.ts.map +1 -0
  72. package/dist/infrastructure/config/yaml-config-writer.js +49 -0
  73. package/dist/infrastructure/config/yaml-config-writer.js.map +1 -0
  74. package/dist/infrastructure/context-memory/execution-journal-repository.d.ts +26 -0
  75. package/dist/infrastructure/context-memory/execution-journal-repository.d.ts.map +1 -0
  76. package/dist/infrastructure/context-memory/execution-journal-repository.js +110 -0
  77. package/dist/infrastructure/context-memory/execution-journal-repository.js.map +1 -0
  78. package/dist/tools/config-tools.d.ts +12 -0
  79. package/dist/tools/config-tools.d.ts.map +1 -0
  80. package/dist/tools/config-tools.js +136 -0
  81. package/dist/tools/config-tools.js.map +1 -0
  82. package/package.json +4 -2
@@ -6,8 +6,8 @@
6
6
  * SOLID: ISP - one interface per aggregate root
7
7
  */
8
8
  import type { WorkspaceId } from "../shared/value-objects.js";
9
- import type { Session, Todo, Note } from "./entities.js";
10
- import type { SessionId, TodoId, TodoStatus } from "./value-objects.js";
9
+ import type { Session, Todo, Note, ExecutionEntry } from "./entities.js";
10
+ import type { SessionId, TodoId, TodoStatus, ExecutionEntryId } from "./value-objects.js";
11
11
  /** Persistence port for Session aggregate root. */
12
12
  export interface SessionRepository {
13
13
  save(session: Session): Promise<void>;
@@ -43,4 +43,17 @@ export interface ContextSearchResult {
43
43
  readonly content: string;
44
44
  readonly relevance: number;
45
45
  }
46
+ /** Persistence port for ExecutionEntry (execution journal). */
47
+ export interface ExecutionJournalRepository {
48
+ /** Save a new entry; returns entry with persistence-assigned ID. */
49
+ save(entry: ExecutionEntry): Promise<ExecutionEntry>;
50
+ /** Find entry by ID. */
51
+ findById(id: ExecutionEntryId): Promise<ExecutionEntry | null>;
52
+ /** Update an existing entry (state, finishedAt, errorMessage). */
53
+ update(entry: ExecutionEntry): Promise<void>;
54
+ /** Find all entries in Running state for a workspace (orphaned = crash). */
55
+ findRunning(workspace: WorkspaceId): Promise<readonly ExecutionEntry[]>;
56
+ /** Delete entries older than the given date for a workspace. */
57
+ pruneOlderThan(workspace: WorkspaceId, before: Date): Promise<number>;
58
+ }
46
59
  //# sourceMappingURL=repositories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"repositories.d.ts","sourceRoot":"","sources":["../../../src/domain/context-memory/repositories.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAExE,mDAAmD;AACnD,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACjD,eAAe,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;IACrE,UAAU,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC3C,eAAe,CACb,SAAS,EAAE,WAAW,EACtB,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC5B,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,eAAe,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAClE,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC9D,UAAU,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC5E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;CACzE;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,SAAS,CACP,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,WAAW,GACrB,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B"}
1
+ {"version":3,"file":"repositories.d.ts","sourceRoot":"","sources":["../../../src/domain/context-memory/repositories.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Context Memory Value Objects
3
3
  *
4
- * Identity types for Session, Todo, and Note entities.
4
+ * Identity types for Session, Todo, Note, and ExecutionEntry entities.
5
5
  * All are immutable, compared by value.
6
6
  *
7
7
  * DDD: Value Objects - no identity lifecycle, equality by value
@@ -62,4 +62,21 @@ export declare class NoteId extends EntityId {
62
62
  export declare const MIN_PRIORITY = 1;
63
63
  export declare const MAX_PRIORITY = 5;
64
64
  export declare function isValidPriority(priority: number): boolean;
65
+ /** Execution entry lifecycle states. */
66
+ export declare enum ExecutionState {
67
+ Running = "running",
68
+ Success = "success",
69
+ Error = "error",
70
+ Crashed = "crashed"
71
+ }
72
+ export declare function isTerminalExecutionState(state: ExecutionState): boolean;
73
+ /**
74
+ * Execution entry identifier. Auto-increment integer (assigned by persistence).
75
+ */
76
+ export declare class ExecutionEntryId extends EntityId {
77
+ private constructor();
78
+ static create(id: number): ExecutionEntryId;
79
+ static from(value: string): ExecutionEntryId;
80
+ get numericValue(): number;
81
+ }
65
82
  //# sourceMappingURL=value-objects.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"value-objects.d.ts","sourceRoot":"","sources":["../../../src/domain/context-memory/value-objects.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEjE,gCAAgC;AAChC,oBAAY,YAAY;IACtB,QAAQ,aAAa;IACrB,GAAG,QAAQ;IACX,SAAS,cAAc;IACvB,SAAS,cAAc;CACxB;AAED,+BAA+B;AAC/B,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,UAAU,gBAAgB;IAC1B,SAAS,cAAc;IACvB,SAAS,cAAc;CACxB;AAED,iCAAiC;AACjC,oBAAY,QAAQ;IAClB,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,OAAO,YAAY;CACpB;AAED;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,SAAS;IAQrE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IAIrC,IAAI,SAAS,IAAI,MAAM,CAGtB;IAED,IAAI,SAAS,IAAI,MAAM,CAGtB;CACF;AAED;;GAEG;AACH,qBAAa,MAAO,SAAQ,QAAQ;IAClC,OAAO;IAIP,MAAM,CAAC,MAAM,IAAI,MAAM;IAIvB,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAGnC;AAED;;GAEG;AACH,qBAAa,MAAO,SAAQ,QAAQ;IAClC,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAOjC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIlC,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF;AAED,mDAAmD;AACnD,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMzD"}
1
+ {"version":3,"file":"value-objects.d.ts","sourceRoot":"","sources":["../../../src/domain/context-memory/value-objects.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEjE,gCAAgC;AAChC,oBAAY,YAAY;IACtB,QAAQ,aAAa;IACrB,GAAG,QAAQ;IACX,SAAS,cAAc;IACvB,SAAS,cAAc;CACxB;AAED,+BAA+B;AAC/B,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,UAAU,gBAAgB;IAC1B,SAAS,cAAc;IACvB,SAAS,cAAc;CACxB;AAED,iCAAiC;AACjC,oBAAY,QAAQ;IAClB,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,OAAO,YAAY;CACpB;AAED;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,SAAS;IAQrE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IAIrC,IAAI,SAAS,IAAI,MAAM,CAGtB;IAED,IAAI,SAAS,IAAI,MAAM,CAGtB;CACF;AAED;;GAEG;AACH,qBAAa,MAAO,SAAQ,QAAQ;IAClC,OAAO;IAIP,MAAM,CAAC,MAAM,IAAI,MAAM;IAIvB,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAGnC;AAED;;GAEG;AACH,qBAAa,MAAO,SAAQ,QAAQ;IAClC,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAOjC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIlC,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF;AAED,mDAAmD;AACnD,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMzD;AAID,wCAAwC;AACxC,oBAAY,cAAc;IACxB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AASD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAEvE;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB;IAO3C,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB;IAI5C,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Context Memory Value Objects
3
3
  *
4
- * Identity types for Session, Todo, and Note entities.
4
+ * Identity types for Session, Todo, Note, and ExecutionEntry entities.
5
5
  * All are immutable, compared by value.
6
6
  *
7
7
  * DDD: Value Objects - no identity lifecycle, equality by value
@@ -102,4 +102,42 @@ export function isValidPriority(priority) {
102
102
  priority >= MIN_PRIORITY &&
103
103
  priority <= MAX_PRIORITY);
104
104
  }
105
+ // ── Execution Journal ─────────────────────────────────────────────────
106
+ /** Execution entry lifecycle states. */
107
+ export var ExecutionState;
108
+ (function (ExecutionState) {
109
+ ExecutionState["Running"] = "running";
110
+ ExecutionState["Success"] = "success";
111
+ ExecutionState["Error"] = "error";
112
+ ExecutionState["Crashed"] = "crashed";
113
+ })(ExecutionState || (ExecutionState = {}));
114
+ /** Terminal states — an entry in one of these states cannot transition. */
115
+ const TERMINAL_EXECUTION_STATES = new Set([
116
+ ExecutionState.Success,
117
+ ExecutionState.Error,
118
+ ExecutionState.Crashed,
119
+ ]);
120
+ export function isTerminalExecutionState(state) {
121
+ return TERMINAL_EXECUTION_STATES.has(state);
122
+ }
123
+ /**
124
+ * Execution entry identifier. Auto-increment integer (assigned by persistence).
125
+ */
126
+ export class ExecutionEntryId extends EntityId {
127
+ constructor(value) {
128
+ super(value);
129
+ }
130
+ static create(id) {
131
+ if (id <= 0) {
132
+ throw new Error("ExecutionEntryId: must be a positive integer");
133
+ }
134
+ return new ExecutionEntryId(String(id));
135
+ }
136
+ static from(value) {
137
+ return new ExecutionEntryId(value);
138
+ }
139
+ get numericValue() {
140
+ return Number(this.value);
141
+ }
142
+ }
105
143
  //# sourceMappingURL=value-objects.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"value-objects.js","sourceRoot":"","sources":["../../../src/domain/context-memory/value-objects.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"value-objects.js","sourceRoot":"","sources":["../../../src/domain/context-memory/value-objects.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEjE,gCAAgC;AAChC,MAAM,CAAN,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,qCAAqB,CAAA;IACrB,2BAAW,CAAA;IACX,uCAAuB,CAAA;IACvB,uCAAuB,CAAA;AACzB,CAAC,EALW,YAAY,KAAZ,YAAY,QAKvB;AAED,+BAA+B;AAC/B,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACpB,iCAAmB,CAAA;IACnB,wCAA0B,CAAA;IAC1B,qCAAuB,CAAA;IACvB,qCAAuB,CAAA;AACzB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAED,iCAAiC;AACjC,MAAM,CAAN,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,yBAAa,CAAA;IACb,iCAAqB,CAAA;IACrB,mCAAuB,CAAA;IACvB,+BAAmB,CAAA;AACrB,CAAC,EALW,QAAQ,KAAR,QAAQ,QAKnB;AAED;;;;GAIG;AACH,MAAM,OAAO,SAAU,SAAQ,QAAQ;IACrC,YAAoB,KAAa;QAC/B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,aAAqB,EAAE,SAAoB;QACvD,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9C,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,IAAI,SAAS,CAAC,GAAG,EAAE,KAAK,SAAS,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,SAAS;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;IAChC,CAAC;IAED,IAAI,SAAS;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,MAAO,SAAQ,QAAQ;IAClC,YAAoB,KAAa;QAC/B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,MAAO,SAAQ,QAAQ;IAClC,YAAoB,KAAa;QAC/B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,EAAU;QACtB,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI,YAAY;QACd,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;CACF;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,CACL,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC1B,QAAQ,IAAI,YAAY;QACxB,QAAQ,IAAI,YAAY,CACzB,CAAC;AACJ,CAAC;AAED,yEAAyE;AAEzE,wCAAwC;AACxC,MAAM,CAAN,IAAY,cAKX;AALD,WAAY,cAAc;IACxB,qCAAmB,CAAA;IACnB,qCAAmB,CAAA;IACnB,iCAAe,CAAA;IACf,qCAAmB,CAAA;AACrB,CAAC,EALW,cAAc,KAAd,cAAc,QAKzB;AAED,2EAA2E;AAC3E,MAAM,yBAAyB,GAAgC,IAAI,GAAG,CAAC;IACrE,cAAc,CAAC,OAAO;IACtB,cAAc,CAAC,KAAK;IACpB,cAAc,CAAC,OAAO;CACvB,CAAC,CAAC;AAEH,MAAM,UAAU,wBAAwB,CAAC,KAAqB;IAC5D,OAAO,yBAAyB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,gBAAiB,SAAQ,QAAQ;IAC5C,YAAoB,KAAa;QAC/B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,EAAU;QACtB,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAa;QACvB,OAAO,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,YAAY;QACd,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Config Command Hook
3
+ *
4
+ * Intercepts the `/config` slash command in OpenCode sessions.
5
+ * Injects a system prompt that instructs the agent to use the
6
+ * config-read and config-write tools for agent-guided configuration.
7
+ *
8
+ * Hook: "command.execute.before"
9
+ * Signature: (input: { command, sessionID, arguments }, output: { parts: Part[] }) => Promise<void>
10
+ *
11
+ * When the user types `/config` or `/config <section>`, this hook
12
+ * pushes a TextPart instructing the agent on how to proceed.
13
+ *
14
+ * SOLID: SRP — /config command interception only
15
+ */
16
+ interface CommandHookInput {
17
+ command: string;
18
+ sessionID: string;
19
+ arguments: string;
20
+ }
21
+ interface CommandHookOutput {
22
+ parts: Array<{
23
+ type: string;
24
+ [key: string]: unknown;
25
+ }>;
26
+ }
27
+ export interface ConfigCommandHookDeps {
28
+ /** Readable list of writable config sections for the prompt. */
29
+ readonly writableContexts: readonly string[];
30
+ }
31
+ /**
32
+ * Creates the command hook for /config.
33
+ * Returns undefined for non-/config commands (no-op).
34
+ */
35
+ export declare function createConfigCommandHook(deps: ConfigCommandHookDeps): (input: CommandHookInput, output: CommandHookOutput) => Promise<void>;
36
+ export {};
37
+ //# sourceMappingURL=config-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-command.d.ts","sourceRoot":"","sources":["../../src/hooks/config-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,iBAAiB;IACzB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;CACxD;AAID,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAsCD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAkBvE"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Config Command Hook
3
+ *
4
+ * Intercepts the `/config` slash command in OpenCode sessions.
5
+ * Injects a system prompt that instructs the agent to use the
6
+ * config-read and config-write tools for agent-guided configuration.
7
+ *
8
+ * Hook: "command.execute.before"
9
+ * Signature: (input: { command, sessionID, arguments }, output: { parts: Part[] }) => Promise<void>
10
+ *
11
+ * When the user types `/config` or `/config <section>`, this hook
12
+ * pushes a TextPart instructing the agent on how to proceed.
13
+ *
14
+ * SOLID: SRP — /config command interception only
15
+ */
16
+ // ── Prompt Templates ──────────────────────────────────────────────────
17
+ function buildAllSectionsPrompt(contexts) {
18
+ return `[JARVIS /config COMMAND]
19
+
20
+ The user wants to view or modify JARVIS configuration.
21
+
22
+ INSTRUCTIONS:
23
+ 1. Use the "config-read" tool (no arguments) to read ALL current configuration sections
24
+ 2. Present the configuration to the user in a clear, organized format
25
+ 3. Ask the user which section they want to modify
26
+ 4. When the user tells you what to change, use the "config-write" tool with:
27
+ - section: the section name (e.g., "azure-sync")
28
+ - values: a JSON string with ONLY the keys to change
29
+
30
+ Available sections: ${contexts.join(", ")}
31
+
32
+ IMPORTANT: Only include changed values in the config-write call. The system automatically computes minimal overrides against defaults.`;
33
+ }
34
+ function buildSectionPrompt(section) {
35
+ return `[JARVIS /config COMMAND — section: ${section}]
36
+
37
+ The user wants to view or modify the "${section}" configuration section.
38
+
39
+ INSTRUCTIONS:
40
+ 1. Use the "config-read" tool with section="${section}" to read current values
41
+ 2. Present the configuration to the user
42
+ 3. Ask what they want to change
43
+ 4. Use the "config-write" tool to apply changes
44
+
45
+ IMPORTANT: Only include changed values in the config-write call.`;
46
+ }
47
+ // ── Hook Factory ──────────────────────────────────────────────────────
48
+ /**
49
+ * Creates the command hook for /config.
50
+ * Returns undefined for non-/config commands (no-op).
51
+ */
52
+ export function createConfigCommandHook(deps) {
53
+ return async (input, output) => {
54
+ if (input.command !== "config") {
55
+ return;
56
+ }
57
+ const sectionArg = input.arguments.trim();
58
+ const prompt = sectionArg
59
+ ? buildSectionPrompt(sectionArg)
60
+ : buildAllSectionsPrompt(deps.writableContexts);
61
+ const textPart = {
62
+ type: "text",
63
+ text: prompt,
64
+ };
65
+ output.parts.push(textPart);
66
+ };
67
+ }
68
+ //# sourceMappingURL=config-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-command.js","sourceRoot":"","sources":["../../src/hooks/config-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA4BH,yEAAyE;AAEzE,SAAS,sBAAsB,CAAC,QAA2B;IACzD,OAAO;;;;;;;;;;;;sBAYa,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;;uIAE8F,CAAC;AACxI,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAe;IACzC,OAAO,sCAAsC,OAAO;;wCAEd,OAAO;;;8CAGD,OAAO;;;;;iEAKY,CAAC;AAClE,CAAC;AAED,yEAAyE;AAEzE;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAA2B;IAE3B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAC7B,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,UAAU;YACvB,CAAC,CAAC,kBAAkB,CAAC,UAAU,CAAC;YAChC,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAElD,MAAM,QAAQ,GAAa;YACzB,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,MAAM;SACb,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Execution Journal Hooks
3
+ *
4
+ * Records tool execution lifecycle for crash detection:
5
+ * - tool.execute.before: Creates a Running entry in the journal
6
+ * - event (tool.execute.after): Updates entry to Success or Error
7
+ *
8
+ * Uses an in-memory pending entries map to correlate before/after events.
9
+ * On plugin init, detectCrashes() finds orphaned Running entries from
10
+ * prior sessions and surfaces them to the user.
11
+ *
12
+ * SOLID: SRP — execution journal recording only
13
+ * SOLID: DIP — depends on ExecutionJournalUseCases abstraction
14
+ */
15
+ import type { ExecutionJournalUseCases } from "../application/context-memory/execution-journal-use-cases.js";
16
+ import type { PluginEvent } from "./event-handlers.js";
17
+ import type { PluginLogger } from "./logger.js";
18
+ export interface ExecutionJournalHookDeps {
19
+ readonly journalUseCases: ExecutionJournalUseCases;
20
+ readonly workspace: string;
21
+ readonly log?: PluginLogger;
22
+ }
23
+ export interface ExecutionJournalHooks {
24
+ /** Hook for tool.execute.before — records start. */
25
+ readonly beforeHook: (input: {
26
+ tool: string;
27
+ }, output: {
28
+ args: Record<string, unknown>;
29
+ }) => Promise<void>;
30
+ /** Hook for event — records finish (success/error). */
31
+ readonly afterHook: (input: {
32
+ event: PluginEvent;
33
+ }) => Promise<void>;
34
+ }
35
+ /**
36
+ * Creates execution journal hooks.
37
+ * The beforeHook and afterHook share state via the PendingEntries tracker.
38
+ */
39
+ export declare function createExecutionJournalHooks(deps: ExecutionJournalHookDeps): ExecutionJournalHooks;
40
+ //# sourceMappingURL=execution-journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-journal.d.ts","sourceRoot":"","sources":["../../src/hooks/execution-journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8DAA8D,CAAC;AAI7G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,eAAe,EAAE,wBAAwB,CAAC;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAmDD,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,QAAQ,CAAC,UAAU,EAAE,CACnB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EACvB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KACtC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,uDAAuD;IACvD,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,wBAAwB,GAC7B,qBAAqB,CA0DvB"}
@@ -0,0 +1,102 @@
1
+ import { ExecutionEntryId as ExecutionEntryIdClass } from "../domain/context-memory/value-objects.js";
2
+ import { WorkspaceId } from "../domain/shared/value-objects.js";
3
+ /** Summarize tool args for the journal (truncated key list). */
4
+ function summarizeArgs(args) {
5
+ const keys = Object.keys(args);
6
+ if (keys.length === 0)
7
+ return "";
8
+ const parts = [];
9
+ for (const key of keys) {
10
+ const val = args[key];
11
+ if (val === undefined)
12
+ continue;
13
+ const str = typeof val === "string"
14
+ ? val.length > 80 ? val.slice(0, 80) + "..." : val
15
+ : JSON.stringify(val);
16
+ parts.push(`${key}=${str}`);
17
+ }
18
+ return parts.join(", ");
19
+ }
20
+ // ── Pending Entries Tracker ───────────────────────────────────────────
21
+ /**
22
+ * Tracks pending (running) execution entries for correlation.
23
+ * Uses a stack per tool name since tool invocations are sequential.
24
+ * If multiple calls to the same tool overlap, they stack LIFO.
25
+ */
26
+ class PendingEntries {
27
+ stacks = new Map();
28
+ push(toolName, entryId) {
29
+ let stack = this.stacks.get(toolName);
30
+ if (stack === undefined) {
31
+ stack = [];
32
+ this.stacks.set(toolName, stack);
33
+ }
34
+ stack.push(entryId);
35
+ }
36
+ pop(toolName) {
37
+ const stack = this.stacks.get(toolName);
38
+ if (stack === undefined || stack.length === 0)
39
+ return undefined;
40
+ const id = stack.pop();
41
+ if (stack.length === 0) {
42
+ this.stacks.delete(toolName);
43
+ }
44
+ return id;
45
+ }
46
+ }
47
+ /**
48
+ * Creates execution journal hooks.
49
+ * The beforeHook and afterHook share state via the PendingEntries tracker.
50
+ */
51
+ export function createExecutionJournalHooks(deps) {
52
+ const pending = new PendingEntries();
53
+ const beforeHook = async (input, output) => {
54
+ try {
55
+ const result = await deps.journalUseCases.recordStart({
56
+ toolName: input.tool,
57
+ argsSummary: summarizeArgs(output.args),
58
+ workspace: WorkspaceId.from(deps.workspace),
59
+ });
60
+ pending.push(input.tool, ExecutionEntryIdClass.from(result.entryId));
61
+ }
62
+ catch (err) {
63
+ // Journal recording must NEVER block tool execution
64
+ deps.log?.warn("Execution journal recordStart failed", {
65
+ tool: input.tool,
66
+ error: err instanceof Error ? err.message : String(err),
67
+ });
68
+ }
69
+ };
70
+ const afterHook = async (input) => {
71
+ if (input.event.type !== "tool.execute.after")
72
+ return;
73
+ const toolName = typeof input.event.properties["tool"] === "string"
74
+ ? input.event.properties["tool"]
75
+ : typeof input.event.properties["toolName"] === "string"
76
+ ? input.event.properties["toolName"]
77
+ : undefined;
78
+ if (toolName === undefined)
79
+ return;
80
+ const entryId = pending.pop(toolName);
81
+ if (entryId === undefined)
82
+ return; // No pending entry for this tool
83
+ try {
84
+ const error = input.event.properties["error"];
85
+ if (typeof error === "string" && error.length > 0) {
86
+ await deps.journalUseCases.recordError({ entryId }, error.length > 500 ? error.slice(0, 500) + "..." : error);
87
+ }
88
+ else {
89
+ await deps.journalUseCases.recordSuccess({ entryId });
90
+ }
91
+ }
92
+ catch (err) {
93
+ // Journal recording must NEVER block event processing
94
+ deps.log?.warn("Execution journal recordFinish failed", {
95
+ tool: toolName,
96
+ error: err instanceof Error ? err.message : String(err),
97
+ });
98
+ }
99
+ };
100
+ return { beforeHook, afterHook };
101
+ }
102
+ //# sourceMappingURL=execution-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-journal.js","sourceRoot":"","sources":["../../src/hooks/execution-journal.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,8 @@ export interface FirstRunGuideState {
17
17
  isFirstRun: boolean;
18
18
  /** True when RAG index has 0 documents (needs indexing). */
19
19
  ragEmpty: boolean;
20
+ /** Crash report summary from execution journal, if any orphaned entries detected. */
21
+ crashReport?: string;
20
22
  }
21
23
  /**
22
24
  * Creates the system prompt injection hook for first-run guidance.
@@ -1 +1 @@
1
- {"version":3,"file":"first-run-guide.d.ts","sourceRoot":"","sources":["../../src/hooks/first-run-guide.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,UAAU,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;CACnB;AA4BD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,GACxB,CACD,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,EAC7C,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,KACzB,OAAO,CAAC,IAAI,CAAC,CAejB"}
1
+ {"version":3,"file":"first-run-guide.d.ts","sourceRoot":"","sources":["../../src/hooks/first-run-guide.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,UAAU,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAkCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,GACxB,CACD,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,EAC7C,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,KACzB,OAAO,CAAC,IAAI,CAAC,CAoBjB"}
@@ -34,6 +34,11 @@ The RAG semantic search index has 0 documents. The agent should suggest running:
34
34
  - rag-oracle-index directory="obsidian-vault" (to index documentation)
35
35
 
36
36
  Without RAG indexing, semantic code search will not return results.`;
37
+ const CRASH_REPORT_PREFIX = `[JARVIS CRASH RECOVERY]
38
+
39
+ The previous session ended unexpectedly. The execution journal detected interrupted tool invocations:
40
+
41
+ `;
37
42
  // ── Hook Factory ──────────────────────────────────────────────────────────────
38
43
  /**
39
44
  * Creates the system prompt injection hook for first-run guidance.
@@ -53,6 +58,10 @@ export function createFirstRunGuideHook(state) {
53
58
  if (state.ragEmpty) {
54
59
  output.system.push(RAG_EMPTY_GUIDANCE);
55
60
  }
61
+ // Crash recovery report: inject every session until crashReport is cleared
62
+ if (state.crashReport !== undefined && state.crashReport.length > 0) {
63
+ output.system.push(CRASH_REPORT_PREFIX + state.crashReport);
64
+ }
56
65
  };
57
66
  }
58
67
  //# sourceMappingURL=first-run-guide.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"first-run-guide.js","sourceRoot":"","sources":["../../src/hooks/first-run-guide.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,iFAAiF;AASjF,iFAAiF;AAEjF,MAAM,kBAAkB,GAAG;;;;;;;;;;;;wJAY6H,CAAC;AAEzJ,MAAM,kBAAkB,GAAG;;;;;;oEAMyC,CAAC;AAErE,iFAAiF;AAEjF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAyB;IAKzB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QAC9B,8CAA8C;QAC9C,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACvC,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;QAED,iEAAiE;QACjE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"first-run-guide.js","sourceRoot":"","sources":["../../src/hooks/first-run-guide.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,iFAAiF;AAWjF,iFAAiF;AAEjF,MAAM,kBAAkB,GAAG;;;;;;;;;;;;wJAY6H,CAAC;AAEzJ,MAAM,kBAAkB,GAAG;;;;;;oEAMyC,CAAC;AAErE,MAAM,mBAAmB,GAAG;;;;CAI3B,CAAC;AAEF,iFAAiF;AAEjF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAyB;IAKzB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QAC9B,8CAA8C;QAC9C,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACvC,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;QAED,iEAAiE;QACjE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACzC,CAAC;QAED,2EAA2E;QAC3E,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAgHlD,eAAO,MAAM,YAAY,EAAE,MAse1B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAuHlD,eAAO,MAAM,YAAY,EAAE,MAgiB1B,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ import { SqliteSessionRepository } from "./infrastructure/context-memory/session
6
6
  import { SqliteTodoRepository } from "./infrastructure/context-memory/todo-repository.js";
7
7
  import { SqliteNoteRepository } from "./infrastructure/context-memory/note-repository.js";
8
8
  import { createSimpleSearchRepo } from "./infrastructure/context-memory/search-repository.js";
9
+ import { SqliteExecutionJournalRepository } from "./infrastructure/context-memory/execution-journal-repository.js";
9
10
  import { SqliteCardRepository } from "./infrastructure/kanban/card-repository.js";
10
11
  import { SqliteSprintRepository, SqliteEpicRepository } from "./infrastructure/kanban/sprint-repository.js";
11
12
  import { SessionDomainService, TodoDomainService, NoteDomainService, ContextSearchService } from "./domain/context-memory/services.js";
@@ -16,6 +17,7 @@ import { PolicyValidationService } from "./domain/governance/services.js";
16
17
  import { SessionUseCases } from "./application/context-memory/session-use-cases.js";
17
18
  import { TodoUseCases } from "./application/context-memory/todo-use-cases.js";
18
19
  import { NoteUseCases } from "./application/context-memory/note-use-cases.js";
20
+ import { ExecutionJournalUseCases } from "./application/context-memory/execution-journal-use-cases.js";
19
21
  import { CardUseCases } from "./application/kanban/card-use-cases.js";
20
22
  import { SprintUseCases, EpicUseCases } from "./application/kanban/sprint-use-cases.js";
21
23
  import { BoardUseCases } from "./application/kanban/board-use-cases.js";
@@ -51,7 +53,9 @@ import { SqliteEnvironmentRepository } from "./infrastructure/environment/enviro
51
53
  import { EnvironmentScannerAdapter } from "./infrastructure/environment/scanner-adapter.js";
52
54
  import { EnvironmentDomainService } from "./domain/environment/services.js";
53
55
  import { YamlConfigRepository } from "./infrastructure/config/yaml-config-repository.js";
56
+ import { YamlConfigWriter } from "./infrastructure/config/yaml-config-writer.js";
54
57
  import { ConfigService } from "./application/config/config-service.js";
58
+ import { ConfigWriteService } from "./application/config/config-write-service.js";
55
59
  import { SqlitePipelineRepository, InMemoryPipelineTemplateRegistry, DaggerCliAdapter, DaggerScaffoldGenerator } from "./infrastructure/pipeline/index.js";
56
60
  import { PipelineFactory, GateEnforcer } from "./domain/pipeline/services.js";
57
61
  import { PipelineId } from "./domain/pipeline/value-objects.js";
@@ -84,6 +88,7 @@ import { AzurePollService, SyncEventUseCases } from "./application/azure-sync/po
84
88
  import { createAzureSyncTools } from "./tools/azure-sync-tools.js";
85
89
  import { createAzureSyncEventTools } from "./tools/azure-sync-event-tools.js";
86
90
  import { createBootstrapTools } from "./tools/bootstrap-tools.js";
91
+ import { createConfigTools } from "./tools/config-tools.js";
87
92
  import { BootstrapUseCases, HealthcheckUseCases, TerminalCommandsUseCases } from "./application/bootstrap/index.js";
88
93
  // Hooks
89
94
  import { createCompactingHook } from "./hooks/context-compacting.js";
@@ -91,6 +96,8 @@ import { createShellEnvHook } from "./hooks/shell-env.js";
91
96
  import { createGuardrailsHook } from "./hooks/guardrails.js";
92
97
  import { createEventHook } from "./hooks/event-handlers.js";
93
98
  import { createFirstRunGuideHook } from "./hooks/first-run-guide.js";
99
+ import { createConfigCommandHook } from "./hooks/config-command.js";
100
+ import { createExecutionJournalHooks } from "./hooks/execution-journal.js";
94
101
  import { PluginLogger } from "./hooks/logger.js";
95
102
  /**
96
103
  * Derive workspace name from directory path.
@@ -109,14 +116,17 @@ export const JarvisPlugin = async (input) => {
109
116
  let db;
110
117
  let registryDb;
111
118
  let configService;
119
+ let configWriteService;
112
120
  try {
113
121
  mkdirSync(jarvisDir, { recursive: true });
114
122
  db = new SqliteAdapter({ path: dbPath });
115
123
  const jarvisHome = resolveJarvisHome();
116
124
  mkdirSync(jarvisHome, { recursive: true });
117
125
  registryDb = new SqliteAdapter({ path: join(jarvisHome, "registry.db") });
118
- const configRepo = new YamlConfigRepository(join(input.directory, "config", "jarvis.yaml"));
126
+ const configPath = join(input.directory, "config", "jarvis.yaml");
127
+ const configRepo = new YamlConfigRepository(configPath);
119
128
  configService = new ConfigService(configRepo);
129
+ configWriteService = new ConfigWriteService(configRepo, new YamlConfigWriter(configPath));
120
130
  }
121
131
  catch (err) {
122
132
  log.exception("Failed to initialize infrastructure or config", err, { directory: input.directory });
@@ -126,6 +136,7 @@ export const JarvisPlugin = async (input) => {
126
136
  const sessionRepo = new SqliteSessionRepository(db);
127
137
  const todoRepo = new SqliteTodoRepository(db);
128
138
  const noteRepo = new SqliteNoteRepository(db);
139
+ const executionJournalRepo = new SqliteExecutionJournalRepository(db);
129
140
  const searchRepo = createSimpleSearchRepo(todoRepo, noteRepo);
130
141
  const cardRepo = new SqliteCardRepository(db);
131
142
  const sprintRepo = new SqliteSprintRepository(db);
@@ -176,6 +187,7 @@ export const JarvisPlugin = async (input) => {
176
187
  const sessionUseCases = new SessionUseCases(sessionService);
177
188
  const todoUseCases = new TodoUseCases(todoService, todoRepo);
178
189
  const noteUseCases = new NoteUseCases(noteService, searchService);
190
+ const executionJournalUseCases = new ExecutionJournalUseCases(executionJournalRepo);
179
191
  // Token Metrics (created before kanban to allow cross-context callback)
180
192
  const tmConfig = configService.getTokenMetricsConfig();
181
193
  const sprintStats = { async resolve(sid) {
@@ -408,6 +420,10 @@ export const JarvisPlugin = async (input) => {
408
420
  configService,
409
421
  directory: input.directory,
410
422
  });
423
+ const configTools = createConfigTools({
424
+ configService,
425
+ configWriteService,
426
+ });
411
427
  // ── Auto-Registration ─────────────────────────────────────────────
412
428
  // Register current workspace in the central registry on plugin boot.
413
429
  // Fire-and-forget — does not block plugin startup.
@@ -481,6 +497,43 @@ export const JarvisPlugin = async (input) => {
481
497
  activeCardProvider,
482
498
  });
483
499
  const firstRunGuideHook = createFirstRunGuideHook(firstRunState);
500
+ const configCommandHook = createConfigCommandHook({
501
+ writableContexts: configWriteService.getWritableContexts(),
502
+ });
503
+ // Execution Journal — crash recovery hooks
504
+ const journalHooks = createExecutionJournalHooks({
505
+ journalUseCases: executionJournalUseCases,
506
+ workspace: getWorkspace(input.directory),
507
+ log: log.child("journal"),
508
+ });
509
+ // Composed tool.execute.before: guardrails first, then journal recording
510
+ const composedBeforeHook = async (input_, output_) => {
511
+ await guardrailsHook(input_, output_);
512
+ await journalHooks.beforeHook(input_, output_);
513
+ };
514
+ // Composed event hook: existing event handling + journal after-recording
515
+ const composedEventHook = async (input_) => {
516
+ await eventHook(input_);
517
+ await journalHooks.afterHook(input_);
518
+ };
519
+ // Crash detection — check for orphaned running entries on startup
520
+ const wsIdForJournal = WorkspaceId.create(getWorkspace(input.directory));
521
+ executionJournalUseCases.detectCrashes(wsIdForJournal).then((report) => {
522
+ if (report.totalCrashed > 0) {
523
+ log.warn("Crash recovery", {
524
+ crashed: report.totalCrashed,
525
+ summary: report.summary,
526
+ });
527
+ // Store crash report for first-run guide to surface
528
+ firstRunState.crashReport = report.summary;
529
+ }
530
+ // Prune old journal entries (fire-and-forget)
531
+ return executionJournalUseCases.prune(wsIdForJournal);
532
+ }).catch((err) => {
533
+ log.warn("Crash detection failed", {
534
+ error: err instanceof Error ? err.message : String(err),
535
+ });
536
+ });
484
537
  // ── Compose Hooks Object ──────────────────────────────────────────
485
538
  const allTools = {
486
539
  ...contextMemoryTools,
@@ -503,6 +556,7 @@ export const JarvisPlugin = async (input) => {
503
556
  ...azureSyncTools,
504
557
  ...azureSyncEventTools,
505
558
  ...bootstrapTools,
559
+ ...configTools,
506
560
  };
507
561
  log.info("Plugin initialized", {
508
562
  workspace: wsName,
@@ -513,9 +567,10 @@ export const JarvisPlugin = async (input) => {
513
567
  tool: allTools,
514
568
  "experimental.session.compacting": compactingHook,
515
569
  "experimental.chat.system.transform": firstRunGuideHook,
570
+ "command.execute.before": configCommandHook,
516
571
  "shell.env": shellEnvHook,
517
- "tool.execute.before": guardrailsHook,
518
- event: eventHook,
572
+ "tool.execute.before": composedBeforeHook,
573
+ event: composedEventHook,
519
574
  };
520
575
  };
521
576
  //# sourceMappingURL=index.js.map