@imunitic/synapse 0.13.5 → 0.13.7
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/commands/synapse-design-note.md +1 -1
- package/commands/synapse-init.md +4 -4
- package/commands/synapse-note.md +1 -1
- package/commands/synapse-rebuild-full.md +1 -1
- package/commands/synapse-task-note.md +1 -1
- package/commands/synapse-vault-tidy.md +4 -3
- package/harness/codex/skills/synapse-design-note/SKILL.md +5 -1
- package/harness/codex/skills/synapse-note/SKILL.md +5 -0
- package/harness/codex/skills/synapse-vault-tidy/SKILL.md +1 -1
- package/package.json +4 -4
- package/skills/synapse-node/SKILL.md +3 -3
- package/skills/synapse-node-authoring/SKILL.md +18 -23
- package/skills/synapse-node-format/SKILL.md +3 -0
- package/skills/synapse-query/SKILL.md +2 -2
- package/skills/synapse-vault/SKILL.md +8 -5
|
@@ -238,7 +238,7 @@ edit history here worth tracking separately.
|
|
|
238
238
|
## Filename
|
|
239
239
|
|
|
240
240
|
`designs/{project}/{Topic}.md` — grouped one level deeper into a per-project
|
|
241
|
-
subfolder named by the note's own `project:` frontmatter value (e.g. `designs/
|
|
241
|
+
subfolder named by the note's own `project:` frontmatter value (e.g. `designs/widget/`,
|
|
242
242
|
`designs/synapse/`), the same mapping `tasks/{project}/` uses. Sanitize filesystem-illegal
|
|
243
243
|
characters (`/ : * ? " < > |`). No slug, no numbering — vault filenames are the title itself.
|
|
244
244
|
|
package/commands/synapse-init.md
CHANGED
|
@@ -40,8 +40,8 @@ No arguments — always operates on the repo containing the current working dire
|
|
|
40
40
|
Every step below needs the same three facts, resolved once up front:
|
|
41
41
|
|
|
42
42
|
1. **Repo root:** `git rev-parse --show-toplevel`.
|
|
43
|
-
2. **Namespace key:** `{repo}@{branch}`, resolved by `
|
|
44
|
-
`
|
|
43
|
+
2. **Namespace key:** `{repo}@{branch}`, resolved by `synapse namespace`
|
|
44
|
+
(`core.identity.namespace`) — never derived by hand here, since every component resolves it the same way
|
|
45
45
|
from that one place and a second derivation is how they start disagreeing. The repo half comes
|
|
46
46
|
from the *remote's* basename, not the directory: a linked worktree's directory name differs from
|
|
47
47
|
its parent's, and that difference is exactly what must not matter. The branch half is
|
|
@@ -51,8 +51,8 @@ Every step below needs the same three facts, resolved once up front:
|
|
|
51
51
|
and `stale` describing a single tree, and it means a branch switch leaves the old graph intact
|
|
52
52
|
rather than invalidating it wholesale.
|
|
53
53
|
|
|
54
|
-
**On a detached HEAD, stop.** There is no branch, so there is no key — `
|
|
55
|
-
1
|
|
54
|
+
**On a detached HEAD, stop.** There is no branch, so there is no key — `synapse namespace` exits
|
|
55
|
+
1 with `core.identity.detached_message`. Do not invent one, and do not fall back to the directory name: every detached
|
|
56
56
|
checkout everywhere would collide on the same value. Tell the user to check out a branch first.
|
|
57
57
|
|
|
58
58
|
Distinct from the short task-prefix scheme (`project-name=prefix`) used by
|
package/commands/synapse-note.md
CHANGED
|
@@ -32,7 +32,7 @@ Categorize:
|
|
|
32
32
|
- **Prefixed notes**: `task_id` matches `{prefix}-\d+`. Group by the distinct prefix found (whatever
|
|
33
33
|
prefixes actually appear — don't assume a fixed set). Within each prefix, split further into:
|
|
34
34
|
- **Open**: `status` is `TODO`, `IN-PROGRESS`, or `REVIEW` (or missing — treat as open)
|
|
35
|
-
- **Closed**: `status` is `DONE
|
|
35
|
+
- **Closed**: `status` is `DONE` or `CANCELED`
|
|
36
36
|
- **Other notes**: no `task_id`, or one that doesn't match `{prefix}-\d+`
|
|
37
37
|
|
|
38
38
|
Sort each prefix group's notes numerically by task id (`{prefix}-9` before `{prefix}-10`); sort other notes alphabetically by title. Report one section per prefix found — "{prefix} notes — open", "{prefix} notes — closed" — plus "Other notes", each line as `{task-id or filename} — {title} [{status}]`. Omit a section header if it has zero entries. End with a total count.
|
|
@@ -32,7 +32,7 @@ No arguments — always operates on the repo and branch containing the current w
|
|
|
32
32
|
- Requires the `synapse` CLI on `PATH`. If it errors (no vault configured), say so and stop —
|
|
33
33
|
same requirement `/synapse-init` has.
|
|
34
34
|
- Must be run from inside a git repository, on a named branch (not detached `HEAD`) — same
|
|
35
|
-
requirement `/synapse-init` has, since `
|
|
35
|
+
requirement `/synapse-init` has, since `synapse namespace` needs a branch to key on.
|
|
36
36
|
|
|
37
37
|
## Procedure
|
|
38
38
|
|
|
@@ -35,7 +35,7 @@ Use those instead of reinventing a parallel view.
|
|
|
35
35
|
nothing to compile. Reopen it with `/synapse-design-note \"{topic}\"` and mark it Ready if that's
|
|
36
36
|
changed."
|
|
37
37
|
- A task note already exists for this design (check the design note's `> Compiled task:` annotation,
|
|
38
|
-
or `
|
|
38
|
+
or `synapse vault-search-text` for a `tasks/` note linking to it) → show its current state (title, `status:`,
|
|
39
39
|
checked/total) and ask: view it, or recompile (only on explicit confirmation — recompiling rewrites
|
|
40
40
|
the checklist, so any progress on items that no longer exist is lost).
|
|
41
41
|
|
|
@@ -83,8 +83,9 @@ just two fields (`title`, `created` — see `synapse-note`'s bare-mode format),
|
|
|
83
83
|
guessing:
|
|
84
84
|
|
|
85
85
|
- Missing `title` → the filename with its `.md` extension stripped.
|
|
86
|
-
- Missing `created` → `stat.ctime`, formatted
|
|
87
|
-
convention
|
|
86
|
+
- Missing `created` → `stat.ctime`, formatted as RFC3339 with a numeric offset (`synapse now`'s
|
|
87
|
+
own shape) to match every other note's real `created`/`updated` convention — not `built_at`'s
|
|
88
|
+
coarser `YYYY-MM-DD HH:MM`, which is graph-node-only.
|
|
88
89
|
|
|
89
90
|
Apply with `synapse frontmatter set <path> <key> <value>` (or `vault-patch --frontmatter`, which
|
|
90
91
|
delegates to the same byte-preserving mechanism) — either writes exactly this one field and leaves
|
|
@@ -154,7 +155,7 @@ proposal, for the vault owner to act on.
|
|
|
154
155
|
## Step 6: Compose the proposal
|
|
155
156
|
|
|
156
157
|
One note, `inbox/Vault tidy — {YYYY-MM-DD}.md` (fetch machine local time, never infer it), written
|
|
157
|
-
via `
|
|
158
|
+
via `vault-write` (creates `inbox/` automatically if it doesn't exist yet; if `inbox/` isn't already
|
|
158
159
|
in `Index.md`'s folder list, add it there in the same pass, matching the folder-layout rule every
|
|
159
160
|
other command that can create a top-level folder already follows). Two sections:
|
|
160
161
|
|
|
@@ -231,6 +231,10 @@ already follows above, just additive instead of pruned. Named `References` rathe
|
|
|
231
231
|
`## Links` for something unrelated (source files, typed relations) in that other kind of note
|
|
232
232
|
sharing the same vault.
|
|
233
233
|
|
|
234
|
+
Any string scalar that is all digits (e.g. a numeric-looking title) must be quoted: an
|
|
235
|
+
unquoted all-digit value is parsed as an integer, which fails a `type: string` schema
|
|
236
|
+
field. `title`, `project`, `note_id`, and both timestamps are quoted above.
|
|
237
|
+
|
|
234
238
|
Resolve tags through the `synapse-vault` skill's configured vocabulary procedure. Fetch machine
|
|
235
239
|
local time once (`synapse now`) — never infer it — and use the exact same value for `created` and
|
|
236
240
|
`updated`.
|
|
@@ -241,7 +245,7 @@ edit history here worth tracking separately.
|
|
|
241
245
|
## Filename
|
|
242
246
|
|
|
243
247
|
`designs/{project}/{Topic}.md` — grouped one level deeper into a per-project
|
|
244
|
-
subfolder named by the note's own `project:` frontmatter value (e.g. `designs/
|
|
248
|
+
subfolder named by the note's own `project:` frontmatter value (e.g. `designs/widget/`,
|
|
245
249
|
`designs/synapse/`), the same mapping tasks use. Sanitize filesystem-illegal
|
|
246
250
|
characters (`/ : * ? " < > |`). No slug, no numbering — vault filenames are the title itself.
|
|
247
251
|
|
|
@@ -250,6 +250,11 @@ or supplied directly by a caller like the synapse-task-note skill):
|
|
|
250
250
|
|
|
251
251
|
{constraints or context}
|
|
252
252
|
```
|
|
253
|
+
|
|
254
|
+
Quote every scalar string value. In particular, a value that is all digits
|
|
255
|
+
(a numeric-looking `title`, or any future numeric id) must be quoted — an
|
|
256
|
+
unquoted all-digit value is parsed as an integer and fails a `type: string`
|
|
257
|
+
schema field.
|
|
253
258
|
5. Write it with `synapse vault-write <path>` (content on stdin). Task mode: path
|
|
254
259
|
`tasks/{project}/{filename}.md` (project resolved in "Resolving the
|
|
255
260
|
project folder" above). Bare mode: path `{category}/{filename}.md`
|
|
@@ -155,7 +155,7 @@ proposal, for the vault owner to act on.
|
|
|
155
155
|
## Step 6: Compose the proposal
|
|
156
156
|
|
|
157
157
|
One note, `inbox/Vault tidy — {YYYY-MM-DD}.md` (fetch machine local time, never infer it), written
|
|
158
|
-
via `
|
|
158
|
+
via `vault-write` (creates `inbox/` automatically if it doesn't exist yet; if `inbox/` isn't already
|
|
159
159
|
in the index note's folder list, add it there in the same pass, matching the folder-layout rule every
|
|
160
160
|
other skill that can create a top-level folder already follows). Two sections:
|
|
161
161
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imunitic/synapse",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.7",
|
|
4
4
|
"description": "Memory for Claude Code, Codex CLI, and OpenCode: a durable markdown vault plus a per-repo code graph.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"*.conf.template"
|
|
24
24
|
],
|
|
25
25
|
"optionalDependencies": {
|
|
26
|
-
"@imunitic/synapse-darwin-arm64": "0.13.
|
|
27
|
-
"@imunitic/synapse-linux-x64": "0.13.
|
|
28
|
-
"@imunitic/synapse-linux-arm64": "0.13.
|
|
26
|
+
"@imunitic/synapse-darwin-arm64": "0.13.7",
|
|
27
|
+
"@imunitic/synapse-linux-x64": "0.13.7",
|
|
28
|
+
"@imunitic/synapse-linux-arm64": "0.13.7"
|
|
29
29
|
},
|
|
30
30
|
"license": "SEE LICENSE IN LICENSE"
|
|
31
31
|
}
|
|
@@ -14,7 +14,7 @@ speculatively.
|
|
|
14
14
|
|
|
15
15
|
Whenever a `synapse/{project}/{Node}.md` file is about to be read **for its content to actually be
|
|
16
16
|
used** (orienting on a subsystem, answering a question about it, deciding where to make a change)
|
|
17
|
-
— not for a `
|
|
17
|
+
— not for a `vault-list`/title-only skim. Run this procedure *before* trusting what comes back from
|
|
18
18
|
that read. This is the one Synapse mechanism that isn't a hook: a hook is compiled code with no
|
|
19
19
|
reasoning, and classifying whether a file "fits" a node is exactly the kind of judgment call that
|
|
20
20
|
needs one.
|
|
@@ -133,7 +133,7 @@ needs one.
|
|
|
133
133
|
|
|
134
134
|
It replaces only the generated region and re-emits everything after the closing fence verbatim,
|
|
135
135
|
which is what makes the `## Notes` guarantee enforceable rather than a promise.
|
|
136
|
-
- **Never hand-write the frontmatter**, with `
|
|
136
|
+
- **Never hand-write the frontmatter**, with `vault-patch --frontmatter <key>` or
|
|
137
137
|
otherwise. `--frontmatter` only ever writes a single scalar value, so it can't represent
|
|
138
138
|
`sources:`/`grounded_in:` at all, and enumerating the rest of a node's fields by hand one call
|
|
139
139
|
at a time is how `summary` and `commit` get silently dropped — which then breaks the next
|
|
@@ -195,7 +195,7 @@ needs one.
|
|
|
195
195
|
- Never treat the script's exit 1 as a clean result. It means the check could not run.
|
|
196
196
|
- Never regenerate a node that neither the script nor its `stale:` flag named — regeneration is real
|
|
197
197
|
cost, reserved for actual staleness.
|
|
198
|
-
- Never `
|
|
198
|
+
- Never `vault-read` a hub node just to read its summary. Offset past the frontmatter (step 3).
|
|
199
199
|
- Never silently fold a regeneration or an unassigned-file attachment into normal output — both
|
|
200
200
|
get an explicit, visible announcement line.
|
|
201
201
|
- `## Notes` content is sacrosanct across regeneration — if a rewrite would touch it, that's a bug
|
|
@@ -9,11 +9,9 @@ Loaded wherever a *batch* of nodes needs prose written, not a single lazy regene
|
|
|
9
9
|
is the `synapse-node` skill's job, one node, triggered by a stale read). Today's caller is
|
|
10
10
|
`/synapse-init`'s node-authoring step. `/synapse-rebuild-full` inherits this for free — it
|
|
11
11
|
delegates to `/synapse-init`'s procedure by reference rather than repeating it.
|
|
12
|
-
`/synapse-rebuild-diff`'s *re-orient* class is a natural second caller
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
gathers its facts ad hoc rather than through `rank --lists`/`link-graph`, and needs that fixed
|
|
16
|
-
first.
|
|
12
|
+
`/synapse-rebuild-diff`'s *re-orient* class is a natural second caller but is not wired to this
|
|
13
|
+
skill yet — it still gathers its facts ad hoc rather than through `rank --lists`/`link-graph`,
|
|
14
|
+
and needs that fixed first.
|
|
17
15
|
|
|
18
16
|
This skill owns two things: **deciding how many authors run at once**, and **the standing
|
|
19
17
|
contract every author works under**, whichever pool size is in play. Which nodes need
|
|
@@ -132,23 +130,22 @@ flowing text.
|
|
|
132
130
|
|
|
133
131
|
Same model as the orchestrating session, no override — matches the constraint that "a
|
|
134
132
|
parallel author produces exactly what a sequential one does," and keeps the quality
|
|
135
|
-
comparison
|
|
136
|
-
than two (that, plus a cheaper model).
|
|
133
|
+
comparison to one variable (isolation/concurrency) rather than two (that, plus a cheaper model).
|
|
137
134
|
|
|
138
135
|
**Why this is spelled out explicitly rather than assumed inherited:** a prior pooled run shipped
|
|
139
|
-
hard-wrapped nodes despite the vault's no-hard-wrap
|
|
140
|
-
|
|
141
|
-
Loading `synapse-node-format` does not cover it
|
|
142
|
-
structure, not the vault's prose-formatting
|
|
143
|
-
assuming it travels for free.
|
|
136
|
+
hard-wrapped nodes despite the vault's own no-hard-wrap convention (every paragraph is one
|
|
137
|
+
continuous line in the source, letting the viewer soft-wrap it) — evidently not reliably carried
|
|
138
|
+
into a fresh subagent's behavior on its own. Loading `synapse-node-format` does not cover it
|
|
139
|
+
either, since that skill is about the node's structure, not the vault's prose-formatting
|
|
140
|
+
convention. State it here, every time, rather than assuming it travels for free.
|
|
144
141
|
|
|
145
142
|
### 3d. Verify on completion, retry once, then fall back
|
|
146
143
|
|
|
147
144
|
When a completion notification arrives, read `b-NN.md` yourself — this is a check you read the
|
|
148
|
-
file for, same as the section check next to it, not a shell one-liner (
|
|
149
|
-
frontmatter reader
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
file for, same as the section check next to it, not a shell one-liner (`core/query.zig` is this
|
|
146
|
+
codebase's own tested, compiled frontmatter reader — a fresh hand-rolled `grep`/`sed`/`awk`
|
|
147
|
+
pattern here would drift from it the same way the gap this section exists to close first
|
|
148
|
+
happened). Confirm the file exists, opens with
|
|
152
149
|
frontmatter carrying a non-empty `summary:` field (`synapse-node-format`'s own contract — see
|
|
153
150
|
its "Each `b-NN.md` opens with its own one-line summary in frontmatter" line), and has
|
|
154
151
|
`## Summary`, `## Crux`, and `## Links` sections. Pass → dispatch the next queued node (§3b) and
|
|
@@ -177,9 +174,8 @@ Not a synonym for §2. It still bundles a brief, dispatches to an isolated subag
|
|
|
177
174
|
and retries-then-falls-back — only the concurrency is 1. Useful on its own terms: it isolates
|
|
178
175
|
whether a quality difference against the sequential baseline comes from *isolation* (no
|
|
179
176
|
author sees another's output or memory — present even at pool 1) or from *concurrency*
|
|
180
|
-
itself (only present at pool ≥ 2). Reach for it specifically when
|
|
181
|
-
|
|
182
|
-
committing to a higher pool size.
|
|
177
|
+
itself (only present at pool ≥ 2). Reach for it specifically when comparing prose quality
|
|
178
|
+
against a sequential build, before committing to a higher pool size.
|
|
183
179
|
|
|
184
180
|
## Guardrails
|
|
185
181
|
|
|
@@ -188,13 +184,12 @@ committing to a higher pool size.
|
|
|
188
184
|
read-only during it — this is what removes the concurrent-writer problem rather than merely
|
|
189
185
|
managing it.
|
|
190
186
|
- **No author reads another node's brief or body.** Overlap in *source* reads (two nodes'
|
|
191
|
-
file lists sharing a path) is expected and accepted
|
|
192
|
-
|
|
187
|
+
file lists sharing a path) is expected and accepted, but an author's own inputs are its
|
|
188
|
+
brief and nothing else.
|
|
193
189
|
- **Never grow the pool mid-run.** The size is resolved once at the start (§1); do not read
|
|
194
190
|
`synapse.conf` again partway through a build.
|
|
195
191
|
- **A retry gets the same brief, not a rewritten one.** If the brief itself was the problem,
|
|
196
192
|
fixing it is a §3a-level fix (regenerate every brief and restart), not something to
|
|
197
193
|
improvise per-node inside the retry.
|
|
198
194
|
- **`part_of` is never computed, at any pool size.** It is containment, not reference, and
|
|
199
|
-
deriving it from directory nesting would turn a folder layout into a claim about concepts
|
|
200
|
-
the same reasoning the design's own Alternatives section already rejected this on.
|
|
195
|
+
deriving it from directory nesting would turn a folder layout into a claim about concepts.
|
|
@@ -60,6 +60,8 @@ to orient someone already inside. A node without one is an error, not a default.
|
|
|
60
60
|
a single-key lookup never has to scan past it. `graph-node/v1`'s schema enforces this order
|
|
61
61
|
directly (`field_order: relative`); this document and `synapse write-node`'s own emission order
|
|
62
62
|
agree with it, not the other way around.
|
|
63
|
+
- **`branch`:** the branch half of the namespace key (`synapse namespace --branch`), filled in by
|
|
64
|
+
the writer — never hand-authored.
|
|
63
65
|
- **`sources_digest`:** `sha256` over the sorted `path:hash` lines of `sources` (see "Computing
|
|
64
66
|
`sources_digest`" below). Lets a staleness check answer "has this node changed" by reading one
|
|
65
67
|
field instead of every hash.
|
|
@@ -157,6 +159,7 @@ schema: graph-node/v1
|
|
|
157
159
|
title: "World — entity/component/resource core"
|
|
158
160
|
node_type: synapse-node
|
|
159
161
|
project: acme
|
|
162
|
+
branch: main
|
|
160
163
|
sources_digest: <sha256 over the sorted "path:hash" lines>
|
|
161
164
|
stale: false
|
|
162
165
|
built_at: "<now>"
|
|
@@ -88,14 +88,14 @@ resolve the specific symbol-level question:
|
|
|
88
88
|
## Guardrails
|
|
89
89
|
|
|
90
90
|
- **Never grep the whole repo before checking `synapse/{project}/Index.md`**, unless this repo has
|
|
91
|
-
no Synapse namespace at all (`
|
|
91
|
+
no Synapse namespace at all (`vault-list` on `synapse/{project}/` comes back empty). Before
|
|
92
92
|
concluding there's nothing to consult, check whether the task actually concerns a *different*
|
|
93
93
|
checkout — `synapse query --namespace <repo>@<branch> body "{Node}"` reaches that repo's graph
|
|
94
94
|
without switching directories or checking it out. Only when no namespace anywhere covers the task
|
|
95
95
|
is there truly nothing to consult; say so and proceed normally.
|
|
96
96
|
- **Never treat a node's summary as ground truth for a symbol-level claim** it wasn't built to make
|
|
97
97
|
precisely — see "When a node isn't enough" above.
|
|
98
|
-
- **Never `
|
|
98
|
+
- **Never `vault-read` a node just to read its prose — including a node in another checkout's
|
|
99
99
|
namespace.** That pulls the full frontmatter, which can run to megabytes on a hub node. Use
|
|
100
100
|
`synapse query body` (add `--namespace <repo>@<branch>` for a graph outside this checkout) — see
|
|
101
101
|
the cost note above.
|
|
@@ -34,8 +34,11 @@ synapse vault-read <path> the whole note -- no partial/targeted
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
`vault-search`'s JsonLogic filter and `--fields` projection both stop at frontmatter/tags/content/
|
|
37
|
-
path --
|
|
38
|
-
|
|
37
|
+
path -- links aren't filterable through search itself, though a dedicated whole-vault wikilink
|
|
38
|
+
index does exist as its own set of subcommands (`vault-backlinks`/`vault-links`/`vault-unresolved`/
|
|
39
|
+
`vault-orphans`/`vault-deadends`/`vault-ambiguous`/`vault-rename`), reach for one of those directly
|
|
40
|
+
instead of trying to express a link query through `vault-search`. `vault-read` always returns the
|
|
41
|
+
full body, never one section on its own -- request
|
|
39
42
|
exactly what you need with `--fields` instead of over-fetching, and pull a specific section out of
|
|
40
43
|
`vault-read`'s output locally when that's all you actually need.
|
|
41
44
|
|
|
@@ -110,15 +113,15 @@ Every new note is created through an authoring command, never by freeforming a f
|
|
|
110
113
|
- `/synapse-note` (bare mode) creates plain notes in any category -- `research/`,
|
|
111
114
|
`scratchpad/`, `inbox/`, anything that is not a tracked task or a design note. It mints the
|
|
112
115
|
frontmatter (`schema`, `title`, `note_id`, `created`, `updated`, `tags`) to the note schema's
|
|
113
|
-
contract,
|
|
116
|
+
contract, sampling `created`/`updated` from `synapse now`.
|
|
114
117
|
- `/synapse-note --task` creates tracked task notes under `tasks/{project}/`.
|
|
115
118
|
- `/synapse-design-note` and `/synapse-task-note` handle design discussions and compiled tasks --
|
|
116
119
|
both delegate the file-minting mechanics to `/synapse-note` internally.
|
|
117
120
|
|
|
118
121
|
`vault-write` is for *editing existing notes*, or the rare read-modify-write round trip. If a
|
|
119
122
|
direct creation is ever genuinely unavoidable, follow bare mode's frontmatter contract exactly
|
|
120
|
-
(`schema`/`title`/`note_id`/`created`/`updated`/`tags`,
|
|
121
|
-
rather than improvising a shape.
|
|
123
|
+
(`schema`/`title`/`note_id`/`created`/`updated`/`tags`, with `created`/`updated` taken from
|
|
124
|
+
`synapse now` -- never hand-typed) rather than improvising a shape.
|
|
122
125
|
|
|
123
126
|
Schemas are opt-in by declaration: a note whose frontmatter declares `schema:` is held to that
|
|
124
127
|
schema's contract on every `vault-write`/`vault-patch`; a note without the field is never
|