@agimon-ai/doompi-hook 0.0.1-alpha.4 → 0.0.1-alpha.41

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 (52) hide show
  1. package/README.md +50 -13
  2. package/dist/adapters/hookDocuments.d.cts +2 -3
  3. package/dist/adapters/hookDocuments.d.cts.map +1 -1
  4. package/dist/adapters/hookDocuments.d.mts +2 -3
  5. package/dist/adapters/hookDocuments.d.mts.map +1 -1
  6. package/dist/adapters/hookRunner.d.cts +2 -3
  7. package/dist/adapters/hookRunner.d.cts.map +1 -1
  8. package/dist/adapters/hookRunner.d.mts +2 -3
  9. package/dist/adapters/hookRunner.d.mts.map +1 -1
  10. package/dist/adapters/pi/extension.cjs +1 -1
  11. package/dist/adapters/pi/extension.cjs.map +1 -1
  12. package/dist/adapters/pi/extension.d.cts +3 -3
  13. package/dist/adapters/pi/extension.d.cts.map +1 -1
  14. package/dist/adapters/pi/extension.d.mts +3 -3
  15. package/dist/adapters/pi/extension.d.mts.map +1 -1
  16. package/dist/adapters/pi/extension.mjs +1 -1
  17. package/dist/adapters/pi/extension.mjs.map +1 -1
  18. package/dist/adapters/telemetry/logSinkTelemetry.d.cts +2 -3
  19. package/dist/adapters/telemetry/logSinkTelemetry.d.cts.map +1 -1
  20. package/dist/adapters/telemetry/logSinkTelemetry.d.mts +2 -3
  21. package/dist/adapters/telemetry/logSinkTelemetry.d.mts.map +1 -1
  22. package/dist/services/hookDecisions.d.cts +7 -8
  23. package/dist/services/hookDecisions.d.cts.map +1 -1
  24. package/dist/services/hookDecisions.d.mts +7 -8
  25. package/dist/services/hookDecisions.d.mts.map +1 -1
  26. package/dist/services/hookPayload.d.cts +2 -3
  27. package/dist/services/hookPayload.d.cts.map +1 -1
  28. package/dist/services/hookPayload.d.mts +2 -3
  29. package/dist/services/hookPayload.d.mts.map +1 -1
  30. package/dist/services/hookRegistry.d.cts +4 -5
  31. package/dist/services/hookRegistry.d.cts.map +1 -1
  32. package/dist/services/hookRegistry.d.mts +4 -5
  33. package/dist/services/hookRegistry.d.mts.map +1 -1
  34. package/dist/services/pluginHooks.d.cts +1 -2
  35. package/dist/services/pluginHooks.d.cts.map +1 -1
  36. package/dist/services/pluginHooks.d.mts +1 -2
  37. package/dist/services/pluginHooks.d.mts.map +1 -1
  38. package/dist/services/toolNames.d.cts +2 -3
  39. package/dist/services/toolNames.d.cts.map +1 -1
  40. package/dist/services/toolNames.d.mts +2 -3
  41. package/dist/services/toolNames.d.mts.map +1 -1
  42. package/dist/types/hooks.d.cts +30 -31
  43. package/dist/types/hooks.d.cts.map +1 -1
  44. package/dist/types/hooks.d.mts +30 -31
  45. package/dist/types/hooks.d.mts.map +1 -1
  46. package/dist/types/telemetry.d.cts +6 -7
  47. package/dist/types/telemetry.d.cts.map +1 -1
  48. package/dist/types/telemetry.d.mts +6 -7
  49. package/dist/types/telemetry.d.mts.map +1 -1
  50. package/llms.txt +6 -2
  51. package/package.json +22 -13
  52. package/src/prompts/doompi-author-hook/SKILL.md +51 -0
@@ -7,7 +7,6 @@ import { PluginHookDocument, ResolvedHook } from "../types/hooks.cjs";
7
7
  * maps to groups, each with an optional matcher and a list of commands. Order
8
8
  * follows the declaration order of the plugins the harness resolved.
9
9
  */
10
- declare function selectPluginHooks(documents: ReadonlyArray<PluginHookDocument>, eventName: string, toolName?: string): ResolvedHook[];
10
+ export declare function selectPluginHooks(documents: ReadonlyArray<PluginHookDocument>, eventName: string, toolName?: string): ResolvedHook[];
11
11
  //#endregion
12
- export { selectPluginHooks };
13
12
  //# sourceMappingURL=pluginHooks.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pluginHooks.d.cts","names":[],"sources":["../../src/services/pluginHooks.ts"],"mappings":";;;;;;;;;iBAUgB,kBACd,WAAW,cAAc,qBACzB,mBACA,oBACC"}
1
+ {"version":3,"file":"pluginHooks.d.cts","names":[],"sources":["../../src/services/pluginHooks.ts"],"mappings":";;;;;;;;;wBAUgB,kBACd,WAAW,cAAc,qBACzB,mBACA,oBACC"}
@@ -7,7 +7,6 @@ import { PluginHookDocument, ResolvedHook } from "../types/hooks.mjs";
7
7
  * maps to groups, each with an optional matcher and a list of commands. Order
8
8
  * follows the declaration order of the plugins the harness resolved.
9
9
  */
10
- declare function selectPluginHooks(documents: ReadonlyArray<PluginHookDocument>, eventName: string, toolName?: string): ResolvedHook[];
10
+ export declare function selectPluginHooks(documents: ReadonlyArray<PluginHookDocument>, eventName: string, toolName?: string): ResolvedHook[];
11
11
  //#endregion
12
- export { selectPluginHooks };
13
12
  //# sourceMappingURL=pluginHooks.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pluginHooks.d.mts","names":[],"sources":["../../src/services/pluginHooks.ts"],"mappings":";;;;;;;;;iBAUgB,kBACd,WAAW,cAAc,qBACzB,mBACA,oBACC"}
1
+ {"version":3,"file":"pluginHooks.d.mts","names":[],"sources":["../../src/services/pluginHooks.ts"],"mappings":";;;;;;;;;wBAUgB,kBACd,WAAW,cAAc,qBACzB,mBACA,oBACC"}
@@ -1,8 +1,7 @@
1
1
  //#region src/services/toolNames.d.ts
2
2
  /** The Claude name a hook matcher expects for a tool Pi just ran. */
3
- declare function toClaudeToolName(tool: string): string;
3
+ export declare function toClaudeToolName(tool: string): string;
4
4
  /** Whether a matcher, if the row declares one, accepts the tool that fired. */
5
- declare function matchesTool(matcher: string | undefined, toolName: string | undefined): boolean;
5
+ export declare function matchesTool(matcher: string | undefined, toolName: string | undefined): boolean;
6
6
  //#endregion
7
- export { matchesTool, toClaudeToolName };
8
7
  //# sourceMappingURL=toolNames.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolNames.d.cts","names":[],"sources":["../../src/services/toolNames.ts"],"mappings":";;iBAmBgB,iBAAiB;;iBAKjB,YAAY,6BAA6B"}
1
+ {"version":3,"file":"toolNames.d.cts","names":[],"sources":["../../src/services/toolNames.ts"],"mappings":";;wBAmBgB,iBAAiB;;wBAKjB,YAAY,6BAA6B"}
@@ -1,8 +1,7 @@
1
1
  //#region src/services/toolNames.d.ts
2
2
  /** The Claude name a hook matcher expects for a tool Pi just ran. */
3
- declare function toClaudeToolName(tool: string): string;
3
+ export declare function toClaudeToolName(tool: string): string;
4
4
  /** Whether a matcher, if the row declares one, accepts the tool that fired. */
5
- declare function matchesTool(matcher: string | undefined, toolName: string | undefined): boolean;
5
+ export declare function matchesTool(matcher: string | undefined, toolName: string | undefined): boolean;
6
6
  //#endregion
7
- export { matchesTool, toClaudeToolName };
8
7
  //# sourceMappingURL=toolNames.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolNames.d.mts","names":[],"sources":["../../src/services/toolNames.ts"],"mappings":";;iBAmBgB,iBAAiB;;iBAKjB,YAAY,6BAA6B"}
1
+ {"version":3,"file":"toolNames.d.mts","names":[],"sources":["../../src/services/toolNames.ts"],"mappings":";;wBAmBgB,iBAAiB;;wBAKjB,YAAY,6BAA6B"}
@@ -7,21 +7,21 @@
7
7
  * translation onto Pi's lifecycle happens at the adapter boundary.
8
8
  */
9
9
  /** Registry event names. Each is used twice per dispatch, so drift would be silent. */
10
- declare const HOOK_EVENT: {
11
- readonly sessionStart: "SessionStart";
12
- readonly preToolUse: "PreToolUse";
13
- readonly postToolUse: "PostToolUse";
14
- readonly stop: "Stop";
15
- readonly sessionEnd: "SessionEnd";
10
+ export declare const HOOK_EVENT: {
11
+ readonly sessionStart: 'SessionStart';
12
+ readonly preToolUse: 'PreToolUse';
13
+ readonly postToolUse: 'PostToolUse';
14
+ readonly stop: 'Stop';
15
+ readonly sessionEnd: 'SessionEnd';
16
16
  };
17
- type HookEventName = (typeof HOOK_EVENT)[keyof typeof HOOK_EVENT];
18
- interface HookCommand {
17
+ export type HookEventName = (typeof HOOK_EVENT)[keyof typeof HOOK_EVENT];
18
+ export interface HookCommand {
19
19
  command: string;
20
20
  /** Seconds before the hook is terminated. Defaults to DEFAULT_HOOK_TIMEOUT_SECONDS. */
21
21
  timeout?: number;
22
22
  }
23
23
  /** What one registry row declares for the `pi` frontend. */
24
- interface RegistryBinding {
24
+ export interface RegistryBinding {
25
25
  matcher?: string;
26
26
  command: string;
27
27
  timeout?: number;
@@ -29,7 +29,7 @@ interface RegistryBinding {
29
29
  order?: number;
30
30
  }
31
31
  /** A registry row plus the group membership used to include or drop it. */
32
- interface RegistryEntry extends RegistryBinding {
32
+ export interface RegistryEntry extends RegistryBinding {
33
33
  event: string;
34
34
  order: number;
35
35
  /** Declaration order across every source, used as the sort tiebreaker. */
@@ -39,45 +39,45 @@ interface RegistryEntry extends RegistryBinding {
39
39
  /** Root of the config that declared the group, exported as CLAUDE_PLUGIN_ROOT. */
40
40
  baseDirectory: string;
41
41
  }
42
- interface RegistryGroup {
42
+ export interface RegistryGroup {
43
43
  core?: boolean;
44
44
  hooks?: Array<{
45
45
  event: string;
46
46
  pi?: RegistryBinding;
47
47
  }>;
48
48
  }
49
- interface RegistryDocument {
49
+ export interface RegistryDocument {
50
50
  groups?: Record<string, RegistryGroup>;
51
51
  }
52
52
  /** One `.doom/hooks.yaml` as read from disk, before it is parsed. */
53
- interface HookDocumentSource {
53
+ export interface HookDocumentSource {
54
54
  baseDirectory: string;
55
55
  text: string;
56
56
  }
57
57
  /** One `.doom/hooks.yaml` after parsing, tagged with the root that declared it. */
58
- interface ParsedRegistrySource {
58
+ export interface ParsedRegistrySource {
59
59
  baseDirectory: string;
60
60
  document: RegistryDocument;
61
61
  }
62
- interface PluginHookGroup {
62
+ export interface PluginHookGroup {
63
63
  matcher?: string;
64
64
  hooks?: HookCommand[];
65
65
  }
66
- interface PluginHookConfig {
66
+ export interface PluginHookConfig {
67
67
  hooks?: Record<string, PluginHookGroup[]>;
68
68
  }
69
69
  /** A parsed plugin config plus the root exported to its commands. */
70
- interface PluginHookDocument {
70
+ export interface PluginHookDocument {
71
71
  pluginRoot: string;
72
72
  config: PluginHookConfig;
73
73
  }
74
74
  /** A hook command paired with the config root it runs against. */
75
- interface ResolvedHook {
75
+ export interface ResolvedHook {
76
76
  hook: HookCommand;
77
77
  root: string;
78
78
  }
79
79
  /** The JSON a hook may write on stdout to steer or block the call it observed. */
80
- interface HookDecision {
80
+ export interface HookDecision {
81
81
  decision?: string;
82
82
  reason?: string;
83
83
  hookSpecificOutput?: {
@@ -86,13 +86,13 @@ interface HookDecision {
86
86
  additionalContext?: string;
87
87
  };
88
88
  }
89
- type HookFailureReason = 'spawn_failed' | 'non_zero_exit' | 'timeout' | 'invalid_json' | 'registry_read' | 'plugin_config';
90
- interface HookFailure {
89
+ export type HookFailureReason = 'spawn_failed' | 'non_zero_exit' | 'timeout' | 'invalid_json' | 'registry_read' | 'plugin_config';
90
+ export interface HookFailure {
91
91
  command: string;
92
92
  message: string;
93
93
  reason: HookFailureReason;
94
94
  }
95
- interface HookOutcome {
95
+ export interface HookOutcome {
96
96
  decision?: HookDecision;
97
97
  failure?: HookFailure;
98
98
  }
@@ -102,7 +102,7 @@ interface HookOutcome {
102
102
  * Pi's ToolCallEvent and ToolResultEvent both satisfy this structurally, so the
103
103
  * adapter forwards them unchanged and the payload builder stays host-neutral.
104
104
  */
105
- interface HookToolEvent {
105
+ export interface HookToolEvent {
106
106
  readonly type: string;
107
107
  readonly toolName: string;
108
108
  readonly input: unknown;
@@ -110,36 +110,35 @@ interface HookToolEvent {
110
110
  readonly isError?: boolean;
111
111
  }
112
112
  /** The JSON document handed to a hook on stdin. */
113
- type HookPayload = Record<string, unknown>;
114
- interface HookRunOptions {
113
+ export type HookPayload = Record<string, unknown>;
114
+ export interface HookRunOptions {
115
115
  repoRoot: string;
116
116
  /** Exported as CLAUDE_PLUGIN_ROOT so a hook can reach its own scripts. */
117
117
  pluginRoot?: string;
118
118
  }
119
119
  /** Runs one hook command and reports what it decided or how it failed. */
120
- interface HookRunner {
120
+ export interface HookRunner {
121
121
  run(hook: HookCommand, payload: HookPayload, options: HookRunOptions): Promise<HookOutcome>;
122
122
  }
123
123
  /** Registry rows for this repository, or the failure that emptied them. */
124
- interface RegistryRead {
124
+ export interface RegistryRead {
125
125
  entries: RegistryEntry[];
126
126
  failure?: HookFailure;
127
127
  }
128
128
  /** Plugin configs that could be read, and one failure per config that could not. */
129
- interface PluginDocumentRead {
129
+ export interface PluginDocumentRead {
130
130
  documents: PluginHookDocument[];
131
131
  failures: HookFailure[];
132
132
  }
133
133
  /** Where a plugin declares its hooks. Mirrors the harness state entry. */
134
- interface PluginHookSourceRef {
134
+ export interface PluginHookSourceRef {
135
135
  readonly pluginRoot: string;
136
136
  readonly configPath: string;
137
137
  }
138
138
  /** Reads the hook documents a session runs from. */
139
- interface HookDocumentReader {
139
+ export interface HookDocumentReader {
140
140
  registry(repoRoot: string): Promise<RegistryRead>;
141
141
  plugins(sources: readonly PluginHookSourceRef[]): Promise<PluginDocumentRead>;
142
142
  }
143
143
  //#endregion
144
- export { HOOK_EVENT, HookCommand, HookDecision, HookDocumentReader, HookDocumentSource, HookEventName, HookFailure, HookFailureReason, HookOutcome, HookPayload, HookRunOptions, HookRunner, HookToolEvent, ParsedRegistrySource, PluginDocumentRead, PluginHookConfig, PluginHookDocument, PluginHookGroup, PluginHookSourceRef, RegistryBinding, RegistryDocument, RegistryEntry, RegistryGroup, RegistryRead, ResolvedHook };
145
144
  //# sourceMappingURL=hooks.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.cts","names":[],"sources":["../../src/types/hooks.ts"],"mappings":";;;;;;;;;cASa;;;;;;;KAQD,wBAAwB,yBAAyB;UAE5C;EACf;;EAEA;;;UAIe;EACf;EACA;EACA;EACA;EACA;;;UAIe,sBAAsB;EACrC;EACA;;EAEA;EACA;EACA;;EAEA;;UAGe;EACf;EACA,QAAQ;IAAQ;IAAe,KAAK;;;UAGrB;EACf,SAAS,eAAe;;;UAIT;EACf;EACA;;;UAIe;EACf;EACA,UAAU;;UAGK;EACf;EACA,QAAQ;;UAGO;EACf,QAAQ,eAAe;;;UAIR;EACf;EACA,QAAQ;;;UAIO;EACf,MAAM;EACN;;;UAIe;EACf;EACA;EACA;IACE;IACA;IACA;;;KAIQ;UAQK;EACf;EACA;EACA,QAAQ;;UAGO;EACf,WAAW;EACX,UAAU;;;;;;;;UASK;WACN;WACA;WACA;WACA;WACA;;;KAIC,cAAc;UAET;EACf;;EAEA;;;UAIe;EACf,IAAI,MAAM,aAAa,SAAS,aAAa,SAAS,iBAAiB,QAAQ;;;UAIhE;EACf,SAAS;EACT,UAAU;;;UAIK;EACf,WAAW;EACX,UAAU;;;UAIK;WACN;WACA;;;UAIM;EACf,SAAS,mBAAmB,QAAQ;EACpC,QAAQ,kBAAkB,wBAAwB,QAAQ"}
1
+ {"version":3,"file":"hooks.d.cts","names":[],"sources":["../../src/types/hooks.ts"],"mappings":";;;;;;;;;qBASa;WACX;WACA;WACA;WACA;WACA;;YAGU,wBAAwB,yBAAyB;iBAE5C;EACf;;EAEA;;;iBAIe;EACf;EACA;EACA;EACA;EACA;;;iBAIe,sBAAsB;EACrC;EACA;;EAEA;EACA;EACA;;EAEA;;iBAGe;EACf;EACA,QAAQ;IAAQ;IAAe,KAAK;;;iBAGrB;EACf,SAAS,eAAe;;;iBAIT;EACf;EACA;;;iBAIe;EACf;EACA,UAAU;;iBAGK;EACf;EACA,QAAQ;;iBAGO;EACf,QAAQ,eAAe;;;iBAIR;EACf;EACA,QAAQ;;;iBAIO;EACf,MAAM;EACN;;;iBAIe;EACf;EACA;EACA;IACE;IACA;IACA;;;YAIQ;iBAQK;EACf;EACA;EACA,QAAQ;;iBAGO;EACf,WAAW;EACX,UAAU;;;;;;;;iBASK;WACN;WACA;WACA;WACA;WACA;;;YAIC,cAAc;iBAET;EACf;;EAEA;;;iBAIe;EACf,IAAI,MAAM,aAAa,SAAS,aAAa,SAAS,iBAAiB,QAAQ;;;iBAIhE;EACf,SAAS;EACT,UAAU;;;iBAIK;EACf,WAAW;EACX,UAAU;;;iBAIK;WACN;WACA;;;iBAIM;EACf,SAAS,mBAAmB,QAAQ;EACpC,QAAQ,kBAAkB,wBAAwB,QAAQ"}
@@ -7,21 +7,21 @@
7
7
  * translation onto Pi's lifecycle happens at the adapter boundary.
8
8
  */
9
9
  /** Registry event names. Each is used twice per dispatch, so drift would be silent. */
10
- declare const HOOK_EVENT: {
11
- readonly sessionStart: "SessionStart";
12
- readonly preToolUse: "PreToolUse";
13
- readonly postToolUse: "PostToolUse";
14
- readonly stop: "Stop";
15
- readonly sessionEnd: "SessionEnd";
10
+ export declare const HOOK_EVENT: {
11
+ readonly sessionStart: 'SessionStart';
12
+ readonly preToolUse: 'PreToolUse';
13
+ readonly postToolUse: 'PostToolUse';
14
+ readonly stop: 'Stop';
15
+ readonly sessionEnd: 'SessionEnd';
16
16
  };
17
- type HookEventName = (typeof HOOK_EVENT)[keyof typeof HOOK_EVENT];
18
- interface HookCommand {
17
+ export type HookEventName = (typeof HOOK_EVENT)[keyof typeof HOOK_EVENT];
18
+ export interface HookCommand {
19
19
  command: string;
20
20
  /** Seconds before the hook is terminated. Defaults to DEFAULT_HOOK_TIMEOUT_SECONDS. */
21
21
  timeout?: number;
22
22
  }
23
23
  /** What one registry row declares for the `pi` frontend. */
24
- interface RegistryBinding {
24
+ export interface RegistryBinding {
25
25
  matcher?: string;
26
26
  command: string;
27
27
  timeout?: number;
@@ -29,7 +29,7 @@ interface RegistryBinding {
29
29
  order?: number;
30
30
  }
31
31
  /** A registry row plus the group membership used to include or drop it. */
32
- interface RegistryEntry extends RegistryBinding {
32
+ export interface RegistryEntry extends RegistryBinding {
33
33
  event: string;
34
34
  order: number;
35
35
  /** Declaration order across every source, used as the sort tiebreaker. */
@@ -39,45 +39,45 @@ interface RegistryEntry extends RegistryBinding {
39
39
  /** Root of the config that declared the group, exported as CLAUDE_PLUGIN_ROOT. */
40
40
  baseDirectory: string;
41
41
  }
42
- interface RegistryGroup {
42
+ export interface RegistryGroup {
43
43
  core?: boolean;
44
44
  hooks?: Array<{
45
45
  event: string;
46
46
  pi?: RegistryBinding;
47
47
  }>;
48
48
  }
49
- interface RegistryDocument {
49
+ export interface RegistryDocument {
50
50
  groups?: Record<string, RegistryGroup>;
51
51
  }
52
52
  /** One `.doom/hooks.yaml` as read from disk, before it is parsed. */
53
- interface HookDocumentSource {
53
+ export interface HookDocumentSource {
54
54
  baseDirectory: string;
55
55
  text: string;
56
56
  }
57
57
  /** One `.doom/hooks.yaml` after parsing, tagged with the root that declared it. */
58
- interface ParsedRegistrySource {
58
+ export interface ParsedRegistrySource {
59
59
  baseDirectory: string;
60
60
  document: RegistryDocument;
61
61
  }
62
- interface PluginHookGroup {
62
+ export interface PluginHookGroup {
63
63
  matcher?: string;
64
64
  hooks?: HookCommand[];
65
65
  }
66
- interface PluginHookConfig {
66
+ export interface PluginHookConfig {
67
67
  hooks?: Record<string, PluginHookGroup[]>;
68
68
  }
69
69
  /** A parsed plugin config plus the root exported to its commands. */
70
- interface PluginHookDocument {
70
+ export interface PluginHookDocument {
71
71
  pluginRoot: string;
72
72
  config: PluginHookConfig;
73
73
  }
74
74
  /** A hook command paired with the config root it runs against. */
75
- interface ResolvedHook {
75
+ export interface ResolvedHook {
76
76
  hook: HookCommand;
77
77
  root: string;
78
78
  }
79
79
  /** The JSON a hook may write on stdout to steer or block the call it observed. */
80
- interface HookDecision {
80
+ export interface HookDecision {
81
81
  decision?: string;
82
82
  reason?: string;
83
83
  hookSpecificOutput?: {
@@ -86,13 +86,13 @@ interface HookDecision {
86
86
  additionalContext?: string;
87
87
  };
88
88
  }
89
- type HookFailureReason = 'spawn_failed' | 'non_zero_exit' | 'timeout' | 'invalid_json' | 'registry_read' | 'plugin_config';
90
- interface HookFailure {
89
+ export type HookFailureReason = 'spawn_failed' | 'non_zero_exit' | 'timeout' | 'invalid_json' | 'registry_read' | 'plugin_config';
90
+ export interface HookFailure {
91
91
  command: string;
92
92
  message: string;
93
93
  reason: HookFailureReason;
94
94
  }
95
- interface HookOutcome {
95
+ export interface HookOutcome {
96
96
  decision?: HookDecision;
97
97
  failure?: HookFailure;
98
98
  }
@@ -102,7 +102,7 @@ interface HookOutcome {
102
102
  * Pi's ToolCallEvent and ToolResultEvent both satisfy this structurally, so the
103
103
  * adapter forwards them unchanged and the payload builder stays host-neutral.
104
104
  */
105
- interface HookToolEvent {
105
+ export interface HookToolEvent {
106
106
  readonly type: string;
107
107
  readonly toolName: string;
108
108
  readonly input: unknown;
@@ -110,36 +110,35 @@ interface HookToolEvent {
110
110
  readonly isError?: boolean;
111
111
  }
112
112
  /** The JSON document handed to a hook on stdin. */
113
- type HookPayload = Record<string, unknown>;
114
- interface HookRunOptions {
113
+ export type HookPayload = Record<string, unknown>;
114
+ export interface HookRunOptions {
115
115
  repoRoot: string;
116
116
  /** Exported as CLAUDE_PLUGIN_ROOT so a hook can reach its own scripts. */
117
117
  pluginRoot?: string;
118
118
  }
119
119
  /** Runs one hook command and reports what it decided or how it failed. */
120
- interface HookRunner {
120
+ export interface HookRunner {
121
121
  run(hook: HookCommand, payload: HookPayload, options: HookRunOptions): Promise<HookOutcome>;
122
122
  }
123
123
  /** Registry rows for this repository, or the failure that emptied them. */
124
- interface RegistryRead {
124
+ export interface RegistryRead {
125
125
  entries: RegistryEntry[];
126
126
  failure?: HookFailure;
127
127
  }
128
128
  /** Plugin configs that could be read, and one failure per config that could not. */
129
- interface PluginDocumentRead {
129
+ export interface PluginDocumentRead {
130
130
  documents: PluginHookDocument[];
131
131
  failures: HookFailure[];
132
132
  }
133
133
  /** Where a plugin declares its hooks. Mirrors the harness state entry. */
134
- interface PluginHookSourceRef {
134
+ export interface PluginHookSourceRef {
135
135
  readonly pluginRoot: string;
136
136
  readonly configPath: string;
137
137
  }
138
138
  /** Reads the hook documents a session runs from. */
139
- interface HookDocumentReader {
139
+ export interface HookDocumentReader {
140
140
  registry(repoRoot: string): Promise<RegistryRead>;
141
141
  plugins(sources: readonly PluginHookSourceRef[]): Promise<PluginDocumentRead>;
142
142
  }
143
143
  //#endregion
144
- export { HOOK_EVENT, HookCommand, HookDecision, HookDocumentReader, HookDocumentSource, HookEventName, HookFailure, HookFailureReason, HookOutcome, HookPayload, HookRunOptions, HookRunner, HookToolEvent, ParsedRegistrySource, PluginDocumentRead, PluginHookConfig, PluginHookDocument, PluginHookGroup, PluginHookSourceRef, RegistryBinding, RegistryDocument, RegistryEntry, RegistryGroup, RegistryRead, ResolvedHook };
145
144
  //# sourceMappingURL=hooks.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.mts","names":[],"sources":["../../src/types/hooks.ts"],"mappings":";;;;;;;;;cASa;;;;;;;KAQD,wBAAwB,yBAAyB;UAE5C;EACf;;EAEA;;;UAIe;EACf;EACA;EACA;EACA;EACA;;;UAIe,sBAAsB;EACrC;EACA;;EAEA;EACA;EACA;;EAEA;;UAGe;EACf;EACA,QAAQ;IAAQ;IAAe,KAAK;;;UAGrB;EACf,SAAS,eAAe;;;UAIT;EACf;EACA;;;UAIe;EACf;EACA,UAAU;;UAGK;EACf;EACA,QAAQ;;UAGO;EACf,QAAQ,eAAe;;;UAIR;EACf;EACA,QAAQ;;;UAIO;EACf,MAAM;EACN;;;UAIe;EACf;EACA;EACA;IACE;IACA;IACA;;;KAIQ;UAQK;EACf;EACA;EACA,QAAQ;;UAGO;EACf,WAAW;EACX,UAAU;;;;;;;;UASK;WACN;WACA;WACA;WACA;WACA;;;KAIC,cAAc;UAET;EACf;;EAEA;;;UAIe;EACf,IAAI,MAAM,aAAa,SAAS,aAAa,SAAS,iBAAiB,QAAQ;;;UAIhE;EACf,SAAS;EACT,UAAU;;;UAIK;EACf,WAAW;EACX,UAAU;;;UAIK;WACN;WACA;;;UAIM;EACf,SAAS,mBAAmB,QAAQ;EACpC,QAAQ,kBAAkB,wBAAwB,QAAQ"}
1
+ {"version":3,"file":"hooks.d.mts","names":[],"sources":["../../src/types/hooks.ts"],"mappings":";;;;;;;;;qBASa;WACX;WACA;WACA;WACA;WACA;;YAGU,wBAAwB,yBAAyB;iBAE5C;EACf;;EAEA;;;iBAIe;EACf;EACA;EACA;EACA;EACA;;;iBAIe,sBAAsB;EACrC;EACA;;EAEA;EACA;EACA;;EAEA;;iBAGe;EACf;EACA,QAAQ;IAAQ;IAAe,KAAK;;;iBAGrB;EACf,SAAS,eAAe;;;iBAIT;EACf;EACA;;;iBAIe;EACf;EACA,UAAU;;iBAGK;EACf;EACA,QAAQ;;iBAGO;EACf,QAAQ,eAAe;;;iBAIR;EACf;EACA,QAAQ;;;iBAIO;EACf,MAAM;EACN;;;iBAIe;EACf;EACA;EACA;IACE;IACA;IACA;;;YAIQ;iBAQK;EACf;EACA;EACA,QAAQ;;iBAGO;EACf,WAAW;EACX,UAAU;;;;;;;;iBASK;WACN;WACA;WACA;WACA;WACA;;;YAIC,cAAc;iBAET;EACf;;EAEA;;;iBAIe;EACf,IAAI,MAAM,aAAa,SAAS,aAAa,SAAS,iBAAiB,QAAQ;;;iBAIhE;EACf,SAAS;EACT,UAAU;;;iBAIK;EACf,WAAW;EACX,UAAU;;;iBAIK;WACN;WACA;;;iBAIM;EACf,SAAS,mBAAmB,QAAQ;EACpC,QAAQ,kBAAkB,wBAAwB,QAAQ"}
@@ -1,20 +1,19 @@
1
1
  //#region src/types/telemetry.d.ts
2
2
  /** Telemetry events this package reports, and the port that records them. */
3
- declare const HOOK_TELEMETRY_EVENT: {
4
- readonly hookFailed: "doom_pi_hook.failed";
5
- readonly hookRegistryReadFailed: "doom_pi_hook.registry_read_failed";
3
+ export declare const HOOK_TELEMETRY_EVENT: {
4
+ readonly hookFailed: 'doom_pi_hook.failed';
5
+ readonly hookRegistryReadFailed: 'doom_pi_hook.registry_read_failed';
6
6
  };
7
- type HookTelemetryEventName = (typeof HOOK_TELEMETRY_EVENT)[keyof typeof HOOK_TELEMETRY_EVENT];
8
- type HookTelemetryAttributes = Record<string, string | number | boolean>;
7
+ export type HookTelemetryEventName = (typeof HOOK_TELEMETRY_EVENT)[keyof typeof HOOK_TELEMETRY_EVENT];
8
+ export type HookTelemetryAttributes = Record<string, string | number | boolean>;
9
9
  /**
10
10
  * A hook that never ran is indistinguishable from one that passed, which is why
11
11
  * both a failed run and an unreadable registry are worth reporting rather than
12
12
  * swallowing.
13
13
  */
14
- interface HookTelemetry {
14
+ export interface HookTelemetry {
15
15
  recordError(event: HookTelemetryEventName, error: unknown, attributes?: HookTelemetryAttributes): Promise<void>;
16
16
  recordWarning(event: HookTelemetryEventName, error: unknown, attributes?: HookTelemetryAttributes): Promise<void>;
17
17
  }
18
18
  //#endregion
19
- export { HOOK_TELEMETRY_EVENT, HookTelemetry, HookTelemetryAttributes, HookTelemetryEventName };
20
19
  //# sourceMappingURL=telemetry.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.cts","names":[],"sources":["../../src/types/telemetry.ts"],"mappings":";;cACa;WAAA;WAAA;;KAKD,iCAAiC,mCAAmC;KACpE,0BAA0B;;;;;;UAOrB;EACf,YAAY,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B;EAClG,cAAc,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B"}
1
+ {"version":3,"file":"telemetry.d.cts","names":[],"sources":["../../src/types/telemetry.ts"],"mappings":";;qBACa;WACX;WACA;;YAGU,iCAAiC,mCAAmC;YACpE,0BAA0B;;;;;;iBAOrB;EACf,YAAY,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B;EAClG,cAAc,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B"}
@@ -1,20 +1,19 @@
1
1
  //#region src/types/telemetry.d.ts
2
2
  /** Telemetry events this package reports, and the port that records them. */
3
- declare const HOOK_TELEMETRY_EVENT: {
4
- readonly hookFailed: "doom_pi_hook.failed";
5
- readonly hookRegistryReadFailed: "doom_pi_hook.registry_read_failed";
3
+ export declare const HOOK_TELEMETRY_EVENT: {
4
+ readonly hookFailed: 'doom_pi_hook.failed';
5
+ readonly hookRegistryReadFailed: 'doom_pi_hook.registry_read_failed';
6
6
  };
7
- type HookTelemetryEventName = (typeof HOOK_TELEMETRY_EVENT)[keyof typeof HOOK_TELEMETRY_EVENT];
8
- type HookTelemetryAttributes = Record<string, string | number | boolean>;
7
+ export type HookTelemetryEventName = (typeof HOOK_TELEMETRY_EVENT)[keyof typeof HOOK_TELEMETRY_EVENT];
8
+ export type HookTelemetryAttributes = Record<string, string | number | boolean>;
9
9
  /**
10
10
  * A hook that never ran is indistinguishable from one that passed, which is why
11
11
  * both a failed run and an unreadable registry are worth reporting rather than
12
12
  * swallowing.
13
13
  */
14
- interface HookTelemetry {
14
+ export interface HookTelemetry {
15
15
  recordError(event: HookTelemetryEventName, error: unknown, attributes?: HookTelemetryAttributes): Promise<void>;
16
16
  recordWarning(event: HookTelemetryEventName, error: unknown, attributes?: HookTelemetryAttributes): Promise<void>;
17
17
  }
18
18
  //#endregion
19
- export { HOOK_TELEMETRY_EVENT, HookTelemetry, HookTelemetryAttributes, HookTelemetryEventName };
20
19
  //# sourceMappingURL=telemetry.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.mts","names":[],"sources":["../../src/types/telemetry.ts"],"mappings":";;cACa;WAAA;WAAA;;KAKD,iCAAiC,mCAAmC;KACpE,0BAA0B;;;;;;UAOrB;EACf,YAAY,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B;EAClG,cAAc,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B"}
1
+ {"version":3,"file":"telemetry.d.mts","names":[],"sources":["../../src/types/telemetry.ts"],"mappings":";;qBACa;WACX;WACA;;YAGU,iCAAiC,mCAAmC;YACpE,0BAA0B;;;;;;iBAOrB;EACf,YAAY,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B;EAClG,cAAc,OAAO,wBAAwB,gBAAgB,aAAa,0BAA0B"}
package/llms.txt CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Claude-Code-compatible repository and plugin hooks for Doom Pi sessions.
4
4
 
5
- ## Resources
5
+ ## How to author
6
6
 
7
- - [Package README](./README.md): the `.doom/hooks.yaml` document, group selection, the event mapping, and what a hook decision can do.
7
+ - [Author DoomPi hooks](./src/prompts/doompi-author-hook/SKILL.md): Create `.doom/hooks.yaml` groups and Claude-compatible hook commands.
8
+
9
+ ## Package reference
10
+
11
+ - [Package README](./README.md): The hook registry, group selection, event mapping, decisions, and failure handling.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-hook",
3
- "version": "0.0.1-alpha.4",
3
+ "version": "0.0.1-alpha.41",
4
4
  "description": "Claude-Code-compatible repository and plugin hook runner for DoomPi sessions.",
5
5
  "keywords": [
6
6
  "ai",
@@ -16,12 +16,21 @@
16
16
  "repository-hooks"
17
17
  ],
18
18
  "homepage": "https://agimon.ai",
19
+ "bugs": {
20
+ "url": "https://github.com/AgiFlow/doompi/issues"
21
+ },
19
22
  "license": "MIT",
20
23
  "author": "Vuong Ngo",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/AgiFlow/doompi.git",
27
+ "directory": "packages/default/doompi-hook"
28
+ },
21
29
  "files": [
22
30
  "dist",
23
31
  "llms.txt",
24
32
  "README.md",
33
+ "src/prompts",
25
34
  "LICENSE",
26
35
  "package.json"
27
36
  ],
@@ -46,23 +55,23 @@
46
55
  "access": "public"
47
56
  },
48
57
  "dependencies": {
49
- "@deepseek-ai/cordis": "4.0.1",
58
+ "@deepseek-ai/cordis": "4.0.2",
50
59
  "yaml": "2.9.0",
51
- "@agimon-ai/doompi-config": "0.0.1-alpha.26",
52
- "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.26",
53
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.26"
60
+ "@agimon-ai/doompi-config": "0.0.1-alpha.63",
61
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.62",
62
+ "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.63"
54
63
  },
55
64
  "devDependencies": {
56
- "@earendil-works/pi-coding-agent": "0.84.2",
57
- "@types/node": "26.1.1",
58
- "@vitest/coverage-v8": "4.1.10",
59
- "tsdown": "0.22.14",
60
- "typescript": "6.0.3",
61
- "vitest": "4.1.10",
62
- "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.26"
65
+ "@earendil-works/pi-coding-agent": "0.85.1",
66
+ "@types/node": "26.4.1",
67
+ "@vitest/coverage-v8": "5.0.0",
68
+ "tsdown": "0.23.0",
69
+ "typescript": "7.0.2",
70
+ "vitest": "5.0.0",
71
+ "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.60"
63
72
  },
64
73
  "peerDependencies": {
65
- "@earendil-works/pi-coding-agent": "0.84.2"
74
+ "@earendil-works/pi-coding-agent": "0.85.1"
66
75
  },
67
76
  "peerDependenciesMeta": {
68
77
  "@earendil-works/pi-coding-agent": {
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: doompi-author-hook
3
+ description: Author DoomPi repository or plugin hooks. Use when creating or changing .doom/hooks.yaml, selecting hook groups from modes.yaml, writing hook commands, or adapting Claude Code hook payloads and decisions to DoomPi.
4
+ ---
5
+
6
+ # Author DoomPi hooks
7
+
8
+ Write the smallest hook that enforces the requested policy, and treat every hook command as executable repository code.
9
+
10
+ ## Repository registry
11
+
12
+ Define repository and personal hooks in `.doom/hooks.yaml`:
13
+
14
+ ```yaml
15
+ groups:
16
+ safety:
17
+ core: true
18
+ hooks:
19
+ - event: PreToolUse
20
+ pi:
21
+ matcher: Bash
22
+ command: .doom/hooks/guard-destructive-commands.sh
23
+ timeout: 10
24
+ skipInSubagent: true
25
+ order: 0
26
+ ```
27
+
28
+ - Personal configuration comes from `~/.pi/.doom/hooks.yaml`; repository configuration comes from `<repo>/.doom/hooks.yaml`.
29
+ - A repository group replaces a personal group with the same ID as one complete value.
30
+ - `core: true` runs regardless of the selected groups. Otherwise, add the group ID to a layer's `hookGroups` in `modes.yaml`.
31
+ - `matcher` is a regular expression over Claude tool names such as `Bash` and `Write`, even though Pi uses lowercase tool names internally.
32
+ - Use `skipInSubagent: true` when running the hook in a child could duplicate or close parent-owned work. Lower `order` values run first, with declaration order as the tiebreaker.
33
+
34
+ Supported repository events are `SessionStart`, `PreToolUse`, `PostToolUse`, and `Stop`. `SessionEnd` is resolved only from plugin `hooks.json` documents.
35
+
36
+ ## Command contract
37
+
38
+ DoomPi runs each command through `/bin/bash -c` from the repository root and writes the Claude-compatible event payload to stdin. The environment includes `CLAUDE_PROJECT_DIR`, `CODEX_REPO_ROOT`, `ORIGINAL_REPO_PATH`, and `CLAUDE_PLUGIN_ROOT`. For `.doom/hooks.yaml`, `CLAUDE_PLUGIN_ROOT` is the root that declared the personal or repository document.
39
+
40
+ The final stdout line beginning with `{` is parsed as the hook decision. Use Claude Code decision fields only when the event supports them. `PreToolUse` may deny a tool or add context, `PostToolUse` may append context or mark a result as denied, and `SessionStart` may add context. `Stop` and `SessionEnd` run for side effects.
41
+
42
+ Hook failures are advisory: nonzero exits, invalid JSON, spawn failures, and timeouts are reported to the agent instead of crashing the turn. Set `timeout` in seconds only when the 10-second default is unsuitable. A timeout terminates the command's process group.
43
+
44
+ ## Verification
45
+
46
+ Before enabling a new hook broadly:
47
+
48
+ 1. Run the command directly with a representative JSON payload on stdin.
49
+ 2. Start DoomPi with the intended major mode and confirm the group appears in `doompi --explain` output.
50
+ 3. Exercise the exact lifecycle event in a disposable session, including a child session when `skipInSubagent` matters.
51
+ 4. Confirm failure output reaches the agent and that repeated shutdown does not repeat external side effects unexpectedly.