@raidiant/notifai 9.2.2 → 9.3.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 (105) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +8 -5
  3. package/dist/claude-wake.js +11 -0
  4. package/dist/claude-wake.js.map +1 -1
  5. package/dist/codex-wake.js +9 -0
  6. package/dist/codex-wake.js.map +1 -1
  7. package/dist/commands-core.d.ts +0 -3
  8. package/dist/commands-core.js.map +1 -1
  9. package/dist/commands-doctor.js +41 -2
  10. package/dist/commands-doctor.js.map +1 -1
  11. package/dist/commands-hook-shape.d.ts +4 -3
  12. package/dist/commands-hook-shape.js +19 -10
  13. package/dist/commands-hook-shape.js.map +1 -1
  14. package/dist/commands-hooks.js +64 -13
  15. package/dist/commands-hooks.js.map +1 -1
  16. package/dist/commands-init.js +12 -1
  17. package/dist/commands-init.js.map +1 -1
  18. package/dist/commands-project.d.ts +4 -0
  19. package/dist/commands-project.js +41 -0
  20. package/dist/commands-project.js.map +1 -0
  21. package/dist/commands-send-support.js +1 -22
  22. package/dist/commands-send-support.js.map +1 -1
  23. package/dist/commands-send.js +10 -4
  24. package/dist/commands-send.js.map +1 -1
  25. package/dist/commands-skill.js +58 -0
  26. package/dist/commands-skill.js.map +1 -1
  27. package/dist/commands.d.ts +1 -0
  28. package/dist/commands.js +1 -0
  29. package/dist/commands.js.map +1 -1
  30. package/dist/config-schema.js +2 -2
  31. package/dist/config-schema.js.map +1 -1
  32. package/dist/config.d.ts +3 -3
  33. package/dist/config.js +4 -7
  34. package/dist/config.js.map +1 -1
  35. package/dist/guidance-content.d.ts +3 -0
  36. package/dist/guidance-content.js +20 -0
  37. package/dist/guidance-content.js.map +1 -1
  38. package/dist/guidance-render.js +3 -3
  39. package/dist/guidance-render.js.map +1 -1
  40. package/dist/harnesses.js +2 -2
  41. package/dist/harnesses.js.map +1 -1
  42. package/dist/hooks.d.ts +26 -50
  43. package/dist/hooks.js +391 -150
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/install-hooks.d.ts +7 -28
  46. package/dist/install-hooks.js +18 -37
  47. package/dist/install-hooks.js.map +1 -1
  48. package/dist/program.d.ts +4 -1
  49. package/dist/program.js +19 -1
  50. package/dist/program.js.map +1 -1
  51. package/dist/project-enablement.d.ts +15 -0
  52. package/dist/project-enablement.js +87 -0
  53. package/dist/project-enablement.js.map +1 -0
  54. package/dist/question-timing.d.ts +46 -0
  55. package/dist/question-timing.js +48 -0
  56. package/dist/question-timing.js.map +1 -0
  57. package/dist/readiness.d.ts +7 -0
  58. package/dist/readiness.js.map +1 -1
  59. package/dist/send.d.ts +2 -0
  60. package/dist/send.js +6 -1
  61. package/dist/send.js.map +1 -1
  62. package/dist/session-activation.d.ts +1 -1
  63. package/dist/session-activation.js +3 -4
  64. package/dist/session-activation.js.map +1 -1
  65. package/package.json +2 -2
  66. package/src/claude-wake.test.ts +1 -0
  67. package/src/claude-wake.ts +10 -0
  68. package/src/codex-wake.test.ts +1 -0
  69. package/src/codex-wake.ts +9 -0
  70. package/src/commands-core.ts +0 -3
  71. package/src/commands-doctor.ts +48 -4
  72. package/src/commands-hook-shape.ts +26 -10
  73. package/src/commands-hooks.ts +59 -13
  74. package/src/commands-init.ts +11 -1
  75. package/src/commands-project.ts +47 -0
  76. package/src/commands-send-support.ts +1 -27
  77. package/src/commands-send.ts +8 -3
  78. package/src/commands-skill.test.ts +44 -0
  79. package/src/commands-skill.ts +57 -0
  80. package/src/commands.test.ts +47 -17
  81. package/src/commands.ts +5 -0
  82. package/src/config-schema.ts +2 -2
  83. package/src/config.test.ts +2 -3
  84. package/src/config.ts +7 -10
  85. package/src/guidance-content.ts +22 -0
  86. package/src/guidance-render.ts +3 -3
  87. package/src/harnesses.ts +2 -2
  88. package/src/hook-adapter.test.ts +27 -8
  89. package/src/hooks.test.ts +808 -80
  90. package/src/hooks.ts +525 -181
  91. package/src/install-hooks.test.ts +8 -12
  92. package/src/install-hooks.ts +21 -37
  93. package/src/program.test.ts +18 -0
  94. package/src/program.ts +22 -0
  95. package/src/project-enablement.test.ts +55 -0
  96. package/src/project-enablement.ts +99 -0
  97. package/src/question-timing.ts +56 -0
  98. package/src/readiness.ts +8 -1
  99. package/src/send.ts +8 -1
  100. package/src/session-activation.ts +3 -4
  101. package/dist/orca-session-title.d.ts +0 -10
  102. package/dist/orca-session-title.js +0 -99
  103. package/dist/orca-session-title.js.map +0 -1
  104. package/src/orca-session-title.test.ts +0 -95
  105. package/src/orca-session-title.ts +0 -105
@@ -1,95 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { readOrcaSessionTitle, type OrcaCommand } from './orca-session-title.js'
3
-
4
- const worktreeId = 'repo-123::/worktrees/semantic-session-implementation'
5
-
6
- function response(overrides: Record<string, unknown> = {}): string {
7
- return JSON.stringify({
8
- ok: true,
9
- result: {
10
- worktree: {
11
- id: worktreeId,
12
- path: '/worktrees/semantic-session-implementation',
13
- displayName: 'Worker - semantic session implementation',
14
- ...overrides,
15
- },
16
- },
17
- })
18
- }
19
-
20
- describe('Orca semantic session title', () => {
21
- it('accepts only the display name returned for the exact managed worktree', () => {
22
- const calls: { executable: string; args: readonly string[] }[] = []
23
- const command: OrcaCommand = (executable, args) => {
24
- calls.push({ executable, args })
25
- return response()
26
- }
27
-
28
- expect(
29
- readOrcaSessionTitle(
30
- { TERM_PROGRAM: 'Orca', ORCA_WORKTREE_ID: worktreeId },
31
- command,
32
- ),
33
- ).toBe('Worker - semantic session implementation')
34
- expect(calls).toEqual([
35
- {
36
- executable: 'orca',
37
- args: ['worktree', 'show', '--worktree', `id:${worktreeId}`, '--json'],
38
- },
39
- ])
40
- })
41
-
42
- it('uses Orca-provided executable selection without invoking a shell', () => {
43
- const calls: string[] = []
44
- expect(
45
- readOrcaSessionTitle(
46
- {
47
- TERM_PROGRAM: 'Orca',
48
- ORCA_WORKTREE_ID: worktreeId,
49
- ORCA_CLI_COMMAND: '/mnt/c/Program Files/Orca/orca.exe',
50
- },
51
- (executable) => {
52
- calls.push(executable)
53
- return response()
54
- },
55
- ),
56
- ).toBe('Worker - semantic session implementation')
57
- expect(calls).toEqual(['/mnt/c/Program Files/Orca/orca.exe'])
58
- })
59
-
60
- it('ignores non-Orca and malformed selectors without running a command', () => {
61
- const command: OrcaCommand = () => {
62
- throw new Error('must not run')
63
- }
64
- expect(readOrcaSessionTitle({ ORCA_WORKTREE_ID: worktreeId }, command)).toBeUndefined()
65
- expect(
66
- readOrcaSessionTitle(
67
- { TERM_PROGRAM: 'Orca', ORCA_WORKTREE_ID: '/private/untrusted' },
68
- command,
69
- ),
70
- ).toBeUndefined()
71
- expect(
72
- readOrcaSessionTitle(
73
- { TERM_PROGRAM: 'Orca', ORCA_WORKTREE_ID: 'repo-123::relative/path' },
74
- command,
75
- ),
76
- ).toBeUndefined()
77
- })
78
-
79
- it.each([
80
- ['command failure', () => null],
81
- ['thrown command failure', () => { throw new Error('offline') }],
82
- ['malformed JSON', () => '{not json}'],
83
- ['failed response', () => JSON.stringify({ ok: false })],
84
- ['different worktree id', () => response({ id: 'repo-123::/worktrees/other' })],
85
- ['different worktree path', () => response({ path: '/private/untrusted' })],
86
- ['blank display name', () => response({ displayName: ' ' })],
87
- ])('fails closed for %s', (_name, command) => {
88
- expect(
89
- readOrcaSessionTitle(
90
- { TERM_PROGRAM: 'Orca', ORCA_WORKTREE_ID: worktreeId },
91
- command,
92
- ),
93
- ).toBeUndefined()
94
- })
95
- })
@@ -1,105 +0,0 @@
1
- import { execFileSync } from 'node:child_process'
2
- import path from 'node:path'
3
-
4
- export type OrcaSessionTitleLookup = (env: NodeJS.ProcessEnv) => string | undefined
5
- export type OrcaCommand = (executable: string, args: readonly string[]) => string | null
6
-
7
- const runOrcaCommand: OrcaCommand = (executable, args) => {
8
- try {
9
- return execFileSync(executable, args, {
10
- encoding: 'utf8',
11
- stdio: ['ignore', 'pipe', 'ignore'],
12
- timeout: 2_000,
13
- maxBuffer: 512 * 1024,
14
- windowsHide: true,
15
- }).trim()
16
- } catch {
17
- return null
18
- }
19
- }
20
-
21
- function containsControlCharacter(value: string): boolean {
22
- return Array.from(value).some((character) => {
23
- const codePoint = character.codePointAt(0) ?? 0
24
- return codePoint < 32 || codePoint === 127
25
- })
26
- }
27
-
28
- function worktreePathFromId(value: string): string | null {
29
- if (value.length === 0 || value.length > 4_096 || containsControlCharacter(value)) {
30
- return null
31
- }
32
- const separator = value.indexOf('::')
33
- if (separator <= 0) return null
34
- const repoId = value.slice(0, separator)
35
- const worktreePath = value.slice(separator + 2)
36
- if (!/^[A-Za-z0-9._-]+$/u.test(repoId) || worktreePath.length === 0) return null
37
- return path.posix.isAbsolute(worktreePath) || path.win32.isAbsolute(worktreePath)
38
- ? worktreePath
39
- : null
40
- }
41
-
42
- function orcaExecutable(env: NodeJS.ProcessEnv): string | null {
43
- const configured = env['ORCA_CLI_COMMAND']?.trim()
44
- if (configured !== undefined && configured.length > 0) {
45
- return containsControlCharacter(configured) ? null : configured
46
- }
47
- return env['ORCA_DEV_REPO_ROOT'] === undefined ? 'orca' : 'orca-dev'
48
- }
49
-
50
- /**
51
- * Read the semantic display name assigned to this exact Orca worktree.
52
- *
53
- * The environment contributes only an opaque selector. Orca must return that
54
- * exact id and its matching path before its display name becomes trusted; no
55
- * path component or identifier is ever promoted into the User-visible label.
56
- */
57
- export function readOrcaSessionTitle(
58
- env: NodeJS.ProcessEnv,
59
- command: OrcaCommand = runOrcaCommand,
60
- ): string | undefined {
61
- if (env['TERM_PROGRAM'] !== 'Orca') return undefined
62
- const worktreeId = env['ORCA_WORKTREE_ID']
63
- if (worktreeId === undefined) return undefined
64
- const expectedPath = worktreePathFromId(worktreeId)
65
- if (expectedPath === null) return undefined
66
- const executable = orcaExecutable(env)
67
- if (executable === null) return undefined
68
-
69
- let output: string | null
70
- try {
71
- output = command(executable, [
72
- 'worktree',
73
- 'show',
74
- '--worktree',
75
- `id:${worktreeId}`,
76
- '--json',
77
- ])
78
- } catch {
79
- return undefined
80
- }
81
- if (output === null || output === '') return undefined
82
-
83
- let parsed: unknown
84
- try {
85
- parsed = JSON.parse(output)
86
- } catch {
87
- return undefined
88
- }
89
- if (typeof parsed !== 'object' || parsed === null) return undefined
90
- const response = parsed as {
91
- ok?: unknown
92
- result?: { worktree?: { id?: unknown; path?: unknown; displayName?: unknown } }
93
- }
94
- const worktree = response.result?.worktree
95
- if (
96
- response.ok !== true ||
97
- worktree?.id !== worktreeId ||
98
- worktree.path !== expectedPath ||
99
- typeof worktree.displayName !== 'string' ||
100
- worktree.displayName.trim().length === 0
101
- ) {
102
- return undefined
103
- }
104
- return worktree.displayName
105
- }