docs: clarify db-backed state guidance

This commit is contained in:
Mikael Hugo 2026-05-07 03:20:20 +02:00
parent 2fae96d539
commit 39382f7e54
5 changed files with 20 additions and 14 deletions

View file

@ -40,11 +40,11 @@ Schedule entries use [ULID](https://github.com/ulid/spec) (Universally Unique Le
The `generateULID()` function in `schedule-ulid.js` is used for all new entries.
### Append-Only JSONL
### Versioned Append-Only JSONL
Each write appends a JSON line to `schedule.jsonl`. The latest entry per ID wins on read (via `created_at` comparison). This means status transitions (`pending``done`, `cancelled`, `snoozed`) are implemented as new entries, not mutations. The file is never rewritten — only appended to.
Each write appends a schema-versioned JSON line to `schedule.jsonl`. The latest entry per ID wins on read (via `created_at` comparison). This means status transitions (`pending``done`, `cancelled`, `snoozed`) are implemented as new entries, not mutations. The file is never rewritten — only appended to.
Corrupt lines are skipped with a warning, never fatal.
Rows without `schemaVersion` are treated as legacy version 1. Unsupported future schema versions are ignored by the current reader. Corrupt lines are skipped with a warning, never fatal.
---
@ -61,6 +61,7 @@ Corrupt lines are skipped with a warning, never fatal.
```json
{
"schemaVersion": 1,
"id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", // ULID — 28 chars
"kind": "reminder", // ScheduleKind enum
"status": "pending", // pending | done | cancelled | snoozed
@ -76,7 +77,7 @@ Corrupt lines are skipped with a warning, never fatal.
### JSONL Line Example
```
{"id":"01ARZ3NDEKTSV4RRFFQ69G5FAV","kind":"reminder","status":"pending","due_at":"2026-06-15T09:00:00.000Z","created_at":"2026-05-15T09:00:00.000Z","payload":{"message":"Review adoption metrics"},"created_by":"user","auto_dispatch":false}
{"schemaVersion":1,"id":"01ARZ3NDEKTSV4RRFFQ69G5FAV","kind":"reminder","status":"pending","due_at":"2026-06-15T09:00:00.000Z","created_at":"2026-05-15T09:00:00.000Z","payload":{"message":"Review adoption metrics"},"created_by":"user","auto_dispatch":false}
```
---

View file

@ -372,7 +372,8 @@ export function loadKnowledgeBlock(sfHomeDir, cwd) {
const TACIT_SECTION_MAX_BYTES = 4096;
// Cap self-feedback entries to prevent context bloat. High/critical entries
// are always included; medium/low are truncated if needed. Evidence details
// are stored in jsonl only — the prompt gets compact summaries with IDs.
// live in the durable self-feedback store; the prompt gets compact summaries
// with IDs.
// (#sf-moobj36p-ko6snt)
const SELF_FEEDBACK_MAX_ENTRIES = 20;
const SELF_FEEDBACK_MAX_CHARS = 4000;
@ -425,7 +426,7 @@ function loadSelfFeedbackBlock(cwd) {
if (kept.length > SELF_FEEDBACK_MAX_ENTRIES) {
kept = kept.slice(0, SELF_FEEDBACK_MAX_ENTRIES);
}
// Render compact summaries — evidence is in jsonl, not injected here
// Render compact summaries — full evidence is not injected here
const rows = kept
.map((e) => `- **${e.severity}** \`${e.kind}\`${e.summary}`)
.join("\n");
@ -443,7 +444,7 @@ function loadSelfFeedbackBlock(cwd) {
}
// Add note about where to find full evidence
if (entries.length > kept.length) {
block += `\n\n*(${entries.length - kept.length} more entries hidden to prevent context bloat. Full evidence in .sf/self-feedback.jsonl by entry ID.)*`;
block += `\n\n*(${entries.length - kept.length} more entries hidden to prevent context bloat. Use sf_self_feedback_resolve/read tools or .sf/SELF-FEEDBACK.md entry IDs to inspect full evidence.)*`;
}
return `\n\n[SELF-FEEDBACK — Recent sf-internal anomalies]\n\n${block}`;
}

View file

@ -2,7 +2,7 @@
* SF Command /sf schedule
*
* Schedule management: add, list, done, cancel, snooze, run.
* Entries stored as append-only JSONL in .sf/schedule.jsonl (project)
* Entries stored as versioned append-only JSONL in .sf/schedule.jsonl (project)
* or ~/.sf/schedule.jsonl (global).
*/

View file

@ -155,7 +155,7 @@ function buildInlineFixPrompt(entries) {
"4. Commit the fix with a conventional commit message.",
"5. Call `sf_self_feedback_resolve` for each repaired entry with agent-fix evidence and the commit SHA.",
"6. If an entry is already fixed, verify it and call `sf_self_feedback_resolve` with the verification evidence.",
"7. Do not hand-edit `.sf/self-feedback.jsonl`; use the resolver tool so markdown, JSONL, and reload detection stay consistent.",
"7. Do not hand-edit `.sf/self-feedback.jsonl` or `.sf/SELF-FEEDBACK.md`; use the resolver tool so the durable self-feedback store, markdown projection, and reload detection stay consistent.",
"",
"When done, say: Self-feedback inline fix complete.",
].join("\n");

View file

@ -207,21 +207,25 @@ See [references/answer-injection.md](references/answer-injection.md) for full de
## SF Project Structure
All state lives in `.sf/` as markdown files (version-controllable):
Durable project state lives in `.sf/sf.db` when the project has been migrated.
Markdown files in `.sf/` are version-controllable projections, exports, or
recovery/import inputs:
```
.sf/
milestones/M001/
M001-CONTEXT.md # Requirements, scope, decisions
M001-ROADMAP.md # Slices with tasks, dependencies, checkboxes
M001-ROADMAP.md # Rendered roadmap projection
M001-SUMMARY.md # Completion summary
slices/S01/
S01-PLAN.md # Task list
S01-PLAN.md # Rendered slice plan projection
S01-SUMMARY.md # Slice summary with frontmatter
tasks/T01-PLAN.md # Individual task spec
tasks/T01-PLAN.md # Rendered task plan projection
```
State is derived from files on disk — checkboxes in ROADMAP.md are the source of truth for completion.
Use `sf headless query` or the SF DB-backed tools to inspect and mutate state.
Do not treat roadmap checkboxes as authoritative for completion when the DB is
available.
## All Headless Commands