CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/nanoclaw-trusted

Rules for trusted NanoClaw groups. Shared memory, session bootstrap, cross-group memory updates. Loaded for trusted and main containers only.

76

Quality

96%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

High

Do not use without reviewing

Overview
Quality
Evals
Security
Files

state-schema.mdskills/trusted-memory/

trusted-memory state schema

State written by scripts/register-session.py per jbaruch/coding-policy: stateful-artifacts. Owner skill is tessl__trusted-memory. Reader skills — jbaruch/nanoclaw-admin: tessl__heartbeat and jbaruch/nanoclaw-admin: tessl__check-email — MUST treat any unrecognised shape as "no usable prior state" and let the next owner-skill run rewrite it.

Files

/workspace/group/session-state.json

Mutable JSON object. Per-group, not shared across containers.

{
  "schema_version": 1,
  "sessions": {
    "<NANOCLAW_SESSION_NAME>": {
      "started":    "<ISO-8601 UTC, e.g. 2026-04-27T15:00:00Z>",
      "epoch":      <int unix seconds>,
      "session_id": "<sqlite session_id from /workspace/store/messages.db, or null>",
      "last_seen":  "<ISO-8601 UTC>"
    }
  },
  "session_id":       "<top-level mirror of the active session_id, back-compat>",
  "pending_response": null,
  "seen_email_ids":   [],
  "muted_threads":    {}
}

Writer / reader contract

FieldWritersReadersNotes
schema_versionregister-session.py (owner)All readers gate on thisSee Schema versioning below
sessions.<name>.*register-session.py (owner) — own session's subtreeAll readers may inspect any sessionlast_seen may be stamped by tessl__heartbeat for maintenance
session_id (top-level)register-session.py — both sessions on bootstrapLegacy readers onlyBack-compat; last-writer-wins is accepted
pending_responsedefault session writes on inbound start; default clears on send; maintenance heartbeat clears stale entriesAll trusted/main sessionsThe pending-response-tracking rule governs the protocol
seen_email_idstessl__check-email, tessl__heartbeat, tessl__morning-brief, tessl__nightly (all maintenance)tessl__check-email for de-dupAppend-only within a window
muted_threadsdefault sessiondefault + maintenancePer-thread mute map

Back-compat note (legacy migration, ex–reference_session-state-migration.md): the top-level session_id field is the pre-PR jbaruch/nanoclaw#55 shape, when only one session existed per group. It is still written so readers that haven't moved to the per-session subtree continue to work. New readers SHOULD use sessions.<name>.session_id. Old single-session files are accepted on read — register-session.py adds the sessions subtree without dropping the top-level field, so the migration is in-place and idempotent.

Other writers on this file must take fcntl.LOCK_EX on /workspace/group/session-state.json.lock for the duration of their read-modify-write cycle. Current participants: jbaruch/nanoclaw-admin: tessl__heartbeat (writes last_seen, clears stale pending_response) and jbaruch/nanoclaw-admin: tessl__check-email (writes seen_email_ids, pending_response, muted_threads). Without the shared lock, concurrent updates clobber each other.

/tmp/session_bootstrapped

Plain-text sentinel. One line: the value of $CLAUDE_SESSION_ID from the run that completed bootstrap.

needs-bootstrap.py compares this file's contents to the current $CLAUDE_SESSION_ID. Mismatch (or missing file) → bootstrap is needed. register-session.py REFUSES to write an empty sentinel because an empty value would match an empty env var on the next run and permanently suppress bootstrap.

Schema versioning

session-state.json carries schema_version: 1 at the top level. v1 is the current canonical shape: schema_version + sessions.<name> subtree + back-compat top-level session_id. Files written before this field existed are read-tolerated by register-session.py (the owner skill) and silently upgraded to v1 on the next write — owner-skill migration per jbaruch/coding-policy: stateful-artifacts.

Reader skills (jbaruch/nanoclaw-admin: tessl__heartbeat, jbaruch/nanoclaw-admin: tessl__check-email) MUST treat an unknown future version (schema_version > 1) as "no usable prior state" and let the next register-session.py run perform the upgrade — never migrate from a reader.

/tmp/session_bootstrapped is a single-line plain-text sentinel; it has no envelope shape to version. The only behavioral contract is "non-empty content = bootstrap was completed for this $CLAUDE_SESSION_ID", and that contract is stable.

/workspace/trusted/user_profile.md## Addresses block

user_profile.md is a canonical, special-case profile file with a fixed filename. It does NOT follow the general {type}_{slug}.md typed-memory naming convention in SKILL.md (e.g. user_travel-prefs.md); the travel-tile reader contract below resolves it by that exact name. It still uses type: user frontmatter, and its prose body is agent-read context like any other user file. In addition, it carries one machine-readable block that scripts parse directly — the canonical ## Addresses block. Owner skill is tessl__trusted-memory (this tile); the block is trusted-tile-owned per jbaruch/coding-policy: stateful-artifacts, and every other tile is a read-only consumer.

Shape

## Addresses
<!-- canonical, machine-read by travel tile; schema v1 — see trusted-memory state-schema.md -->
- schema_version: 1
- current_home: <current home street address>
- home_airport: <IATA code>
- new_home_wip: <new-build street address>
KeyMeaningMutability
schema_versionBlock shape version (currently 1). Bump on any shape change per jbaruch/coding-policy: stateful-artifacts.Owner-only.
current_homeThe operator's current residence — the origin every home-anchored drive leg routes from.Owner-updated. Switch to the new_home_wip value once that home is occupied.
home_airportHome IATA code (e.g. BNA).Owner-updated.
new_home_wipNew-build street address, not yet occupied.Owner-updated. Not auto-promoted to current_home — that is an explicit later edit.

The block separates the three address values that the surrounding prose conflates ("home base / new build"). Keep the prose for the agent; the block exists so script reads get an unambiguous single value per key.

Schema versioning

schema_version: 1 is the current canonical shape (current_home + home_airport + new_home_wip). Only the owner skill (tessl__trusted-memory) bumps it, and only the owner migrates the block — never a reader. Writer and reader ship through separate pipelines (writer here, reader in jbaruch/nanoclaw-travel). Coordinate bumps per jbaruch/coding-policy: stateful-artifacts:

  • Additive (backward-compatible) bumps — a new optional key — need no reader change. Bump the version, document the new key here.
  • Breaking bumps — renaming/removing current_home or changing its line shape — deploy the dual-accept reader → change the writer → drop the old shape.

A consumer that does not inspect schema_version (the current drive-planner reader does not) treats any version's - current_home: line as readable. A future consumer that gates on version MUST treat an unaccepted version as "no usable prior state" and fail closed, never guess an origin.

Writer / reader contract

FieldWriterReadersNotes
current_hometessl__trusted-memory (owner)jbaruch/nanoclaw-travel: drive-planner (read-only)Origin for home-anchored drive legs.
home_airporttessl__trusted-memory (owner)travel-tile consumers (read-only)IATA code.
new_home_wiptessl__trusted-memory (owner)deliberately ignored by drive-plannerOrigin switches are an explicit later change, never an auto-pickup.

Travel-tile reader contract (consumer-side). jbaruch/nanoclaw-travel's skills/drive-planner/home_address.py is the read-only consumer of current_home. The contract this tile guarantees: a - current_home: <address> line under a ## Addresses heading. The reader refuses to guess on a missing or malformed block — it raises an actionable error pointing back at this skill, and drive-planner's sweep fails closed (no blocks created) until the block lands. Parsing details (the match pattern, whitespace tolerance) live in that script and its docstring/tests; owner-side reformatting MUST preserve the - <key>: <value> line shape, which a nanoclaw-travel fixture pins.

README.md

tile.json