@imunitic/synapse 0.3.2 → 0.4.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/bin/synapse-hook.cjs +4 -1
- package/bin/synapse.cjs +4 -1
- package/commands/synapse-design-note.md +11 -2
- package/commands/synapse-note.md +37 -10
- package/harness/codex/skills/synapse-design-note/SKILL.md +7 -1
- package/harness/codex/skills/synapse-note/SKILL.md +31 -10
- package/package.json +5 -4
- package/schema/vault-design-note/v1.yaml +95 -0
- package/schema/vault-note/v1.yaml +67 -0
- package/schema/vault-task-note/v1.yaml +93 -0
- package/skills/synapse-task/SKILL.md +25 -15
package/bin/synapse-hook.cjs
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"use strict";
|
|
8
8
|
|
|
9
9
|
const { spawnSync } = require("child_process");
|
|
10
|
+
const path = require("path");
|
|
10
11
|
const { hookPath, platformPackageName } = require("../lib/resolve-binaries.cjs");
|
|
11
12
|
|
|
12
13
|
const bin = hookPath();
|
|
@@ -15,5 +16,7 @@ if (!bin) {
|
|
|
15
16
|
process.exit(1);
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const env = { ...process.env };
|
|
20
|
+
if (!env.SYNAPSE_CONTENT_ROOT) env.SYNAPSE_CONTENT_ROOT = path.join(__dirname, "..");
|
|
21
|
+
const result = spawnSync(bin, process.argv.slice(2), { stdio: "inherit", env });
|
|
19
22
|
process.exit(result.status ?? 1);
|
package/bin/synapse.cjs
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"use strict";
|
|
9
9
|
|
|
10
10
|
const { spawnSync } = require("child_process");
|
|
11
|
+
const path = require("path");
|
|
11
12
|
const { cliPath, platformPackageName } = require("../lib/resolve-binaries.cjs");
|
|
12
13
|
|
|
13
14
|
const bin = cliPath();
|
|
@@ -16,5 +17,7 @@ if (!bin) {
|
|
|
16
17
|
process.exit(1);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
+
const env = { ...process.env };
|
|
21
|
+
if (!env.SYNAPSE_CONTENT_ROOT) env.SYNAPSE_CONTENT_ROOT = path.join(__dirname, "..");
|
|
22
|
+
const result = spawnSync(bin, process.argv.slice(2), { stdio: "inherit", env });
|
|
20
23
|
process.exit(result.status ?? 1);
|
|
@@ -177,10 +177,13 @@ so the `## Status` line is the only lifecycle marker that matters. It simply sta
|
|
|
177
177
|
|
|
178
178
|
```
|
|
179
179
|
---
|
|
180
|
+
schema: vault-design-note/v1
|
|
180
181
|
title: "{PROJECT} — {Topic}"
|
|
181
182
|
project: {prefix}
|
|
182
|
-
created: "{now}"
|
|
183
183
|
note_id: {id}
|
|
184
|
+
created: "{now}"
|
|
185
|
+
updated: "{now}"
|
|
186
|
+
tags: [{comma-separated configured tags, or empty}]
|
|
184
187
|
---
|
|
185
188
|
|
|
186
189
|
# {PROJECT} — {Topic}
|
|
@@ -204,7 +207,13 @@ Discussing | Ready | Reference
|
|
|
204
207
|
- {Anything deferred or unresolved}
|
|
205
208
|
```
|
|
206
209
|
|
|
207
|
-
|
|
210
|
+
Any string scalar that is all digits (e.g. a numeric-looking title) must be quoted: an
|
|
211
|
+
unquoted all-digit value is parsed as an integer, which fails a `type: string` schema
|
|
212
|
+
field. `title`, `project`, `note_id`, and both timestamps are quoted above.
|
|
213
|
+
|
|
214
|
+
Resolve tags through the `synapse-vault` skill's configured vocabulary procedure. Fetch machine
|
|
215
|
+
local time once (`date '+%Y-%m-%d %H:%M:%S %Z'`) — never infer it — and use the exact same value
|
|
216
|
+
for `created` and `updated`.
|
|
208
217
|
|
|
209
218
|
No `Notes`/changelog section — it stays a small, single-conclusion note; there's no long-running
|
|
210
219
|
edit history here worth tracking separately.
|
package/commands/synapse-note.md
CHANGED
|
@@ -171,36 +171,64 @@ or supplied directly by a caller like `/synapse-task-note`):
|
|
|
171
171
|
characters (`/ : * ? " < > |`) with `-`, collapse repeated whitespace.
|
|
172
172
|
No timestamp prefix, no project-slug prefix — the filename is just the
|
|
173
173
|
(sanitized) title.
|
|
174
|
-
2.
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
2. Resolve tags through the `synapse-vault` skill's configured
|
|
175
|
+
`synapse-tag-vocabulary.conf` procedure. Choose only entries already in that vocabulary; an
|
|
176
|
+
empty list is valid when no tag applies, but the `tags` field itself is mandatory.
|
|
177
|
+
3. Fetch machine local time once: `date '+%Y-%m-%d %H:%M:%S %Z'` — never use inferred
|
|
178
|
+
time. Use the exact same value for `created` and `updated`.
|
|
179
|
+
4. Build the file content. A bare note needs a concise Summary. A task note needs lead prose and
|
|
180
|
+
at least one real flat checklist item before it can be written; never create an invalid empty
|
|
181
|
+
skeleton and promise to populate it later.
|
|
177
182
|
|
|
178
183
|
**Bare mode:**
|
|
179
184
|
```
|
|
180
185
|
---
|
|
186
|
+
schema: vault-note/v1
|
|
181
187
|
title: "{title}"
|
|
182
|
-
created: "{now}"
|
|
183
188
|
note_id: {id}
|
|
189
|
+
created: "{now}"
|
|
190
|
+
updated: "{now}"
|
|
191
|
+
tags: [{comma-separated tags, or empty}]
|
|
184
192
|
---
|
|
185
193
|
|
|
194
|
+
# {title}
|
|
195
|
+
|
|
196
|
+
## Summary
|
|
197
|
+
|
|
198
|
+
{essential content}
|
|
186
199
|
```
|
|
187
200
|
|
|
188
201
|
**Task mode:**
|
|
189
202
|
```
|
|
190
203
|
---
|
|
204
|
+
schema: vault-task-note/v1
|
|
191
205
|
title: "{title}"
|
|
192
|
-
|
|
206
|
+
project: {prefix}
|
|
193
207
|
task_id: {task-id}
|
|
208
|
+
created: "{now}"
|
|
209
|
+
updated: "{now}"
|
|
210
|
+
tags: [{comma-separated tags, or empty}]
|
|
194
211
|
status: TODO
|
|
195
|
-
last_updated: "{now}"
|
|
196
212
|
---
|
|
197
213
|
|
|
198
214
|
# {title}
|
|
199
215
|
|
|
216
|
+
{task description}
|
|
217
|
+
|
|
218
|
+
## Checklist
|
|
219
|
+
|
|
220
|
+
- [ ] {first implementation step}
|
|
221
|
+
|
|
200
222
|
## Notes
|
|
201
223
|
|
|
224
|
+
{constraints or context}
|
|
202
225
|
```
|
|
203
|
-
|
|
226
|
+
|
|
227
|
+
Quote every scalar string value. In particular, a value that is all digits
|
|
228
|
+
(a numeric-looking `title`, or any future numeric id) must be quoted — an
|
|
229
|
+
unquoted all-digit value is parsed as an integer and fails a `type: string`
|
|
230
|
+
schema field.
|
|
231
|
+
5. Write it with `synapse vault-write <path>` (content on stdin). Task mode: path
|
|
204
232
|
`tasks/{project}/{filename}.md` (project resolved in "Resolving the
|
|
205
233
|
project folder" above). Bare mode: path `{category}/{filename}.md`
|
|
206
234
|
(category resolved above).
|
|
@@ -209,7 +237,6 @@ or supplied directly by a caller like `/synapse-task-note`):
|
|
|
209
237
|
|
|
210
238
|
Report the file path back to the user.
|
|
211
239
|
|
|
212
|
-
- Bare mode:
|
|
240
|
+
- Bare mode: report the Summary that was captured.
|
|
213
241
|
- Task mode: note the task ID extracted or resolved, and remind the user
|
|
214
|
-
|
|
215
|
-
per the `synapse-task` skill.
|
|
242
|
+
that future status transitions are managed by the `synapse-task` skill.
|
|
@@ -178,9 +178,13 @@ so the `## Status` line is the only lifecycle marker that matters. It simply sta
|
|
|
178
178
|
|
|
179
179
|
```
|
|
180
180
|
---
|
|
181
|
+
schema: vault-design-note/v1
|
|
181
182
|
title: "{PROJECT} — {Topic}"
|
|
182
183
|
project: {prefix}
|
|
184
|
+
note_id: {id}
|
|
183
185
|
created: "{now}"
|
|
186
|
+
updated: "{now}"
|
|
187
|
+
tags: [{comma-separated configured tags, or empty}]
|
|
184
188
|
---
|
|
185
189
|
|
|
186
190
|
# {PROJECT} — {Topic}
|
|
@@ -204,7 +208,9 @@ Discussing | Ready | Reference
|
|
|
204
208
|
- {Anything deferred or unresolved}
|
|
205
209
|
```
|
|
206
210
|
|
|
207
|
-
|
|
211
|
+
Resolve tags through the `synapse-vault` skill's configured vocabulary procedure. Fetch machine
|
|
212
|
+
local time once (`date '+%Y-%m-%d %H:%M:%S %Z'`) — never infer it — and use the exact same value
|
|
213
|
+
for `created` and `updated`.
|
|
208
214
|
|
|
209
215
|
No `Notes`/changelog section — it stays a small, single-conclusion note; there's no long-running
|
|
210
216
|
edit history here worth tracking separately.
|
|
@@ -189,36 +189,58 @@ or supplied directly by a caller like the synapse-task-note skill):
|
|
|
189
189
|
characters (`/ : * ? " < > |`) with `-`, collapse repeated whitespace.
|
|
190
190
|
No timestamp prefix, no project-slug prefix — the filename is just the
|
|
191
191
|
(sanitized) title.
|
|
192
|
-
2.
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
2. Resolve tags through the `synapse-vault` skill's configured
|
|
193
|
+
`synapse-tag-vocabulary.conf` procedure. Choose only configured entries; an empty list is valid
|
|
194
|
+
when no tag applies, but the field itself is mandatory.
|
|
195
|
+
3. Fetch machine local time once: `date '+%Y-%m-%d %H:%M:%S %Z'` — never use inferred
|
|
196
|
+
time. Use the exact same value for `created` and `updated`.
|
|
197
|
+
4. Build the file content. Bare notes require a concise Summary. Task notes require lead prose and
|
|
198
|
+
at least one real flat checklist item before the first write.
|
|
195
199
|
|
|
196
200
|
**Bare mode:**
|
|
197
201
|
```
|
|
198
202
|
---
|
|
203
|
+
schema: vault-note/v1
|
|
199
204
|
title: "{title}"
|
|
200
|
-
created: "{now}"
|
|
201
205
|
note_id: {id}
|
|
206
|
+
created: "{now}"
|
|
207
|
+
updated: "{now}"
|
|
208
|
+
tags: [{comma-separated tags, or empty}]
|
|
202
209
|
---
|
|
203
210
|
|
|
211
|
+
# {title}
|
|
212
|
+
|
|
213
|
+
## Summary
|
|
214
|
+
|
|
215
|
+
{essential content}
|
|
204
216
|
```
|
|
205
217
|
|
|
206
218
|
**Task mode:**
|
|
207
219
|
```
|
|
208
220
|
---
|
|
221
|
+
schema: vault-task-note/v1
|
|
209
222
|
title: "{title}"
|
|
210
|
-
|
|
223
|
+
project: {prefix}
|
|
211
224
|
task_id: {task-id}
|
|
225
|
+
created: "{now}"
|
|
226
|
+
updated: "{now}"
|
|
227
|
+
tags: [{comma-separated tags, or empty}]
|
|
212
228
|
status: TODO
|
|
213
|
-
last_updated: "{now}"
|
|
214
229
|
---
|
|
215
230
|
|
|
216
231
|
# {title}
|
|
217
232
|
|
|
233
|
+
{task description}
|
|
234
|
+
|
|
235
|
+
## Checklist
|
|
236
|
+
|
|
237
|
+
- [ ] {first implementation step}
|
|
238
|
+
|
|
218
239
|
## Notes
|
|
219
240
|
|
|
241
|
+
{constraints or context}
|
|
220
242
|
```
|
|
221
|
-
|
|
243
|
+
5. Write it with `synapse vault-write <path>` (content on stdin). Task mode: path
|
|
222
244
|
`tasks/{project}/{filename}.md` (project resolved in "Resolving the
|
|
223
245
|
project folder" above). Bare mode: path `{category}/{filename}.md`
|
|
224
246
|
(category resolved above).
|
|
@@ -227,7 +249,6 @@ or supplied directly by a caller like the synapse-task-note skill):
|
|
|
227
249
|
|
|
228
250
|
Report the file path back to the user.
|
|
229
251
|
|
|
230
|
-
- Bare mode:
|
|
252
|
+
- Bare mode: report the Summary that was captured.
|
|
231
253
|
- Task mode: note the task ID extracted or resolved, and remind the user
|
|
232
|
-
|
|
233
|
-
per the `synapse-task` skill.
|
|
254
|
+
that future status transitions are managed by the `synapse-task` skill.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imunitic/synapse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Memory for Claude Code, Codex CLI, and OpenCode: a durable Obsidian vault plus a per-repo code graph.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,14 +17,15 @@
|
|
|
17
17
|
"skills",
|
|
18
18
|
"commands",
|
|
19
19
|
"harness",
|
|
20
|
+
"schema",
|
|
20
21
|
"synapse-claude.md",
|
|
21
22
|
"Index.md.template",
|
|
22
23
|
"*.conf.template"
|
|
23
24
|
],
|
|
24
25
|
"optionalDependencies": {
|
|
25
|
-
"@imunitic/synapse-darwin-arm64": "0.
|
|
26
|
-
"@imunitic/synapse-linux-x64": "0.
|
|
27
|
-
"@imunitic/synapse-linux-arm64": "0.
|
|
26
|
+
"@imunitic/synapse-darwin-arm64": "0.4.0",
|
|
27
|
+
"@imunitic/synapse-linux-x64": "0.4.0",
|
|
28
|
+
"@imunitic/synapse-linux-arm64": "0.4.0"
|
|
28
29
|
},
|
|
29
30
|
"license": "SEE LICENSE IN LICENSE"
|
|
30
31
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Declared keys are the full v1 spec; enforcement is a deliberate subset — unknown note fields are ignored, never an error.
|
|
2
|
+
schema: synapse-note-schema/v1
|
|
3
|
+
id: vault-design-note/v1
|
|
4
|
+
|
|
5
|
+
frontmatter:
|
|
6
|
+
fields:
|
|
7
|
+
schema:
|
|
8
|
+
type: string
|
|
9
|
+
required: true
|
|
10
|
+
const: vault-design-note/v1
|
|
11
|
+
title:
|
|
12
|
+
type: string
|
|
13
|
+
required: true
|
|
14
|
+
min_length: 1
|
|
15
|
+
project:
|
|
16
|
+
type: string
|
|
17
|
+
required: true
|
|
18
|
+
min_length: 1
|
|
19
|
+
note_id:
|
|
20
|
+
type: string
|
|
21
|
+
required: true
|
|
22
|
+
pattern: '^[a-z][a-z0-9-]*-[0-9]{3,}$'
|
|
23
|
+
mutable: false
|
|
24
|
+
created:
|
|
25
|
+
type: timestamp
|
|
26
|
+
required: true
|
|
27
|
+
format: 'YYYY-MM-dd HH:mm:ss TZ'
|
|
28
|
+
timezone: local
|
|
29
|
+
mutable: false
|
|
30
|
+
updated:
|
|
31
|
+
type: timestamp
|
|
32
|
+
required: true
|
|
33
|
+
format: 'YYYY-MM-dd HH:mm:ss TZ'
|
|
34
|
+
timezone: local
|
|
35
|
+
update_on: [vault-write, vault-patch]
|
|
36
|
+
tags:
|
|
37
|
+
type: list
|
|
38
|
+
required: true
|
|
39
|
+
items: string
|
|
40
|
+
|
|
41
|
+
body:
|
|
42
|
+
h1:
|
|
43
|
+
required: true
|
|
44
|
+
count: 1
|
|
45
|
+
equals: frontmatter.title
|
|
46
|
+
preamble:
|
|
47
|
+
- type: blockquote
|
|
48
|
+
required: false
|
|
49
|
+
position: immediately_after_h1
|
|
50
|
+
pattern: '^> Compiled task: \[\[[^\]]+\]\]$'
|
|
51
|
+
sections:
|
|
52
|
+
- title: Status
|
|
53
|
+
level: 2
|
|
54
|
+
required: true
|
|
55
|
+
content:
|
|
56
|
+
type: string
|
|
57
|
+
enum: [Discussing, Ready, Reference]
|
|
58
|
+
- title: Problem
|
|
59
|
+
level: 2
|
|
60
|
+
required: true
|
|
61
|
+
non_empty: true
|
|
62
|
+
- title: Approach
|
|
63
|
+
level: 2
|
|
64
|
+
required: true
|
|
65
|
+
non_empty: true
|
|
66
|
+
children:
|
|
67
|
+
- title: Alternatives considered
|
|
68
|
+
level: 3
|
|
69
|
+
required: false
|
|
70
|
+
non_empty: true
|
|
71
|
+
- title: Constraints
|
|
72
|
+
level: 2
|
|
73
|
+
required: true
|
|
74
|
+
non_empty: true
|
|
75
|
+
- title: Open Questions
|
|
76
|
+
level: 2
|
|
77
|
+
required: false
|
|
78
|
+
non_empty: true
|
|
79
|
+
section_order: relative
|
|
80
|
+
|
|
81
|
+
checks:
|
|
82
|
+
- equals: [filename.stem, frontmatter.title]
|
|
83
|
+
- unique: frontmatter.note_id
|
|
84
|
+
when: create
|
|
85
|
+
- vocabulary:
|
|
86
|
+
field: frontmatter.project
|
|
87
|
+
source: synapse-projects.conf
|
|
88
|
+
projection: values
|
|
89
|
+
- vocabulary:
|
|
90
|
+
field: frontmatter.tags
|
|
91
|
+
source: synapse-tag-vocabulary.conf
|
|
92
|
+
- not_before: [frontmatter.updated, frontmatter.created]
|
|
93
|
+
- equals:
|
|
94
|
+
values: [frontmatter.created, frontmatter.updated]
|
|
95
|
+
when: create
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Declared keys are the full v1 spec; enforcement is a deliberate subset — unknown note fields are ignored, never an error.
|
|
2
|
+
schema: synapse-note-schema/v1
|
|
3
|
+
id: vault-note/v1
|
|
4
|
+
|
|
5
|
+
frontmatter:
|
|
6
|
+
fields:
|
|
7
|
+
schema:
|
|
8
|
+
type: string
|
|
9
|
+
required: true
|
|
10
|
+
const: vault-note/v1
|
|
11
|
+
title:
|
|
12
|
+
type: string
|
|
13
|
+
required: true
|
|
14
|
+
min_length: 1
|
|
15
|
+
note_id:
|
|
16
|
+
type: string
|
|
17
|
+
required: true
|
|
18
|
+
pattern: '^[a-z][a-z0-9-]*-[0-9]{3,}$'
|
|
19
|
+
mutable: false
|
|
20
|
+
created:
|
|
21
|
+
type: timestamp
|
|
22
|
+
required: true
|
|
23
|
+
format: 'YYYY-MM-dd HH:mm:ss TZ'
|
|
24
|
+
timezone: local
|
|
25
|
+
mutable: false
|
|
26
|
+
updated:
|
|
27
|
+
type: timestamp
|
|
28
|
+
required: true
|
|
29
|
+
format: 'YYYY-MM-dd HH:mm:ss TZ'
|
|
30
|
+
timezone: local
|
|
31
|
+
update_on: [vault-write, vault-patch]
|
|
32
|
+
tags:
|
|
33
|
+
type: list
|
|
34
|
+
required: true
|
|
35
|
+
items: string
|
|
36
|
+
|
|
37
|
+
body:
|
|
38
|
+
h1:
|
|
39
|
+
required: true
|
|
40
|
+
count: 1
|
|
41
|
+
equals: frontmatter.title
|
|
42
|
+
sections:
|
|
43
|
+
- title: Summary
|
|
44
|
+
level: 2
|
|
45
|
+
required: true
|
|
46
|
+
- title: Details
|
|
47
|
+
level: 2
|
|
48
|
+
required: false
|
|
49
|
+
- title: Sources
|
|
50
|
+
level: 2
|
|
51
|
+
required: false
|
|
52
|
+
- title: Open Questions
|
|
53
|
+
level: 2
|
|
54
|
+
required: false
|
|
55
|
+
section_order: relative
|
|
56
|
+
|
|
57
|
+
checks:
|
|
58
|
+
- equals: [filename.stem, frontmatter.title]
|
|
59
|
+
- unique: frontmatter.note_id
|
|
60
|
+
when: create
|
|
61
|
+
- vocabulary:
|
|
62
|
+
field: frontmatter.tags
|
|
63
|
+
source: synapse-tag-vocabulary.conf
|
|
64
|
+
- not_before: [frontmatter.updated, frontmatter.created]
|
|
65
|
+
- equals:
|
|
66
|
+
values: [frontmatter.created, frontmatter.updated]
|
|
67
|
+
when: create
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Declared keys are the full v1 spec; enforcement is a deliberate subset — unknown note fields are ignored, never an error.
|
|
2
|
+
schema: synapse-note-schema/v1
|
|
3
|
+
id: vault-task-note/v1
|
|
4
|
+
|
|
5
|
+
frontmatter:
|
|
6
|
+
fields:
|
|
7
|
+
schema:
|
|
8
|
+
type: string
|
|
9
|
+
required: true
|
|
10
|
+
const: vault-task-note/v1
|
|
11
|
+
title:
|
|
12
|
+
type: string
|
|
13
|
+
required: true
|
|
14
|
+
min_length: 1
|
|
15
|
+
project:
|
|
16
|
+
type: string
|
|
17
|
+
required: true
|
|
18
|
+
min_length: 1
|
|
19
|
+
task_id:
|
|
20
|
+
type: string
|
|
21
|
+
required: true
|
|
22
|
+
pattern: '^[a-z][a-z0-9-]*-[0-9]{3,}$'
|
|
23
|
+
mutable: false
|
|
24
|
+
created:
|
|
25
|
+
type: timestamp
|
|
26
|
+
required: true
|
|
27
|
+
format: 'YYYY-MM-dd HH:mm:ss TZ'
|
|
28
|
+
timezone: local
|
|
29
|
+
mutable: false
|
|
30
|
+
updated:
|
|
31
|
+
type: timestamp
|
|
32
|
+
required: true
|
|
33
|
+
format: 'YYYY-MM-dd HH:mm:ss TZ'
|
|
34
|
+
timezone: local
|
|
35
|
+
update_on: [vault-write, vault-patch]
|
|
36
|
+
tags:
|
|
37
|
+
type: list
|
|
38
|
+
required: true
|
|
39
|
+
items: string
|
|
40
|
+
status:
|
|
41
|
+
type: string
|
|
42
|
+
required: true
|
|
43
|
+
enum: [TODO, IN-PROGRESS, REVIEW, DONE, CANCELED]
|
|
44
|
+
|
|
45
|
+
body:
|
|
46
|
+
h1:
|
|
47
|
+
required: true
|
|
48
|
+
count: 1
|
|
49
|
+
equals: frontmatter.title
|
|
50
|
+
lead:
|
|
51
|
+
type: prose
|
|
52
|
+
required: true
|
|
53
|
+
position: before_sections
|
|
54
|
+
checklist:
|
|
55
|
+
required: true
|
|
56
|
+
min_items: 1
|
|
57
|
+
position: before_sections
|
|
58
|
+
nested_items: false
|
|
59
|
+
allowed_children: [paragraph, fenced_code]
|
|
60
|
+
sections:
|
|
61
|
+
- title: Checklist
|
|
62
|
+
level: 2
|
|
63
|
+
required: true
|
|
64
|
+
- title: Notes
|
|
65
|
+
level: 2
|
|
66
|
+
required: false
|
|
67
|
+
max_occurs: 1
|
|
68
|
+
children:
|
|
69
|
+
- level: 3
|
|
70
|
+
required: false
|
|
71
|
+
repeatable: true
|
|
72
|
+
title_pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2} — .+$'
|
|
73
|
+
section_order: relative
|
|
74
|
+
|
|
75
|
+
checks:
|
|
76
|
+
- equals: [filename.stem, frontmatter.title]
|
|
77
|
+
- unique: frontmatter.task_id
|
|
78
|
+
when: create
|
|
79
|
+
- vocabulary:
|
|
80
|
+
field: frontmatter.project
|
|
81
|
+
source: synapse-projects.conf
|
|
82
|
+
projection: values
|
|
83
|
+
- vocabulary:
|
|
84
|
+
field: frontmatter.tags
|
|
85
|
+
source: synapse-tag-vocabulary.conf
|
|
86
|
+
- not_before: [frontmatter.updated, frontmatter.created]
|
|
87
|
+
- equals:
|
|
88
|
+
values: [frontmatter.created, frontmatter.updated]
|
|
89
|
+
when: create
|
|
90
|
+
- const:
|
|
91
|
+
field: frontmatter.status
|
|
92
|
+
value: TODO
|
|
93
|
+
when: create
|
|
@@ -21,12 +21,12 @@ Invoke this skill **automatically** in two situations:
|
|
|
21
21
|
|
|
22
22
|
1. **Starting work on a task** — as soon as the user confirms work is
|
|
23
23
|
beginning, before writing any code. Set `status: IN-PROGRESS` and update
|
|
24
|
-
`
|
|
24
|
+
`updated`. No notes needed at this point.
|
|
25
25
|
|
|
26
26
|
2. **Finishing work on a task** — after all phases are committed and
|
|
27
27
|
the task note's checklist has been updated. Set `status: REVIEW` (if all
|
|
28
28
|
items checked) or `status: IN-PROGRESS` (if any remain), update
|
|
29
|
-
`
|
|
29
|
+
`updated`, and append an implementation summary to the `## Notes`
|
|
30
30
|
section.
|
|
31
31
|
|
|
32
32
|
Never wait to be asked — apply this skill proactively at both transitions.
|
|
@@ -35,7 +35,7 @@ Never wait to be asked — apply this skill proactively at both transitions.
|
|
|
35
35
|
|
|
36
36
|
- Updates the `status:` frontmatter field (`TODO` → `IN-PROGRESS` or
|
|
37
37
|
`REVIEW`).
|
|
38
|
-
- Updates `
|
|
38
|
+
- Updates `updated` in frontmatter.
|
|
39
39
|
- At task completion: appends concise implementation bullets to the
|
|
40
40
|
existing `## Notes` section (or creates one if none exists).
|
|
41
41
|
|
|
@@ -60,11 +60,11 @@ into `status:` either — always go through this skill, which caps at
|
|
|
60
60
|
2. Inspect its checklist items (`- [ ]` / `- [x]`).
|
|
61
61
|
3. Determine the new `status:` value: `IN-PROGRESS` if any unchecked,
|
|
62
62
|
`REVIEW` if all checked.
|
|
63
|
-
4. Fetch machine local time: `date '+%Y-%m-%d %H:%M'` — never use inferred
|
|
63
|
+
4. Fetch machine local time: `date '+%Y-%m-%d %H:%M:%S %Z'` — never use inferred
|
|
64
64
|
time.
|
|
65
|
-
5. Update `status:` and `
|
|
65
|
+
5. Update `status:` and `updated:` with two `synapse frontmatter set`
|
|
66
66
|
calls, one per field: `synapse frontmatter set <path> status <value>`
|
|
67
|
-
then `synapse frontmatter set <path>
|
|
67
|
+
then `synapse frontmatter set <path> updated "{now}"`. Each call
|
|
68
68
|
changes exactly that one line and nothing else, entirely inside the
|
|
69
69
|
compiled binary — the note's body never enters your context at all.
|
|
70
70
|
When the command isn't available, fall back to **read-modify-write**:
|
|
@@ -94,12 +94,14 @@ The vault-patch hazards below are the task-note-specific instance of a general r
|
|
|
94
94
|
`synapse-vault` skill carries the full list (H1 replace, nested heading paths, frontmatter) for
|
|
95
95
|
every note, not just task notes.
|
|
96
96
|
|
|
97
|
-
**
|
|
98
|
-
|
|
99
|
-
the
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
**Edit checklist items through the `Checklist` heading, never the H1.** With `## Checklist` as its
|
|
98
|
+
own H2 — a sibling of `## Notes` — `vault-patch --heading "{H1 title}::Checklist" --replace`
|
|
99
|
+
(supplying the full new checklist) is the correct tool for a whole-checklist edit and leaves
|
|
100
|
+
`## Notes` untouched. Never target the top-level H1 (`--heading "{H1 title}"`): its section extends
|
|
101
|
+
through *all* nested subheadings (including `## Notes`), so a replace there silently deletes
|
|
102
|
+
everything past the checklist. To flip a single `- [ ]` → `- [x]` in place, `synapse vault-read`
|
|
103
|
+
the full file, edit that one line, and `synapse vault-write` the whole file back — there is no
|
|
104
|
+
per-item toggle yet.
|
|
103
105
|
|
|
104
106
|
## Notes format
|
|
105
107
|
|
|
@@ -116,18 +118,26 @@ level. Append to the last existing notes section.
|
|
|
116
118
|
## Task file structure
|
|
117
119
|
|
|
118
120
|
Each task note, in any project, has **exactly one top-level heading** (the
|
|
119
|
-
task itself, `# {title}`).
|
|
120
|
-
|
|
121
|
-
Step` sub-headings for
|
|
121
|
+
task itself, `# {title}`). Under it: lead prose describing the task, then a
|
|
122
|
+
required `## Checklist` heading holding the `- [ ]` implementation items,
|
|
123
|
+
then a `## Notes` section. Do not create `## Step` sub-headings for
|
|
124
|
+
implementation steps, and do not put checklist items directly under the H1.
|
|
122
125
|
|
|
123
126
|
Correct structure:
|
|
124
127
|
```md
|
|
125
128
|
# Implement something
|
|
126
129
|
|
|
127
130
|
Description of the task.
|
|
131
|
+
|
|
132
|
+
## Checklist
|
|
133
|
+
|
|
128
134
|
- [ ] Step one
|
|
129
135
|
- [ ] Step two
|
|
130
136
|
- [ ] Step three
|
|
137
|
+
|
|
138
|
+
## Notes
|
|
139
|
+
|
|
140
|
+
{constraints or context}
|
|
131
141
|
```
|
|
132
142
|
|
|
133
143
|
Wrong structure (do not do this):
|