@eltonssouza/development-utility-kit 1.0.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 (137) hide show
  1. package/.claude/agents/analyst.md +198 -0
  2. package/.claude/agents/backend-developer.md +126 -0
  3. package/.claude/agents/brain-keeper.md +229 -0
  4. package/.claude/agents/code-reviewer.md +181 -0
  5. package/.claude/agents/database-engineer.md +94 -0
  6. package/.claude/agents/devops-engineer.md +141 -0
  7. package/.claude/agents/frontend-developer.md +97 -0
  8. package/.claude/agents/gate-keeper.md +118 -0
  9. package/.claude/agents/migrator.md +291 -0
  10. package/.claude/agents/mobile-developer.md +80 -0
  11. package/.claude/agents/n8n-specialist.md +94 -0
  12. package/.claude/agents/product-owner.md +115 -0
  13. package/.claude/agents/qa-engineer.md +232 -0
  14. package/.claude/agents/release-engineer.md +204 -0
  15. package/.claude/agents/scaffold.md +87 -0
  16. package/.claude/agents/security-engineer.md +199 -0
  17. package/.claude/agents/sprint-runner.md +44 -0
  18. package/.claude/agents/stack-resolver.md +84 -0
  19. package/.claude/agents/tech-lead.md +182 -0
  20. package/.claude/agents/update-template.md +54 -0
  21. package/.claude/agents/ux-designer.md +118 -0
  22. package/.claude/settings.json +44 -0
  23. package/.claude/skills/README.md +332 -0
  24. package/.claude/skills/active-project/SKILL.md +129 -0
  25. package/.claude/skills/api-integration-test/SKILL.md +64 -0
  26. package/.claude/skills/auto-test-guard/SKILL.md +237 -0
  27. package/.claude/skills/auto-test-guard/resources/backend-tests.md +20 -0
  28. package/.claude/skills/auto-test-guard/resources/e2e-tests.md +24 -0
  29. package/.claude/skills/auto-test-guard/resources/execution-report.md +49 -0
  30. package/.claude/skills/auto-test-guard/resources/frontend-tests.md +18 -0
  31. package/.claude/skills/auto-test-guard/resources/initial-setup.md +108 -0
  32. package/.claude/skills/auto-test-guard/resources/run-suite.md +48 -0
  33. package/.claude/skills/auto-test-guard/resources/senior-gate.md +19 -0
  34. package/.claude/skills/brain-keeper/SKILL.md +60 -0
  35. package/.claude/skills/brain-keeper/obsidian/app.json +9 -0
  36. package/.claude/skills/brain-keeper/obsidian/appearance.json +4 -0
  37. package/.claude/skills/brain-keeper/obsidian/core-plugins.json +20 -0
  38. package/.claude/skills/brain-keeper/obsidian/daily-notes.json +5 -0
  39. package/.claude/skills/brain-keeper/obsidian/graph.json +32 -0
  40. package/.claude/skills/brain-keeper/obsidian/snippets/folder-colors.css +90 -0
  41. package/.claude/skills/brain-keeper/obsidian/templates.json +5 -0
  42. package/.claude/skills/brain-keeper/templates/README.md +51 -0
  43. package/.claude/skills/brain-keeper/templates/adr.md +40 -0
  44. package/.claude/skills/brain-keeper/templates/bug.md +35 -0
  45. package/.claude/skills/brain-keeper/templates/daily.md +38 -0
  46. package/.claude/skills/brain-keeper/templates/feature.md +62 -0
  47. package/.claude/skills/brain-keeper/templates/meeting.md +34 -0
  48. package/.claude/skills/brain-keeper/templates/tech-debt.md +21 -0
  49. package/.claude/skills/caveman/SKILL.md +187 -0
  50. package/.claude/skills/create-stack-pack/SKILL.md +281 -0
  51. package/.claude/skills/grill-me/SKILL.md +79 -0
  52. package/.claude/skills/honcho-memory/SKILL.md +207 -0
  53. package/.claude/skills/honcho-memory/docs/api-endpoints-verified.md +75 -0
  54. package/.claude/skills/honcho-memory/hooks/on-prompt-submit.js +221 -0
  55. package/.claude/skills/honcho-memory/hooks/on-stop.js +193 -0
  56. package/.claude/skills/honcho-memory/lib/honcho-client.js +363 -0
  57. package/.claude/skills/honcho-memory/lib/memory-injector.js +93 -0
  58. package/.claude/skills/honcho-memory/package.json +32 -0
  59. package/.claude/skills/honcho-memory/scripts/cli.js +370 -0
  60. package/.claude/skills/honcho-memory/scripts/setup.js +109 -0
  61. package/.claude/skills/honcho-memory/tests/t001-api-endpoints-verified.test.js +89 -0
  62. package/.claude/skills/honcho-memory/tests/t002-structure.test.js +97 -0
  63. package/.claude/skills/honcho-memory/tests/t003-honcho-client.test.js +162 -0
  64. package/.claude/skills/honcho-memory/tests/t004-soft-delete.test.js +259 -0
  65. package/.claude/skills/honcho-memory/tests/t005-memory-injector.test.js +175 -0
  66. package/.claude/skills/honcho-memory/tests/t006-on-prompt-submit.test.js +215 -0
  67. package/.claude/skills/honcho-memory/tests/t007-on-stop.test.js +165 -0
  68. package/.claude/skills/honcho-memory/tests/t008-cli.test.js +214 -0
  69. package/.claude/skills/honcho-memory/tests/t009-setup.test.js +232 -0
  70. package/.claude/skills/honcho-memory/tests/t010-skill-md.test.js +114 -0
  71. package/.claude/skills/honcho-memory/tests/t011-settings-hooks.test.js +105 -0
  72. package/.claude/skills/honcho-memory/tests/t012-docs-update.test.js +106 -0
  73. package/.claude/skills/honcho-memory/tests/t013-smoke-e2e.test.js +90 -0
  74. package/.claude/skills/pair-debug/SKILL.md +288 -0
  75. package/.claude/skills/prd-ready-check/SKILL.md +58 -0
  76. package/.claude/skills/project-manager/SKILL.md +167 -0
  77. package/.claude/skills/quality-standards/SKILL.md +201 -0
  78. package/.claude/skills/quick-feature/SKILL.md +264 -0
  79. package/.claude/skills/run-sprint/SKILL.md +342 -0
  80. package/.claude/skills/scaffold/SKILL.md +58 -0
  81. package/.claude/skills/stack-discovery/SKILL.md +159 -0
  82. package/.claude/skills/test-coverage-auditor/SKILL.md +59 -0
  83. package/.claude/skills/to-issues/SKILL.md +163 -0
  84. package/.claude/skills/to-prd/SKILL.md +130 -0
  85. package/.claude/skills/update-template/SKILL.md +254 -0
  86. package/.claude/stacks/CODEOWNERS +30 -0
  87. package/.claude/stacks/README.md +88 -0
  88. package/.claude/stacks/_template.md +116 -0
  89. package/.claude/stacks/java/spring-boot-3.md +376 -0
  90. package/.claude/stacks/java/spring-boot-4.md +438 -0
  91. package/.claude/stacks/typescript/angular-18.md +420 -0
  92. package/.claude/stacks/typescript/angular-19.md +397 -0
  93. package/.claude/stacks/typescript/angular-21.md +494 -0
  94. package/CLAUDE.md +453 -0
  95. package/README.md +391 -0
  96. package/bin/cli.js +773 -0
  97. package/bin/lib/backup.js +62 -0
  98. package/bin/lib/detect-stack.js +476 -0
  99. package/bin/lib/help.js +233 -0
  100. package/bin/lib/identity.js +108 -0
  101. package/bin/lib/local-dir.js +69 -0
  102. package/bin/lib/manifest.js +236 -0
  103. package/bin/lib/sync-all.js +394 -0
  104. package/bin/lib/version-check.js +398 -0
  105. package/dashboard/db.js +199 -0
  106. package/dashboard/package.json +22 -0
  107. package/dashboard/public/app.js +709 -0
  108. package/dashboard/public/content/docs/agents-reference.en.md +911 -0
  109. package/dashboard/public/content/docs/architecture-overview.en.md +260 -0
  110. package/dashboard/public/content/docs/autonomy-matrix.en.md +186 -0
  111. package/dashboard/public/content/docs/git-flow.en.md +525 -0
  112. package/dashboard/public/content/docs/honcho-memory.en.md +394 -0
  113. package/dashboard/public/content/docs/hooks-reference.en.md +420 -0
  114. package/dashboard/public/content/docs/pipeline.en.md +400 -0
  115. package/dashboard/public/content/docs/quality-gate.en.md +315 -0
  116. package/dashboard/public/content/docs/skills-reference.en.md +500 -0
  117. package/dashboard/public/content/docs/stack-rules.en.md +362 -0
  118. package/dashboard/public/content/docs/troubleshooting.en.md +637 -0
  119. package/dashboard/public/content/manifest.json +102 -0
  120. package/dashboard/public/content/manual/backend.en.md +1138 -0
  121. package/dashboard/public/content/manual/existing-project.en.md +831 -0
  122. package/dashboard/public/content/manual/frontend.en.md +1065 -0
  123. package/dashboard/public/content/manual/fullstack.en.md +1508 -0
  124. package/dashboard/public/content/manual/mobile.en.md +866 -0
  125. package/dashboard/public/index.html +108 -0
  126. package/dashboard/public/style.css +610 -0
  127. package/dashboard/public/vendor/marked.min.js +69 -0
  128. package/dashboard/rtk.js +143 -0
  129. package/dashboard/server-app.js +403 -0
  130. package/dashboard/server.js +104 -0
  131. package/dashboard/test/sprint1.test.js +406 -0
  132. package/dashboard/test/sprint2.test.js +571 -0
  133. package/dashboard/test/sprint3.test.js +560 -0
  134. package/package.json +33 -0
  135. package/scripts/hooks/subagent-telemetry.sh +14 -0
  136. package/scripts/hooks/telemetry-writer.js +250 -0
  137. package/scripts/latest-versions.json +56 -0
@@ -0,0 +1,207 @@
1
+ ---
2
+ name: honcho-memory
3
+ description: |
4
+ Persistent cross-session memory for Claude Code via Honcho v3 self-hosted.
5
+ Triggers on: "honcho memory", "memória honcho", "honcho skill",
6
+ "lembra que", "remember that", "memoriza", "memorize this",
7
+ "never do", "always do", "never use", "always use",
8
+ "/honcho save", "/honcho search", "/honcho list",
9
+ "/honcho forget", "/honcho status", "/honcho setup",
10
+ "save memory", "search memory", "list memories",
11
+ "forget memory", "honcho status", "honcho setup",
12
+ "memória persistente", "persistent memory", "cross-session memory".
13
+ ---
14
+
15
+ # honcho-memory
16
+
17
+ Persistent cross-session memory for Claude Code backed by **Honcho v3 self-hosted**.
18
+
19
+ Memories survive between sessions. Relevant memories are injected automatically
20
+ into every prompt via the `[HONCHO MEMORY]` block before Claude Code processes them.
21
+
22
+ ---
23
+
24
+ ## Overview
25
+
26
+ The skill integrates Honcho v3 as a semantic memory backend. On every `UserPromptSubmit`
27
+ hook, the skill:
28
+
29
+ 1. Detects explicit memory triggers ("lembra que", "remember that", "memoriza", "never ...", "always ...").
30
+ 2. Saves any explicit memory **before** any search (BR-001).
31
+ 3. Executes hybrid search in `Promise.all`:
32
+ - **Peer-scoped** (`POST /v3/workspaces/{ws}/peers/{peer}/search`) — retrieves `explicit`
33
+ and `inferred` memories, cross-project preferences.
34
+ - **Session-scoped** (`POST /v3/workspaces/{ws}/sessions/{sessionId}/messages/list`) — retrieves
35
+ `project-context` memories for the current directory.
36
+ 4. Merges results by relevance, caps at `topN` items and 2,000 characters.
37
+ 5. Injects the `[HONCHO MEMORY]...[/HONCHO MEMORY]` block into stdout (system prompt extension).
38
+
39
+ On `Stop`, the hook saves the active feature/sprint context as `project-context`.
40
+
41
+ ---
42
+
43
+ ## Subcommands
44
+
45
+ All subcommands are available via the CLI:
46
+
47
+ ```
48
+ bun run .claude/skills/honcho-memory/scripts/cli.js <subcommand> [args]
49
+ ```
50
+
51
+ | Subcommand | Description |
52
+ |---|---|
53
+ | `/honcho save <text>` | Save an explicit memory. Prints the saved message ID. |
54
+ | `/honcho search <query>` | Semantic search — returns top-N relevant memories (excludes soft-deleted). |
55
+ | `/honcho list` | List all memories in the current session (excludes soft-deleted). |
56
+ | `/honcho forget <id>` | Soft-delete a memory via `PUT /v3/workspaces/{ws}/sessions/{sessionId}/messages/{id}` with `{ "metadata": { "deleted": true } }`. Note: uses PUT, NOT DELETE — this is a soft-delete. Calling `forget` without an ID returns exit code 1. |
57
+ | `/honcho status` | Show connection status (OK/FAIL), memory count, config version, `enabled`, `inferenceEnabled` flags. |
58
+ | `/honcho setup` | Interactive wizard: verifies connection, migrates `memory/*.md` to Honcho with backup. |
59
+
60
+ ### forget — soft-delete via PUT
61
+
62
+ `forget <id>` never calls HTTP DELETE. It calls:
63
+
64
+ ```
65
+ PUT /v3/workspaces/{ws}/sessions/{sessionId}/messages/{id}
66
+ Body: { "metadata": { "deleted": true } }
67
+ ```
68
+
69
+ This is a **soft-delete** — the record is preserved in the database but excluded from
70
+ all future list/search results. The CLI stdout contains `"method": "PUT"` to confirm.
71
+
72
+ ---
73
+
74
+ ## Automatic triggers
75
+
76
+ The following patterns in a user prompt trigger **immediate explicit save** before any search:
77
+
78
+ | Pattern | Example |
79
+ |---|---|
80
+ | `lembra que` | "lembra que prefiro records imutáveis em DTOs Java" |
81
+ | `remember that` | "remember that I prefer immutable records" |
82
+ | `memoriza` | "memoriza: usar OnPush em todos os componentes Angular" |
83
+ | `never ...` | "never use var in TypeScript" |
84
+ | `always ...` | "always add JSDoc to public methods" |
85
+
86
+ ---
87
+
88
+ ## [HONCHO MEMORY] block
89
+
90
+ When memories are available, the following block is injected into the system prompt extension:
91
+
92
+ ```
93
+ [HONCHO MEMORY]
94
+ type: explicit | project: my-project | 2026-05-26T10:00:00Z
95
+ Prefer immutable records for DTOs in Java
96
+
97
+ type: project-context | project: development-utility-kit | 2026-05-26T09:00:00Z
98
+ Active feature: honcho-memory-skill Sprint 3
99
+ [/HONCHO MEMORY]
100
+ ```
101
+
102
+ The block is limited to `topN` memories (default: 5) and 2,000 characters total.
103
+ Both opening and closing tags (`[HONCHO MEMORY]` / `[/HONCHO MEMORY]`) are always present.
104
+
105
+ ---
106
+
107
+ ## Graceful degradation
108
+
109
+ When Honcho is unavailable (network timeout, 5xx, DNS failure):
110
+
111
+ - The hook aborts after `timeoutMs` ms (default: 450ms).
112
+ - A `HONCHO_WARN: <reason>` message is written to **stderr**.
113
+ - An **empty string** is written to stdout.
114
+ - Exit code is **0** — Claude Code proceeds normally without memory.
115
+
116
+ This ensures the skill **never blocks** the main workflow. Degradation is graceful.
117
+
118
+ ---
119
+
120
+ ## Configuration
121
+
122
+ Config file: `C:\Users\elton\.honcho\config.json`
123
+
124
+ ```json
125
+ {
126
+ "apiKey": "<bearer-token — never logged, never committed>",
127
+ "peerName": "elton",
128
+ "workspace": "claude_code",
129
+ "endpoint": {
130
+ "baseUrl": "https://honcho.pazzne.cloud"
131
+ },
132
+ "enabled": true,
133
+ "logging": false,
134
+ "inferenceEnabled": false,
135
+ "topN": 5,
136
+ "timeoutMs": 450
137
+ }
138
+ ```
139
+
140
+ **Security**: `apiKey` is never printed to stdout, stderr, or any log. It is never committed to git.
141
+
142
+ ### Session strategy
143
+
144
+ Session ID = `sha256(CWD)[:16]` — one bucket per project directory, never rotated.
145
+ All memories for a given directory accumulate in the same session indefinitely.
146
+
147
+ ---
148
+
149
+ ## Setup
150
+
151
+ Run the interactive wizard:
152
+
153
+ ```bash
154
+ bun run .claude/skills/honcho-memory/scripts/setup.js
155
+ ```
156
+
157
+ Or dry-run (no writes):
158
+
159
+ ```bash
160
+ bun run .claude/skills/honcho-memory/scripts/setup.js --dry-run
161
+ ```
162
+
163
+ The wizard:
164
+ 1. Verifies the Honcho connection.
165
+ 2. Reads existing `memory/*.md` files (legacy memories).
166
+ 3. Shows a preview/diff.
167
+ 4. Asks for confirmation.
168
+ 5. Backs up originals to `memory/backup-YYYYMMDD/`.
169
+ 6. Migrates memories to Honcho.
170
+ 7. Archives the original `.md` files.
171
+
172
+ Setup is **idempotent** — running it multiple times is safe.
173
+
174
+ ---
175
+
176
+ ## Hooks registration
177
+
178
+ Hooks are registered in `C:\Users\elton\.claude\settings.json` (global scope):
179
+
180
+ - **UserPromptSubmit** → `bun run C:/development/tools/development-utility-kit/.claude/skills/honcho-memory/hooks/on-prompt-submit.js`
181
+ - **Stop** → `bun run C:/development/tools/development-utility-kit/.claude/skills/honcho-memory/hooks/on-stop.js`
182
+
183
+ Path uses forward slashes (IR-006 — accepted by the Claude Code hook runner on Windows).
184
+ Implementation lives in the harness at `C:/development/tools/development-utility-kit/.claude/skills/honcho-memory/` (Option B per D-003).
185
+
186
+ ---
187
+
188
+ ## Inference (deferred)
189
+
190
+ `inferenceEnabled: true` in config is a **stub** for `PLAN_honcho-inference.md`.
191
+ When enabled, `on-stop.js` emits `HONCHO_INFO: inference deferred to v2 PLAN, see PLAN_honcho-inference.md` in stderr and proceeds without LLM inference calls.
192
+
193
+ ---
194
+
195
+ ## API endpoints (verified — Honcho v3.0.6)
196
+
197
+ | Operation | Method | Path |
198
+ |---|---|---|
199
+ | Get/create session | POST/GET | `/v3/workspaces/{ws}/sessions` |
200
+ | Save memory (batch) | POST | `/v3/workspaces/{ws}/sessions/{session}/messages` |
201
+ | Soft-delete memory | PUT | `/v3/workspaces/{ws}/sessions/{session}/messages/{id}` |
202
+ | Peer-scoped search | POST | `/v3/workspaces/{ws}/peers/{peer}/search` |
203
+ | List session messages | POST | `/v3/workspaces/{ws}/sessions/{session}/messages/list` |
204
+ | Delete session (nuke) | DELETE | `/v3/workspaces/{ws}/sessions/{session}` |
205
+ | OpenAPI spec | GET | `/openapi.json` (root, not `/v3/openapi.json`) |
206
+
207
+ See `.claude/skills/honcho-memory/docs/api-endpoints-verified.md` for full details.
@@ -0,0 +1,75 @@
1
+ # Honcho v3 API Endpoints — Verified
2
+
3
+ > verifiedAt: 2026-05-26T19:05:19Z
4
+ > Source: GET https://honcho.pazzne.cloud/openapi.json (note: spec served at root, not /v3/openapi.json)
5
+ > API version: 3.0.6 (openapi: 3.1.0)
6
+
7
+ ## Summary of Deviations from DISCOVERY
8
+
9
+ The DISCOVERY document described a `workspaces/{ws}/apps/{app}/users/{user}/...` hierarchy.
10
+ The actual v3 API uses `workspaces/{ws}/sessions/{session}/...` with `peers/{peer}` instead of users/apps.
11
+ There is **no individual message DELETE** endpoint — `deleteMemory` is implemented by deleting the containing session.
12
+
13
+ ## Verified Endpoints (6 operations mapped to client functions)
14
+
15
+ | Client Function | Method | Actual Path | operationId | DISCOVERY Path | Status |
16
+ |---|---|---|---|---|---|
17
+ | `getOrCreateApp` | `POST` | `/v3/workspaces` | `get_or_create_workspace_v3_workspaces_post` | `/v3/workspaces/{ws}/apps` | `differs: no apps concept — workspace IS the app` |
18
+ | `getOrCreateSession` | `POST` | `/v3/workspaces/{workspace_id}/sessions` | `get_or_create_session_v3_workspaces__workspace_id__sessions_post` | `/v3/workspaces/{ws}/apps/{app}/users/{user}/sessions` | `differs: no user/app nesting` |
19
+ | `saveMemory` | `POST` | `/v3/workspaces/{workspace_id}/sessions/{session_id}/messages` | `create_messages_for_session_v3_workspaces__workspace_id__sessions__session_id__messages_post` | `/v3/workspaces/{ws}/apps/{app}/users/{user}/sessions/{session}/messages` | `differs: shorter path, batch body` |
20
+ | `searchMemories` | `POST` | `/v3/workspaces/{workspace_id}/peers/{peer_id}/search` | `search_peer_v3_workspaces__workspace_id__peers__peer_id__search_post` | `/v3/workspaces/{ws}/apps/{app}/users/{user}/search` | `differs: peer-scoped, not user-scoped` |
21
+ | `listMemories` | `POST` | `/v3/workspaces/{workspace_id}/sessions/{session_id}/messages/list` | `get_messages_v3_workspaces__workspace_id__sessions__session_id__messages_list_post` | `/v3/workspaces/{ws}/apps/{app}/users/{user}/sessions/{session}/messages` | `differs: POST + /list suffix` |
22
+ | `deleteMemory` | `DELETE` | `/v3/workspaces/{workspace_id}/sessions/{session_id}` | `delete_session_v3_workspaces__workspace_id__sessions__session_id__delete` | `DELETE /v3/workspaces/{ws}/apps/{app}/users/{user}/sessions/{session}/messages/{id}` | `differs: no individual message delete; deletes whole session` |
23
+
24
+ ## Additional Useful Endpoints
25
+
26
+ | Method | Path | Summary |
27
+ |---|---|---|
28
+ | `GET` | `/health` | Health check (no auth required) |
29
+ | `POST` | `/v3/workspaces/{workspace_id}/search` | Search across entire workspace |
30
+ | `POST` | `/v3/workspaces/{workspace_id}/sessions/{session_id}/search` | Search within session |
31
+ | `DELETE` | `/v3/workspaces/{workspace_id}` | Delete workspace |
32
+ | `PUT` | `/v3/workspaces/{workspace_id}/sessions/{session_id}/messages/{message_id}` | Update message metadata |
33
+
34
+ ## Key Schema Differences
35
+
36
+ ### WorkspaceCreate (POST /v3/workspaces)
37
+ ```json
38
+ { "id": "string (required, pattern: ^[a-zA-Z0-9_-]+$)", "metadata": "object" }
39
+ ```
40
+ Response: workspace object with same `id`.
41
+
42
+ ### SessionCreate (POST /v3/workspaces/{workspace_id}/sessions)
43
+ ```json
44
+ { "id": "string (required)", "metadata": "object|null", "peers": "object|null" }
45
+ ```
46
+ Response: session object.
47
+
48
+ ### MessageBatchCreate (POST .../messages)
49
+ ```json
50
+ {
51
+ "messages": [
52
+ { "content": "string (required)", "peer_id": "string (required)", "metadata": "object|null" }
53
+ ]
54
+ }
55
+ ```
56
+ **Note**: `peer_id` is required per message. Use `peerName` from config as the peer_id.
57
+
58
+ ### MessageSearchOptions (POST .../peers/{peer_id}/search)
59
+ ```json
60
+ { "query": "string (required)", "filters": "object|null", "limit": "integer (1-100, default 10)" }
61
+ ```
62
+
63
+ ### MessageGet (POST .../messages/list)
64
+ ```json
65
+ { "filters": "object|null" }
66
+ ```
67
+ Response: `Page[Message]` with `{ items, total, page, size, pages }`.
68
+
69
+ ## Architecture Notes for honcho-client.js
70
+
71
+ - **Workspace** = equivalent to "app" in DISCOVERY. Use fixed id from config (`hosts.claude_code.workspace`).
72
+ - **Session** = per-directory session. ID derived from SHA-256(CWD)[:16].
73
+ - **Peer** = the user identity. Use `peerName` from config (default: "elton").
74
+ - **getOrCreateApp** in client = `POST /v3/workspaces` (idempotent by id).
75
+ - **deleteMemory** in client = `DELETE /v3/workspaces/{ws}/sessions/{sessionId}` (entire session, not single message). For granular "forget", use `PUT .../messages/{id}` to update metadata with `deleted: true` marker.
@@ -0,0 +1,221 @@
1
+ /**
2
+ * on-prompt-submit.js — UserPromptSubmit hook
3
+ *
4
+ * Triggered by Claude Code before each user prompt is submitted.
5
+ * Reads the user's prompt from stdin, then:
6
+ * 1. Detects explicit memory triggers ("lembra que", "remember that", "memoriza", "never ", "always ")
7
+ * → saves memory immediately with metadata.type = "explicit", metadata.source = "user"
8
+ * 2. Runs hybrid search in Promise.all (peer-scoped + session-scoped) within timeout budget
9
+ * 3. Injects [HONCHO MEMORY] block into stdout as system prompt extension
10
+ *
11
+ * Telemetry: stdout JSON contains peerSearchExecuted + sessionListExecuted fields.
12
+ *
13
+ * Env vars:
14
+ * HONCHO_DRY_RUN=1 — skip real Honcho calls, emit telemetry JSON to stdout
15
+ * HONCHO_BASE_URL — override base URL (env takes precedence over config)
16
+ * HONCHO_TIMEOUT_MS — override timeout in ms
17
+ *
18
+ * Exit codes:
19
+ * 0 — always (NFR-002: never blocks Claude Code)
20
+ *
21
+ * References: FR-003a, FR-003b, FR-003c, BR-001, BR-008, NFR-001, NFR-002
22
+ */
23
+
24
+ import { createHash } from "crypto";
25
+ import { createClient, loadConfig } from "../lib/honcho-client.js";
26
+ import { buildContextBlock } from "../lib/memory-injector.js";
27
+
28
+ const DRY_RUN = process.env.HONCHO_DRY_RUN === "1";
29
+
30
+ const CONFIG_PATH = "C:\\Users\\elton\\.honcho\\config.json";
31
+
32
+ /** Read config, override with env vars where applicable. Returns null if disabled or missing. */
33
+ function getEffectiveConfig() {
34
+ const cfg = loadConfig();
35
+
36
+ // If env vars specify base URL, build a synthetic config
37
+ if (process.env.HONCHO_BASE_URL) {
38
+ // Build minimal config from env — useful for testing with no config file
39
+ const base = {
40
+ apiKey: cfg?.apiKey ?? "dry-run-key",
41
+ peerName: cfg?.peerName ?? "elton",
42
+ workspace: cfg?.workspace ?? "claude_code",
43
+ endpoint: { baseUrl: process.env.HONCHO_BASE_URL },
44
+ enabled: true,
45
+ topN: cfg?.topN ?? 5,
46
+ timeoutMs: process.env.HONCHO_TIMEOUT_MS
47
+ ? parseInt(process.env.HONCHO_TIMEOUT_MS, 10)
48
+ : (cfg?.timeoutMs ?? 450),
49
+ };
50
+ return base;
51
+ }
52
+
53
+ if (!cfg) return null;
54
+ if (cfg.enabled === false) return null;
55
+
56
+ // Apply env override for timeout
57
+ if (process.env.HONCHO_TIMEOUT_MS) {
58
+ cfg.timeoutMs = parseInt(process.env.HONCHO_TIMEOUT_MS, 10);
59
+ }
60
+
61
+ return cfg;
62
+ }
63
+
64
+ /** Derive session ID from CWD: sha256(CWD)[:16] */
65
+ function deriveSessionId(cwd) {
66
+ return createHash("sha256").update(cwd).digest("hex").slice(0, 16);
67
+ }
68
+
69
+ /** Detect explicit memory trigger patterns (BR-001) */
70
+ function detectExplicitTrigger(prompt) {
71
+ const lower = prompt.toLowerCase();
72
+ return (
73
+ lower.includes("lembra que") ||
74
+ lower.includes("remember that") ||
75
+ lower.includes("memoriza") ||
76
+ lower.startsWith("never ") ||
77
+ lower.includes("\nnever ") ||
78
+ lower.startsWith("always ") ||
79
+ lower.includes("\nalways ")
80
+ );
81
+ }
82
+
83
+ /** Write to stderr without logging apiKey */
84
+ function warn(msg) {
85
+ process.stderr.write("HONCHO_WARN: " + msg + "\n");
86
+ }
87
+
88
+ async function main() {
89
+ // Read stdin (prompt text)
90
+ let prompt = "";
91
+ try {
92
+ const chunks = [];
93
+ for await (const chunk of process.stdin) {
94
+ chunks.push(chunk);
95
+ }
96
+ prompt = Buffer.concat(chunks).toString("utf8").trim();
97
+ } catch {
98
+ // stdin read failed — proceed with empty prompt
99
+ }
100
+
101
+ const cfg = getEffectiveConfig();
102
+ const cwd = process.cwd();
103
+ const sessionId = deriveSessionId(cwd);
104
+ const isExplicit = detectExplicitTrigger(prompt);
105
+
106
+ // DRY_RUN mode: simulate execution without real Honcho calls
107
+ if (DRY_RUN) {
108
+ const telemetry = {
109
+ dryRun: true,
110
+ peerSearchExecuted: true,
111
+ sessionListExecuted: true,
112
+ saved: isExplicit ? true : false,
113
+ sessionId,
114
+ prompt: prompt.slice(0, 100),
115
+ };
116
+ if (isExplicit) {
117
+ telemetry.savedType = "explicit";
118
+ telemetry.savedSource = "user";
119
+ }
120
+ process.stdout.write(JSON.stringify(telemetry) + "\n");
121
+ process.exit(0);
122
+ }
123
+
124
+ // No config or disabled — silent no-op
125
+ if (!cfg) {
126
+ process.exit(0);
127
+ }
128
+
129
+ const workspace = cfg.workspace ?? "claude_code";
130
+ const peerId = cfg.peerName ?? "elton";
131
+ const topN = cfg.topN ?? 5;
132
+ const timeoutMs = cfg.timeoutMs ?? 450;
133
+ const project = cwd.split(/[/\\]/).pop() ?? "unknown";
134
+
135
+ const client = createClient({
136
+ baseUrl: cfg.endpoint.baseUrl,
137
+ apiKey: cfg.apiKey,
138
+ timeoutMs,
139
+ });
140
+
141
+ // Step 1: Save explicit memory immediately (BR-001)
142
+ if (isExplicit) {
143
+ try {
144
+ await client.saveMemory(workspace, sessionId, peerId, prompt, {
145
+ type: "explicit",
146
+ source: "user",
147
+ project,
148
+ directory: cwd,
149
+ timestamp: new Date().toISOString(),
150
+ });
151
+ } catch {
152
+ // Never block — ignore save errors
153
+ }
154
+ }
155
+
156
+ // Step 2: Hybrid search within timeout budget (FR-003a + FR-003b, NFR-001)
157
+ let peerResults = null;
158
+ let sessionResults = null;
159
+ let peerSearchExecuted = false;
160
+ let sessionListExecuted = false;
161
+
162
+ try {
163
+ const [peerRes, sessionRes] = await Promise.all([
164
+ client.searchMemories(workspace, peerId, prompt || "general context", topN).then((r) => {
165
+ peerSearchExecuted = true;
166
+ return r;
167
+ }),
168
+ client.listMemories(workspace, sessionId, {}).then((r) => {
169
+ sessionListExecuted = true;
170
+ return r;
171
+ }),
172
+ ]);
173
+ peerResults = peerRes;
174
+ sessionResults = sessionRes;
175
+ } catch {
176
+ // Failure in Promise.all — warn and continue
177
+ warn("search failed, proceeding without memories");
178
+ }
179
+
180
+ // If both failed (null), emit warning
181
+ if (!peerResults && !sessionResults) {
182
+ warn("no memories retrieved — Honcho may be unreachable");
183
+ process.exit(0);
184
+ }
185
+
186
+ // Step 3: Merge results (FR-003c)
187
+ // peer-search returns scored items; session-list returns recency-ordered items
188
+ const peerItems = peerResults?.items ?? [];
189
+ const sessionItems = sessionResults?.items ?? [];
190
+
191
+ // Merge: peer items first (relevance-scored), then session items (recency proxy)
192
+ // Deduplicate by content (simple string match)
193
+ const seen = new Set();
194
+ const merged = [];
195
+ for (const item of [...peerItems, ...sessionItems]) {
196
+ const key = item.content?.trim();
197
+ if (key && !seen.has(key)) {
198
+ seen.add(key);
199
+ merged.push(item);
200
+ }
201
+ }
202
+
203
+ const topMemories = merged.slice(0, topN);
204
+
205
+ if (topMemories.length === 0) {
206
+ process.exit(0);
207
+ }
208
+
209
+ // Step 4: Build and inject context block
210
+ const contextBlock = buildContextBlock(topMemories);
211
+ if (contextBlock) {
212
+ process.stdout.write(contextBlock + "\n");
213
+ }
214
+
215
+ process.exit(0);
216
+ }
217
+
218
+ main().catch((err) => {
219
+ warn("unexpected error: " + (err?.message ?? String(err)));
220
+ process.exit(0);
221
+ });
@@ -0,0 +1,193 @@
1
+ /**
2
+ * on-stop.js — Stop hook
3
+ *
4
+ * Triggered by Claude Code when a session ends.
5
+ * Extracts the active feature/sprint from CLAUDE.md and recent git log,
6
+ * then saves a memory with metadata.type = "project-context".
7
+ *
8
+ * If inferenceEnabled is true (config or HONCHO_INFERENCE_ENABLED=true env):
9
+ * writes "HONCHO_INFO: inference deferred to v2 PLAN, see PLAN_honcho-inference.md" to stderr
10
+ * and proceeds WITHOUT performing inference (NFR-007, BR-006).
11
+ *
12
+ * Env vars:
13
+ * HONCHO_DRY_RUN=1 — skip real Honcho calls, print JSON to stdout
14
+ * HONCHO_BASE_URL — override base URL
15
+ * HONCHO_TIMEOUT_MS — override timeout in ms
16
+ * HONCHO_INFERENCE_ENABLED — "true" to enable inference stub (writes HONCHO_INFO)
17
+ *
18
+ * Exit codes:
19
+ * 0 — always (IR-004: non-blocking, fail-silent)
20
+ *
21
+ * References: FR-004, BR-006, NFR-007, IR-004
22
+ */
23
+
24
+ import { existsSync, readFileSync } from "fs";
25
+ import { join } from "path";
26
+ import { execSync } from "child_process";
27
+ import { createHash } from "crypto";
28
+ import { createClient, loadConfig } from "../lib/honcho-client.js";
29
+
30
+ const DRY_RUN = process.env.HONCHO_DRY_RUN === "1";
31
+ const INFERENCE_ENABLED =
32
+ process.env.HONCHO_INFERENCE_ENABLED === "true";
33
+
34
+ /** Write to stderr */
35
+ function warn(msg) {
36
+ process.stderr.write("HONCHO_WARN: " + msg + "\n");
37
+ }
38
+
39
+ function info(msg) {
40
+ process.stderr.write("HONCHO_INFO: " + msg + "\n");
41
+ }
42
+
43
+ /** Derive session ID from CWD: sha256(CWD)[:16] */
44
+ function deriveSessionId(cwd) {
45
+ return createHash("sha256").update(cwd).digest("hex").slice(0, 16);
46
+ }
47
+
48
+ /**
49
+ * Extract active feature/sprint from CLAUDE.md in the given directory.
50
+ * Returns a short string or null.
51
+ */
52
+ function extractFeatureFromClaudeMd(cwd) {
53
+ const claudeMdPath = join(cwd, "CLAUDE.md");
54
+ if (!existsSync(claudeMdPath)) return null;
55
+ try {
56
+ const content = readFileSync(claudeMdPath, "utf8");
57
+ // Look for sprint / feature / plan mentions
58
+ const sprintMatch = content.match(/(?:sprint|Sprint)\s+([\w-]+)/i);
59
+ const planMatch = content.match(/PLAN_(\w[\w-]*)/i);
60
+ const featureMatch = content.match(/feature\/([\w-]+)/i);
61
+ if (planMatch) return `PLAN_${planMatch[1]}`;
62
+ if (sprintMatch) return `Sprint ${sprintMatch[1]}`;
63
+ if (featureMatch) return `feature/${featureMatch[1]}`;
64
+ return null;
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Extract recent git log summary (last 3 commits, one-line format).
72
+ * Returns a string or null.
73
+ */
74
+ function extractRecentGitLog(cwd) {
75
+ try {
76
+ const log = execSync("git log --oneline -3", {
77
+ cwd,
78
+ timeout: 2000,
79
+ stdio: ["ignore", "pipe", "ignore"],
80
+ encoding: "utf8",
81
+ });
82
+ return log.trim();
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+
88
+ /** Get effective config, applying env overrides. */
89
+ function getEffectiveConfig() {
90
+ const cfg = loadConfig();
91
+
92
+ if (process.env.HONCHO_BASE_URL) {
93
+ return {
94
+ apiKey: cfg?.apiKey ?? "dry-run-key",
95
+ peerName: cfg?.peerName ?? "elton",
96
+ workspace: cfg?.workspace ?? "claude_code",
97
+ endpoint: { baseUrl: process.env.HONCHO_BASE_URL },
98
+ enabled: true,
99
+ timeoutMs: process.env.HONCHO_TIMEOUT_MS
100
+ ? parseInt(process.env.HONCHO_TIMEOUT_MS, 10)
101
+ : (cfg?.timeoutMs ?? 450),
102
+ inferenceEnabled: INFERENCE_ENABLED || (cfg?.inferenceEnabled ?? false),
103
+ };
104
+ }
105
+
106
+ if (!cfg) return null;
107
+
108
+ if (process.env.HONCHO_TIMEOUT_MS) {
109
+ cfg.timeoutMs = parseInt(process.env.HONCHO_TIMEOUT_MS, 10);
110
+ }
111
+
112
+ // env var overrides config flag
113
+ cfg.inferenceEnabled = INFERENCE_ENABLED || (cfg.inferenceEnabled ?? false);
114
+
115
+ return cfg;
116
+ }
117
+
118
+ async function main() {
119
+ const cwd = process.cwd();
120
+ const sessionId = deriveSessionId(cwd);
121
+ const project = cwd.split(/[/\\]/).pop() ?? "unknown";
122
+
123
+ // Extract context from CLAUDE.md and git log
124
+ const featureInfo = extractFeatureFromClaudeMd(cwd);
125
+ const gitLog = extractRecentGitLog(cwd);
126
+
127
+ const contextParts = [];
128
+ if (featureInfo) contextParts.push(`Active: ${featureInfo}`);
129
+ if (gitLog) contextParts.push(`Recent commits:\n${gitLog}`);
130
+ contextParts.push(`Directory: ${cwd}`);
131
+ contextParts.push(`Project: ${project}`);
132
+
133
+ const content = contextParts.join("\n");
134
+
135
+ const memoryPayload = {
136
+ type: "project-context",
137
+ project,
138
+ directory: cwd,
139
+ timestamp: new Date().toISOString(),
140
+ source: "user",
141
+ sessionId,
142
+ featureInfo: featureInfo ?? null,
143
+ };
144
+
145
+ // Check inference flag (BR-006, NFR-007) — always before any Honcho call
146
+ const cfg = getEffectiveConfig();
147
+ const inferenceEnabled = cfg?.inferenceEnabled || INFERENCE_ENABLED;
148
+
149
+ if (inferenceEnabled) {
150
+ info("inference deferred to v2 PLAN, see PLAN_honcho-inference.md");
151
+ // No LLM call — proceed with project-context save only
152
+ }
153
+
154
+ // DRY_RUN mode
155
+ if (DRY_RUN) {
156
+ const output = {
157
+ dryRun: true,
158
+ ...memoryPayload,
159
+ };
160
+ process.stdout.write(JSON.stringify(output) + "\n");
161
+ process.exit(0);
162
+ }
163
+
164
+ // No config or disabled — silent no-op
165
+ if (!cfg || cfg.enabled === false) {
166
+ process.exit(0);
167
+ }
168
+
169
+ const workspace = cfg.workspace ?? "claude_code";
170
+ const peerId = cfg.peerName ?? "elton";
171
+ const timeoutMs = Math.min(cfg.timeoutMs ?? 450, 2000); // cap at 2s for stop hook
172
+
173
+ const client = createClient({
174
+ baseUrl: cfg.endpoint.baseUrl,
175
+ apiKey: cfg.apiKey,
176
+ timeoutMs,
177
+ });
178
+
179
+ // Save project-context memory
180
+ try {
181
+ await client.saveMemory(workspace, sessionId, peerId, content, memoryPayload);
182
+ } catch {
183
+ // Non-blocking — ignore errors
184
+ warn("failed to save project-context memory");
185
+ }
186
+
187
+ process.exit(0);
188
+ }
189
+
190
+ main().catch((err) => {
191
+ warn("unexpected error in on-stop: " + (err?.message ?? String(err)));
192
+ process.exit(0);
193
+ });