@garethdaine/agentops 0.9.3 → 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.
- package/README.md +71 -9
- package/commands/enterprise/idea.md +188 -0
- package/commands/enterprise/search.md +236 -0
- package/commands/enterprise/worklog.md +246 -0
- package/commands/flags.md +3 -0
- package/hooks/ai-guardrails.sh +0 -1
- package/hooks/audit-log.sh +1 -1
- package/hooks/auto-delegate.sh +1 -1
- package/hooks/credential-redact.sh +0 -1
- package/hooks/dashboard-launch.sh +146 -0
- package/hooks/enforcement-lib.sh +4 -2
- package/hooks/feature-flags.sh +4 -0
- package/hooks/flag-utils.sh +6 -0
- package/hooks/hooks.json +8 -1
- package/hooks/integrity-verify.sh +2 -2
- package/hooks/lockfile-audit.sh +1 -1
- package/hooks/patterns-lib.sh +1 -0
- package/hooks/session-cleanup.sh +23 -0
- package/hooks/telemetry.sh +10 -9
- package/hooks/unicode-lib.sh +3 -4
- package/package.json +1 -1
- package/templates/work-journal/conventions.md +423 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# Work Journal Conventions
|
|
2
|
+
|
|
3
|
+
This document defines the shared conventions for all work journal commands (`/worklog`, `/idea`, `/search`). Read this file at command startup before proceeding with command-specific logic.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Config Schema
|
|
8
|
+
|
|
9
|
+
All work journal commands read from `.agentops/journal-config.json`. If this file does not exist, the command must guide the user through interactive creation using `AskUserQuestion`.
|
|
10
|
+
|
|
11
|
+
### Schema
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"identity": {
|
|
16
|
+
"name": "Your Name",
|
|
17
|
+
"role": "Your Role",
|
|
18
|
+
"team": "Your Team"
|
|
19
|
+
},
|
|
20
|
+
"contacts": [
|
|
21
|
+
{
|
|
22
|
+
"id": "unique-id",
|
|
23
|
+
"name": "Contact Name",
|
|
24
|
+
"role": "Contact Role",
|
|
25
|
+
"relationship": "How you work together",
|
|
26
|
+
"share_categories": ["architecture_improvement", "process_improvement"]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"integrations": {
|
|
30
|
+
"cortex": {
|
|
31
|
+
"enabled": false,
|
|
32
|
+
"memory_types": {
|
|
33
|
+
"worklog": "episodic",
|
|
34
|
+
"ideas": "semantic",
|
|
35
|
+
"decisions": "procedural"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"notion": {
|
|
39
|
+
"enabled": false,
|
|
40
|
+
"worklog_database_id": null,
|
|
41
|
+
"ideas_database_id": null,
|
|
42
|
+
"weekly_reviews_database_id": null
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"preferences": {
|
|
46
|
+
"auto_commit": false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### First-Run Setup
|
|
52
|
+
|
|
53
|
+
If `.agentops/journal-config.json` does not exist when any journal command starts:
|
|
54
|
+
|
|
55
|
+
1. Use `AskUserQuestion`: "What is your name?"
|
|
56
|
+
2. Use `AskUserQuestion`: "What is your role?"
|
|
57
|
+
3. Use `AskUserQuestion`: "What team or organisation are you in?"
|
|
58
|
+
4. Use `AskUserQuestion`: "Would you like to add contacts for sharing? (You can add more later)" — options: "Yes, add contacts now" / "Skip for now"
|
|
59
|
+
5. If adding contacts, collect: id, name, role, relationship, share_categories for each
|
|
60
|
+
6. Detect available integrations (see Integration Detection below) and ask about each:
|
|
61
|
+
- If Cortex available: "Cortex memory system detected. Enable sync for cross-session recall?"
|
|
62
|
+
- If Notion available: "Notion workspace detected. Enable sync?"
|
|
63
|
+
7. Write the config file to `.agentops/journal-config.json`
|
|
64
|
+
|
|
65
|
+
The contacts array is extensible — users add as many as they need. The `share_categories` field determines which contacts are suggested when sharing ideas of a given category.
|
|
66
|
+
|
|
67
|
+
### Valid Share Categories
|
|
68
|
+
|
|
69
|
+
`architecture_improvement`, `process_improvement`, `new_tool`, `client_delivery`, `cost_reduction`, `quality_improvement`, `team_workflow`, `business_opportunity`
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Storage Layout
|
|
74
|
+
|
|
75
|
+
All journal data is stored under `.agentops/journal/` within the project directory. This path is private by default (inside `.agentops/` which should be gitignored).
|
|
76
|
+
|
|
77
|
+
> **Hook whitelist note:** The repo's PathPolicy currently protects `.agentops/` with a small whitelist of writable state files. To allow journal writes, add `.agentops/journal/` and `.agentops/journal-config.json` to `AGENTOPS_WRITABLE_STATE` in `hooks/patterns-lib.sh`, or move journal storage to an unprotected path.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
.agentops/journal/
|
|
81
|
+
worklog/
|
|
82
|
+
index.json # Worklog search index
|
|
83
|
+
YYYY/
|
|
84
|
+
MM/
|
|
85
|
+
YYYY-MM-DD.md # Daily worklog entries
|
|
86
|
+
weekly/
|
|
87
|
+
YYYY-Wnn.md # Weekly summaries
|
|
88
|
+
ideas/
|
|
89
|
+
index.json # Ideas search index
|
|
90
|
+
{slug}/
|
|
91
|
+
proposal.md # The idea proposal document
|
|
92
|
+
research.md # Research notes (full development only)
|
|
93
|
+
scratchpad.md # Working notes
|
|
94
|
+
exports/
|
|
95
|
+
{slug}-proposal.pdf # Exported PDF
|
|
96
|
+
{slug}-proposal.docx # Exported DOCX
|
|
97
|
+
exports/
|
|
98
|
+
worklog-YYYY-QN.pdf # Exported worklog reports
|
|
99
|
+
worklog-YYYY-QN.docx
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Directory Creation
|
|
103
|
+
|
|
104
|
+
Commands must create directories as needed using `mkdir -p` before writing files. Never assume directories exist.
|
|
105
|
+
|
|
106
|
+
### File Naming
|
|
107
|
+
|
|
108
|
+
- Worklog daily files: `YYYY-MM-DD.md` (ISO date, UTC)
|
|
109
|
+
- Weekly summaries: `YYYY-Wnn.md` (ISO week number)
|
|
110
|
+
- Idea directories: kebab-case slug generated from title (e.g., `tenant-caching-layer`)
|
|
111
|
+
- Exports: descriptive with date range (e.g., `worklog-2026-Q2.pdf`)
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Index Format
|
|
116
|
+
|
|
117
|
+
Two separate index files: `worklog/index.json` and `ideas/index.json`. These are flat JSON arrays optimised for search.
|
|
118
|
+
|
|
119
|
+
### Worklog Index Schema
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"version": 1,
|
|
124
|
+
"lastUpdated": "2026-03-26T16:00:00Z",
|
|
125
|
+
"entries": [
|
|
126
|
+
{
|
|
127
|
+
"id": "wl-2026-03-26-001",
|
|
128
|
+
"date": "2026-03-26",
|
|
129
|
+
"time": "14:30",
|
|
130
|
+
"category": "Feature delivery",
|
|
131
|
+
"impact": "High",
|
|
132
|
+
"title": "Shipped supplier directory with multi-tenant filtering",
|
|
133
|
+
"tags": ["multi-tenant", "supplier", "feature"],
|
|
134
|
+
"collaborators": "Backend team",
|
|
135
|
+
"file": "2026/03/2026-03-26.md",
|
|
136
|
+
"anchor": "1430-feature-delivery",
|
|
137
|
+
"cortex_id": null,
|
|
138
|
+
"notion_page_id": null
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Ideas Index Schema
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"version": 1,
|
|
149
|
+
"lastUpdated": "2026-03-26T16:00:00Z",
|
|
150
|
+
"entries": [
|
|
151
|
+
{
|
|
152
|
+
"id": "idea-tenant-caching-layer",
|
|
153
|
+
"date": "2026-03-26",
|
|
154
|
+
"title": "Implement tenant-aware caching layer",
|
|
155
|
+
"category": "Architecture improvement",
|
|
156
|
+
"status": "Draft",
|
|
157
|
+
"beneficiaries": ["Engineering team"],
|
|
158
|
+
"tags": ["caching", "multi-tenant", "performance"],
|
|
159
|
+
"file": "tenant-caching-layer/proposal.md",
|
|
160
|
+
"cortex_id": null,
|
|
161
|
+
"notion_page_id": null
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Atomic Write Protocol
|
|
168
|
+
|
|
169
|
+
All index writes MUST use the atomic write pattern to prevent corruption:
|
|
170
|
+
|
|
171
|
+
1. Write the new JSON content to a temporary file: `{index-path}.tmp`
|
|
172
|
+
2. Verify the temporary file is valid JSON (parse it back)
|
|
173
|
+
3. Rename the temporary file to the actual index path (atomic on POSIX filesystems)
|
|
174
|
+
4. If any step fails, leave the original index intact and log a warning
|
|
175
|
+
|
|
176
|
+
In practice within a command file, instruct the agent to:
|
|
177
|
+
- Write to `index.json.tmp` first
|
|
178
|
+
- Read it back to verify valid JSON
|
|
179
|
+
- Move it to `index.json` using `mv`
|
|
180
|
+
|
|
181
|
+
### Rebuild on Parse Failure
|
|
182
|
+
|
|
183
|
+
If loading an index file fails (malformed JSON, empty file, missing file):
|
|
184
|
+
|
|
185
|
+
1. Log a warning: "Index file corrupted or missing. Rebuilding from source files."
|
|
186
|
+
2. Scan the relevant directory for markdown files
|
|
187
|
+
3. For each markdown file:
|
|
188
|
+
- Read frontmatter for file-level metadata (e.g., `date`, `entry_count`)
|
|
189
|
+
- Parse the markdown body to identify individual entry sections and their fields
|
|
190
|
+
(e.g., headings, IDs, titles, tags, timestamps, categories, impact levels)
|
|
191
|
+
4. Reconstruct the index entries from the combination of frontmatter and parsed
|
|
192
|
+
entry metadata
|
|
193
|
+
5. Write the rebuilt index using the atomic write protocol
|
|
194
|
+
6. Continue with the rebuilt index — do NOT fail the operation
|
|
195
|
+
|
|
196
|
+
The markdown files are the source of truth. The index is a derived cache. When
|
|
197
|
+
rebuilding, do not rely solely on frontmatter fields like `date` and
|
|
198
|
+
`entry_count`; always parse the entry sections in the markdown body so the index
|
|
199
|
+
can be accurately reconstructed.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Integration Detection
|
|
204
|
+
|
|
205
|
+
Run integration detection ONCE at command startup. Cache the results for the session. Never re-check per operation.
|
|
206
|
+
|
|
207
|
+
### Protocol
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
1. Read .agentops/journal-config.json for integration preferences
|
|
211
|
+
2. For each integration where config says enabled=true:
|
|
212
|
+
|
|
213
|
+
CORTEX:
|
|
214
|
+
- Attempt to call mcp__cortex__cortex_status
|
|
215
|
+
- If the tool exists and returns successfully: CORTEX_AVAILABLE = true
|
|
216
|
+
- If the tool does not exist or fails: CORTEX_AVAILABLE = false
|
|
217
|
+
- Skip silently if unavailable
|
|
218
|
+
|
|
219
|
+
NOTION:
|
|
220
|
+
- Check if mcp__notion__notion_search tool is available
|
|
221
|
+
- If available: NOTION_AVAILABLE = true
|
|
222
|
+
- If unavailable: NOTION_AVAILABLE = false
|
|
223
|
+
- Skip silently if unavailable
|
|
224
|
+
|
|
225
|
+
LINEAR:
|
|
226
|
+
- Check if any Linear MCP tools are available
|
|
227
|
+
- If available: LINEAR_AVAILABLE = true
|
|
228
|
+
- If unavailable: LINEAR_AVAILABLE = false
|
|
229
|
+
- Skip silently if unavailable
|
|
230
|
+
|
|
231
|
+
3. Report detected integrations to the user ONCE:
|
|
232
|
+
"Integrations: Cortex ✓, Notion ✗, Linear ✗" (or similar brief status)
|
|
233
|
+
If no integrations detected: "Running in local-only mode."
|
|
234
|
+
|
|
235
|
+
4. Proceed with available integrations. Never fail due to missing integration.
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Local-First Write Pattern
|
|
239
|
+
|
|
240
|
+
ALL write operations follow this order:
|
|
241
|
+
|
|
242
|
+
1. Write locally to the filesystem (ALWAYS, unconditionally)
|
|
243
|
+
2. Update the relevant index.json (ALWAYS, using atomic write protocol)
|
|
244
|
+
3. If CORTEX_AVAILABLE and cortex integration enabled in config:
|
|
245
|
+
- Call the appropriate cortex_write tool
|
|
246
|
+
- On failure: log warning, continue (local write already succeeded)
|
|
247
|
+
4. If NOTION_AVAILABLE and notion integration enabled in config:
|
|
248
|
+
- Call the appropriate Notion MCP tool
|
|
249
|
+
- On failure: log warning, continue (local write already succeeded)
|
|
250
|
+
|
|
251
|
+
Integration sync failures NEVER block the local operation.
|
|
252
|
+
|
|
253
|
+
### Cortex Memory Mapping
|
|
254
|
+
|
|
255
|
+
When writing to Cortex, use these type and tag conventions:
|
|
256
|
+
|
|
257
|
+
| Source | Cortex Type | Tags |
|
|
258
|
+
|--------|------------|------|
|
|
259
|
+
| Worklog entry | episodic | ["worklog", "{category}", "{impact}"] |
|
|
260
|
+
| Weekly summary | episodic | ["worklog", "weekly-summary"] |
|
|
261
|
+
| Idea proposal | semantic | ["idea", "{category}", "{status}"] |
|
|
262
|
+
| Decision/lesson | procedural | ["decision", "{topic}"] |
|
|
263
|
+
|
|
264
|
+
### Notion Database Schemas
|
|
265
|
+
|
|
266
|
+
When Notion is available and database IDs are null, offer to create databases:
|
|
267
|
+
|
|
268
|
+
**Work Log Database:** Date (date), Category (select), Impact (select), Description (title), Collaborators (rich text), Tags (multi-select)
|
|
269
|
+
|
|
270
|
+
**Ideas Database:** Title (title), Category (select), Status (select), Date (date), Author (rich text), Beneficiaries (multi-select), Summary (rich text)
|
|
271
|
+
|
|
272
|
+
**Weekly Reviews Database:** Week (title), Date Range (rich text), Key Accomplishments (rich text), Metrics (rich text), Content (rich text)
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Shared Templates
|
|
277
|
+
|
|
278
|
+
### Worklog Entry Frontmatter
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
---
|
|
282
|
+
date: "YYYY-MM-DD"
|
|
283
|
+
entry_count: N
|
|
284
|
+
---
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Worklog Entry Section Format
|
|
288
|
+
|
|
289
|
+
```markdown
|
|
290
|
+
### HH:MM — {Category}
|
|
291
|
+
|
|
292
|
+
**What:** {Description of what was accomplished}
|
|
293
|
+
**Impact:** {High / Medium / Low}
|
|
294
|
+
**Collaborators:** {Who was involved}
|
|
295
|
+
**Context:** Branch: {git branch}, Recent commits: {last 2-3 commits}
|
|
296
|
+
**Notes:** {Additional notes for future reference}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Idea Proposal Frontmatter
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
---
|
|
303
|
+
title: "{Idea Title}"
|
|
304
|
+
author: "{identity.name}"
|
|
305
|
+
date: "YYYY-MM-DD"
|
|
306
|
+
category: "{Category}"
|
|
307
|
+
status: "Draft"
|
|
308
|
+
slug: "{slug}"
|
|
309
|
+
---
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Idea Proposal Document Structure
|
|
313
|
+
|
|
314
|
+
```markdown
|
|
315
|
+
# Idea Proposal: {title}
|
|
316
|
+
|
|
317
|
+
**Author:** {identity.name}
|
|
318
|
+
**Role:** {identity.role}
|
|
319
|
+
**Date:** {YYYY-MM-DD}
|
|
320
|
+
**Category:** {category}
|
|
321
|
+
**Status:** Draft | Proposed | Approved | Implemented | Deferred
|
|
322
|
+
|
|
323
|
+
## Problem Statement
|
|
324
|
+
{What problem does this solve? Why does it matter?}
|
|
325
|
+
|
|
326
|
+
## Proposed Solution
|
|
327
|
+
{What are you proposing? Be specific.}
|
|
328
|
+
|
|
329
|
+
## Expected Benefits
|
|
330
|
+
{What improves if this is implemented?}
|
|
331
|
+
|
|
332
|
+
## Alternatives Considered
|
|
333
|
+
{What other approaches were evaluated?}
|
|
334
|
+
|
|
335
|
+
## Trade-offs & Risks
|
|
336
|
+
{What are the downsides or risks?}
|
|
337
|
+
|
|
338
|
+
## Implementation Sketch
|
|
339
|
+
{High-level approach — phases, effort, dependencies}
|
|
340
|
+
|
|
341
|
+
## Cost-Benefit Assessment
|
|
342
|
+
{Time/effort investment vs expected return}
|
|
343
|
+
|
|
344
|
+
## Success Metrics
|
|
345
|
+
{How do we measure if this worked?}
|
|
346
|
+
|
|
347
|
+
## Recommendation
|
|
348
|
+
{Specific next step — who should review, approve, or act on this?}
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
*Proposed by {identity.name} on {date}. Document ID: {slug}*
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Weekly Summary Structure
|
|
355
|
+
|
|
356
|
+
```markdown
|
|
357
|
+
# Weekly Summary — {YYYY-Wnn}
|
|
358
|
+
|
|
359
|
+
**Period:** {Monday date} to {Friday date}
|
|
360
|
+
**Author:** {identity.name}
|
|
361
|
+
|
|
362
|
+
## Key Accomplishments
|
|
363
|
+
{Bulleted list of highlights}
|
|
364
|
+
|
|
365
|
+
## Metrics
|
|
366
|
+
- Features shipped: {count}
|
|
367
|
+
- Code reviews: {count}
|
|
368
|
+
- Issues resolved: {count}
|
|
369
|
+
- Ideas proposed: {count}
|
|
370
|
+
|
|
371
|
+
## Decisions Made
|
|
372
|
+
{List of key decisions, cross-reference ADRs if they exist}
|
|
373
|
+
|
|
374
|
+
## Git Contribution Stats
|
|
375
|
+
{Output of git log --oneline --since=... --until=...}
|
|
376
|
+
|
|
377
|
+
## Notes for Next Week
|
|
378
|
+
{Anything carrying over or upcoming}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Timestamp Convention
|
|
382
|
+
|
|
383
|
+
- **Storage:** All dates and times stored as ISO 8601 UTC (e.g., `2026-03-26T14:30:00Z`)
|
|
384
|
+
- **Filenames:** Date portion only in UTC (e.g., `2026-03-26.md`)
|
|
385
|
+
- **Display:** Show times in the user's local timezone when presenting to the user
|
|
386
|
+
- **Index entries:** Use UTC dates for consistency and timezone-safe sorting
|
|
387
|
+
|
|
388
|
+
### Export Approach
|
|
389
|
+
|
|
390
|
+
For PDF and DOCX generation, commands should follow this fallback chain:
|
|
391
|
+
|
|
392
|
+
1. **Pandoc (primary):** Check if `pandoc` is available via `which pandoc`. If available, use:
|
|
393
|
+
- PDF: `pandoc input.md -o output.pdf`
|
|
394
|
+
- DOCX: `pandoc input.md -o output.docx`
|
|
395
|
+
- With reference template if available: `--reference-doc=template.docx`
|
|
396
|
+
2. **Playwright (fallback):** If pandoc unavailable, check if Playwright tools are available. Render markdown as styled HTML, then use `page.pdf()` for PDF generation. DOCX not available via Playwright.
|
|
397
|
+
3. **HTML (last resort):** If neither is available, generate a styled HTML file that the user can open in a browser and print to PDF. Inform the user: "Install pandoc for direct PDF/DOCX export: https://pandoc.org/installing.html"
|
|
398
|
+
|
|
399
|
+
### Auto-Tagging
|
|
400
|
+
|
|
401
|
+
When creating entries (worklog or ideas), automatically extract relevant tags from the content:
|
|
402
|
+
- Technology names (e.g., React, PostgreSQL, Redis)
|
|
403
|
+
- Project names (e.g., supplier-directory, auth-system)
|
|
404
|
+
- Domain concepts (e.g., multi-tenant, caching, authentication)
|
|
405
|
+
- Action types (e.g., shipped, fixed, designed, researched)
|
|
406
|
+
|
|
407
|
+
Store tags in lowercase, kebab-case in the index. Use for Cortex writes and Notion syncs when available.
|
|
408
|
+
|
|
409
|
+
### Feature Flag
|
|
410
|
+
|
|
411
|
+
All work journal commands check the `work_journal` flag from `.agentops/flags.json`:
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
Run: source hooks/feature-flags.sh && agentops_enterprise_enabled "work_journal"
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
If the flag is disabled, inform the user: "Work journal commands are disabled. Enable with: /agentops:flags work_journal true" and stop.
|
|
418
|
+
|
|
419
|
+
Default: `true` (commands are enabled by default as they are additive and non-destructive; missing flag entries are treated as enabled-by-default by `agentops_enterprise_enabled`).
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
*Shared conventions for `/agentops:worklog`, `/agentops:idea`, and `/agentops:search`.*
|