From 7656ad8052c5308fb2407215c5ffaeb21ca2bf8e Mon Sep 17 00:00:00 2001 From: Alan Wizemann Date: Fri, 24 Apr 2026 01:09:49 +0200 Subject: [PATCH] docs(v2.3): document how agents see Scarf projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three doc updates covering the AGENTS.md context-injection pattern introduced in the previous commit. CLAUDE.md — new "Project-scoped chat + Scarf-managed AGENTS.md context (v2.3)" subsection under Project Templates. Covers: - The session-project sidecar at ~/.hermes/scarf/session_project_map.json (why it exists, what manages it) - How Hermes picks up project context: cwd-based auto-load of the first matching context file (priority order, 20KB cap) - Exact marker format and block shape - Invariants that future edits must preserve: secret-safe, idempotent, bounded-region, non-fatal, refresh-before-session-start ordering - Template-author contract: leave the region alone, put instructions below - Known caveat: parent-directory `.hermes.md` shadowing (deferred to v2.4) scarf-template-author SKILL.md — new pitfall bullet in the "Common pitfalls" checklist telling scaffolding agents to preserve the `` region and put template- specific instructions below it. Rebuilt the bundle so installs from the catalog pick up the guidance; regenerated catalog.json. Wiki update (Project-Templates page) lands next via scripts/wiki.sh. 93/93 Swift + 24/24 Python tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 36 ++++++++++++++++++ .../skills/scarf-template-author/SKILL.md | 1 + .../template-author.scarftemplate | Bin 14423 -> 14610 bytes templates/catalog.json | 4 +- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 81e5c18..918bb99 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -142,6 +142,42 @@ Key services: [TemplateConfig.swift](scarf/scarf/Core/Models/TemplateConfig.swif **Schema is Swift-primary.** If `TemplateConfigField.FieldType` gains a new case, update in order: `TemplateConfig.swift` (model + validation), `tools/build-catalog.py` (`SUPPORTED_CONFIG_FIELD_TYPES` + type-specific rules), `widgets.js` (`summariseConstraint`), `TemplateConfigSheet.swift` (new control subview), tests on both sides. Schema drift between validator + installer is the kind of bug users only notice after shipping. +### Project-scoped chat + Scarf-managed AGENTS.md context (v2.3) + +v2.3 adds a per-project Sessions tab and a "New Chat" button that spawns `hermes acp` with `cwd = project.path`. Session-to-project attribution is persisted in a Scarf-owned sidecar at `~/.hermes/scarf/session_project_map.json` — the ACP wire protocol has no project-metadata hook (extra params are silently dropped), and `state.db` has no cwd column, so the sidecar is Scarf's source of truth for "which project does this session belong to?" Managed by [SessionAttributionService.swift](scarf/scarf/Core/Services/SessionAttributionService.swift); read by the per-project [ProjectSessionsView.swift](scarf/scarf/Features/Projects/Views/ProjectSessionsView.swift). + +**Giving the agent project awareness.** Hermes auto-reads a context file from the session's cwd at startup — priority order `.hermes.md` → `HERMES.md` → `AGENTS.md` → `CLAUDE.md` → `.cursorrules`, first match wins, 20KB cap. We lean on that by writing a Scarf-managed block into `/AGENTS.md` before opening the session. Service: [ProjectAgentContextService.swift](scarf/scarf/Core/Services/ProjectAgentContextService.swift). Block shape: + +``` + +## Scarf project context +_Auto-generated by Scarf — do not edit between the begin/end markers._ + +You are operating inside a Scarf project named **""**. … + +- **Project directory:** `` +- **Dashboard:** `/.scarf/dashboard.json` +- **Template:** `` v +- **Configuration fields:** `field_a`, `field_b (secret — name only, value stored in Keychain)` +- **Registered cron jobs:** `[tmpl:] ` — schedule …, currently paused|enabled +- **Uninstall manifest:** `/.scarf/template.lock.json` + +Any content below this block is template- or user-authored; preserve and defer to it. + +``` + +**Invariants.** + +- **Secret-safe.** Block surfaces field NAMES, never VALUES. A project with a Keychain-stored secret shows `api_token (secret — name only, …)`; the Keychain ref URI and any plaintext value never appear. Auditable by `refreshListsFieldNamesNotValues` in `ProjectAgentContextServiceTests`. +- **Idempotent.** Two refreshes with unchanged state produce byte-identical output. The write is skipped entirely when no delta, avoiding file-watcher churn. +- **Bounded.** Everything outside the markers is preserved on every refresh. Template-author AGENTS.md content lives safely below the block. +- **Non-fatal.** `ChatViewModel.startACPSession` calls refresh with `try?` + log — a failed write doesn't block the chat from starting; worst case is the session loses project awareness. +- **Refresh timing.** Called BEFORE `client.start()` so the block lands before Hermes's session-boot context scan. Skipping this ordering = the agent sees stale context from the previous refresh (or nothing, on fresh projects). + +**Template-author contract.** A template shipped via the catalog should include an `AGENTS.md` with the template's operational instructions. Authors leave the `` region alone — Scarf populates it at chat-start time. Everything below is template-owned and preserved. + +**Known caveat.** If any parent directory of the project contains `.hermes.md` or `HERMES.md`, those shadow the project's `AGENTS.md` (higher in Hermes's priority order). No fix in v2.3 — deferred to v2.4 pending user input on how to handle authored `.hermes.md` files. + ## Template Catalog Shipped community templates live at `templates///` (one level down — `templates/CONTRIBUTING.md` explains the submission flow for authors). The catalog site is generated from this directory and served at `awizemann.github.io/scarf/templates/` alongside the Sparkle appcast — the two coexist on the `gh-pages` branch but touch completely disjoint paths. diff --git a/templates/awizemann/template-author/staging/skills/scarf-template-author/SKILL.md b/templates/awizemann/template-author/staging/skills/scarf-template-author/SKILL.md index 1376b09..7b4e79f 100644 --- a/templates/awizemann/template-author/staging/skills/scarf-template-author/SKILL.md +++ b/templates/awizemann/template-author/staging/skills/scarf-template-author/SKILL.md @@ -397,6 +397,7 @@ Things to check before declaring the scaffold done: - [ ] `dashboard.json` has `version: 1` at the top. - [ ] `AGENTS.md` documents every config field, every updated widget, and the cron behaviour — the user relies on it as the source of truth when things drift. - [ ] **No raw URLs in field descriptions.** Use `[link text](https://…)` markdown syntax instead — raw URLs read as long unbreakable tokens in the Configuration sheet. Same rule for long paths and other unbreakable strings; wrap in `` ` `` if they must appear verbatim. +- [ ] **Leave the `` / `` region alone in the project's `AGENTS.md`.** As of Scarf v2.3, the app auto-injects a project-identity block at chat-start time (project name, directory, template id, configuration field names, cron jobs). Anything you write inside that region will be overwritten on the next chat start. Put template-specific agent instructions BELOW the block so they're preserved across refreshes. ## Reference — source of truth files diff --git a/templates/awizemann/template-author/template-author.scarftemplate b/templates/awizemann/template-author/template-author.scarftemplate index b63d1b07cd84c1e804faec864be51d1350b36c99..5112ee987a5039d46c1b47ee8898eccb4bb54a33 100644 GIT binary patch delta 8547 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 delta 8316 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