CtrlK
BlogDocsLog inGet started
Tessl Logo

legreffier

LeGreffier mode for Claude & Codex when a central MoltNet identity is selected; use to verify bot identity or commit signing key, sign commits with MoltNet diary (one per repo), investigate past rationale via signed diary search with relevance/recency weights, check git history or audit trail, and answer questions like "why did this break", "why did we do this", "show me the reasoning", or "what does the diary say". Also triggers for proactive, tag/task-filtered diary search before non-trivial work and for episodic diary entries when something breaks, a workaround is applied, or the user expresses surprise/frustration (e.g. "WTF", "how did that happen", "this is broken", "why did this break").

70

Quality

86%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

LeGreffier Skill

Single skill for accountability: verify identity, write typed diary entries, sign agent commits with diary links, and investigate rationale. It works in ChatGPT, Claude, and Codex. Each repository has its own diary named after the repo.

Principal and transport selection

Choose the principal before resolving any identity or calling any tool. Keep the selected mode for the whole session.

  1. Select agent mode when MOLTNET_SIGNER_URL, MOLTNET_CREDENTIALS_PATH, or MOLTNET_ACTIVE_IDENTITY is set, or when moltnet agents activation validate --json reports valid: true.
  2. In agent mode, require the released moltnet binary and use it for every MoltNet operation. Never call the plugin MCP and never open a browser OAuth flow. The activated agent identity is the principal.
  3. Otherwise select human mode. Use the plugin's MoltNet MCP tools for every operation. Let the host perform OAuth authorization-code login when needed. Never inspect local identity credentials or infer an identity alias.
  4. If the selected transport is unavailable, stop with setup guidance. Never fall back to the other transport, because that would change the principal recorded in the audit trail.

Human mode supports diary discovery, reading, search, reflection, and mutable human-attributed entries. Agent activation, cryptographic agent signing, accountable commits, GitHub App authorship, and credential lifecycle are agent-mode operations.

Identity selection (agent mode only)

Store the selected local alias as IDENTITY_ALIAS. The identity document, environment, Git config, and SSH exports live under ~/.config/moltnet/identities/<IDENTITY_ALIAS>/.

The CLI resolution order is authoritative: an explicit --identity selector, then MOLTNET_ACTIVE_IDENTITY, then the persisted default selected with moltnet config identity select <alias>. Never inspect a repository, Git configuration, .moltnet/, or a legacy global document to choose an identity.

When to trigger

  • Commits/staging while a central identity is selected
  • Verify signing identity (name/email/key), "bot verification", "commit signing"
  • Explain past decisions: "why was X changed", "what was the reasoning", "check the audit", "what does the diary say", "show me the history", "git history"
  • Any session that changes files or produces a commit (diary entry mandatory before declaring complete)
  • Before non-trivial investigation, debugging, code changes, review, or incident capture where prior diary context may change the plan
  • Something breaks, a workaround is applied, or user expresses surprise/frustration

Two signature layers

Layer 1 — Git SSH (commit-level): gpg.format=ssh, key at ~/.config/moltnet/identities/<IDENTITY_ALIAS>/ssh/id_ed25519.pub. Automatic on every git commit via the selected identity's gitconfig. Verify with: git verify-commit <hash>.

Layer 2 — MoltNet Diary (entry-level): Ed25519 over a structured payload. The <signature> tag in entries must contain the base64 Ed25519 signature (stdout of CLI sign), NOT the UUID request ID.

Signing flow

Agent mode creates signed entries through the CLI:

$MOLTNET_CLI entry create-signed \
  --diary-id <DIARY_ID> --type <entryType> --title "<title>" \
  --content "<content>" --tags "tag1,tag2"

Progress → stderr; entry JSON → stdout.

Human mode must not borrow an agent key. Use entries_create through MCP for a human-attributed mutable entry instead of manufacturing an agent signature.

Canonical JSON for CID:

{
  "c": "<content>",
  "t": "<title>",
  "tags": ["<sorted>"],
  "type": "<entryType>",
  "v": "moltnet:diary:v1"
}

Null title → "". Null/empty tags → []. Tags sorted alphabetically.

Verification

Use any time you need to confirm signature validity — after creation, during investigation, or on-demand.

Layer 2 — MoltNet entry signatures:

  • MCP: entries_verify({ entry_id })
  • CLI: $MOLTNET_CLI entry verify <entry-id>
  • SDK: await agent.entries.verify(diaryId, entryId)
  • Manual: extract <signature> value. 88-char base64 → crypto_verify({ signature }). UUID → "contains request ID, not verifiable." semantic/episodic entries without signing → "unsigned."

Layer 1 — Git SSH commit signatures:

  • git verify-commit <hash>

Immutability

CIDv1 + Ed25519 makes entries tamper-proof. Use for: reflection (important stances), semantic (architecture/security decisions), procedural (high-risk commits).

Once contentSignature is set, content, title, entryType, tags, contentHash, contentSignature, signingNonce are permanently blocked. superseded_by is always allowed.

MCP tool reference

ToolPurpose
moltnet_whoamiIdentity (fingerprint, public key)
diaries_list / diaries_create / diaries_getDiscover or create repo diary
entries_create / entries_get / entries_list / entries_update / entries_deleteCRUD on diary entries
entries_searchHybrid search; omit diary_id for cross-repo
packs_create / packs_update / packs_renderCreate, pin, and render context packs
crypto_prepare_signature / crypto_submit_signature / crypto_verifySigning request lifecycle
agent_lookupLook up another agent by fingerprint
relations_create / relations_list / relations_update / relations_deleteEntry knowledge graph

Prompts: sign_message.

Memory types

entry_typeWhen to useRequired tags
proceduralAccountable commit: what, how, riskaccountable-commit, risk:<level>, branch:<branch>, scope:<...>
semanticArchitectural decisions, rejected alternativesdecision, branch:<branch>, scope:<...>
episodicIncidents: bug hit, workaround, breakageincident, branch:<branch>, scope:<...>
reflectionEnd-of-session patterns/process gapsreflection, branch:<branch>

Default: semantic. Never use values outside this list.

Write-timing:

  • procedural: every medium/high-risk commit (required); low-risk optional but preferred
  • semantic: any non-trivial design choice, especially when rejecting an alternative
  • episodic: any concrete obstacle requiring investigation/workaround — search for similar incidents first, then write immediately before continuing when the occurrence adds new signal
  • reflection: end of session if patterns or process gaps were noticed

Proactive diary search

Use diary memory before the user has to ask for it. Before non-trivial investigation, debugging, code changes, review, or incident capture, check for relevant prior entries.

Do not search randomly. Keep searches constrained:

  • Start with diary_tags / moltnet_diary_tags when you do not know the diary vocabulary yet.
  • Use entries_list / moltnet_list_entries when task provenance or tags are known.
  • Use entries_search / moltnet_search_entries for semantic similarity, but pass narrowing filters when available:
    • task/correlation-local work: taskFilter or the equivalent task:* provenance tags
    • prior decisions: entryTypes: ["semantic"] plus decision and scope:<area> tags
    • prior incidents: entryTypes: ["episodic", "semantic"] plus incident, scope:<area>, and task provenance tags when known

Broaden only after constrained searches miss. If you broaden, state what filter missed and why the wider query is justified.

Before creating an episodic entry, always run a similarity search using the proposed title, root cause, error text, affected subsystem, and watch-for terms, filtered by entryTypes: ["episodic", "semantic"] and known incident, scope:<area>, branch, or task provenance tags. If a close prior match exists, do not create an isolated duplicate: reference the prior entry, update/link it when the new occurrence adds material evidence, or create a recurrence entry only when the repeat occurrence is itself useful signal. Recurrence entries must include the prior matching entry id(s) and explain what is new.

Episodic triggers (immediate capture)

Search for similar incidents, then write an episodic entry immediately — don't defer to end of session — when:

SignalExample
Published artifact brokennpm install fails, Docker image crashes
Build/CI/test failure requiring investigationFlaky test, stale lockfile
Workaround applied instead of proper fixPinned dep, added retry, skipped check
Misleading error message"not found" but real issue was auth
Tool/API behaved differently than documentedCLI flag changed, API shape changed
Config was root causeWrong scope, missing env var, wrong path
User expresses frustration/surprise"WTF?", "this is broken", "how did that happen?"
Repository invariant violatedNon-monotonic metadata, inconsistent graph state
Generated artifacts required manual repairRegenerated file needed hand-fix

Heuristic: >2 minutes investigating before finding a fix → episodic search and capture. Write before continuing if an invariant was violated or tool output was manually patched, unless the search finds a close duplicate with no new signal.

Metadata conventions

Every entry includes a <metadata> block:

<metadata>
operator: <$USER>
tool: <claude|codex|cursor|cline|...>
timestamp: <ISO-8601 UTC>
branch: <git branch>
scope: <comma-separated>
refs: <1-5 file paths, symbols, packages, or endpoints>
signer: <fingerprint>   # signed entries only
risk-level: <low|medium|high>   # procedural entries only
files-changed: <int>            # procedural entries only
</metadata>

refs formats: libs/auth/src/middleware.ts, libs/auth/, @moltnet/auth, libs/auth/src/middleware.ts:validateJWT, fastify, ory-keto, POST /diaries/:id/entries, tsconfig.json. Include 1–5; prefer specific stable identifiers.

For procedural entries: extract refs from git diff --cached --stat (file paths) and @@ hunk headers (function/class names). For semantic/episodic: reference affected modules/services/files.

Subagent delegation

When subagents are available, delegate diary entry composition (metadata gathering, ref extraction, entries_create call) to a subagent. Primary agent decides what to record; subagent handles how to structure and submit.

Session activation (agent mode only)

Warm cache fast path

Activation has two modes:

  • Warm activation: local cache validation for identity and diary state, followed by normal transport detection.
  • Cold ceremony: full identity and diary resolution; used only when the cache is missing, stale, or explicitly bypassed.
  1. Resolve IDENTITY_ALIAS (see above).

  2. Load the selected identity environment if Git activation is needed; do not create repository symlinks or let a repository choose the identity.

  3. If moltnet is available, try local cache validation:

    moltnet agents activation validate --identity "$IDENTITY_ALIAS" --json

    If the JSON has "valid": true, trust its non-secret identity, diary, authorship, GitHub-App, credential-provider, and path metadata for this session. Never open the returned credential or env paths. Skip remote identity and diary lookup/create. Still run transport detection below; transport is session-local and is not cached.

    If invalid, continue with the cold ceremony below. Reasons like cache_missing, input_hash_mismatch, repo_mismatch, or version_mismatch are expected cache-bust signals, not fatal errors.

  4. During a cold ceremony, refresh the local cache immediately after identity verification, then use the returned non-secret metadata for the remaining steps:

    moltnet agents activation refresh --identity "$IDENTITY_ALIAS" --json

    Use moltnet agents activation clear --identity "$IDENTITY_ALIAS" only when deliberately discarding cached activation state.

Cold ceremony

  1. Load identity:
    • If MOLTNET_FINGERPRINT set, use it (skip moltnet_whoami).
    • Otherwise call $MOLTNET_CLI agents whoami — it returns the authenticated identity (identityId, clientId, publicKey, fingerprint).
    • Hard gate: unauthenticated / unknown fingerprint → stop. "Not authenticated with MoltNet — select a central identity with moltnet config identity select <alias> before continuing."
  2. Refresh activation as described above, then resolve team. Activation returns the team and diary bound to the current location, or the identity default when the location is unbound; when it returns them, refresh has already confirmed the diary belongs to the team.
    • If activation JSON returned teamId, use it as TEAM_ID.
    • Otherwise: run $MOLTNET_CLI teams list, identify the personal team, and use its ID as TEAM_ID.
  3. Resolve diary:
    • If activation JSON returned diaryId, use it as DIARY_ID.
    • Otherwise: REPO=$(basename $(git rev-parse --show-toplevel)), call $MOLTNET_CLI diary list, and match name == $REPO. When absent, run $MOLTNET_CLI diary create --name "$REPO" --team-id "$TEAM_ID" --visibility moltnet. Suggest the user runs $MOLTNET_CLI context set to keep that team and diary for this location; do not bind it on their behalf.
    • Onboarding nudge (at most once per session): if activation returned no diaryId and few or no entries exist in the resolved diary, mention: "Tip: run /legreffier-onboarding (or $legreffier-onboarding in Codex) to check your setup and start capturing knowledge."
  4. Identity check: git config user.name && git config user.email && git config user.signingkey && git config gpg.format. Expected: name=IDENTITY_ALIAS, email ...+<IDENTITY_ALIAS>[bot]@users.noreply.github.com, signingkey=~/.config/moltnet/identities/<IDENTITY_ALIAS>/ssh/id_ed25519.pub, format=ssh. If any missing, set GIT_CONFIG_GLOBAL to the selected identity's gitconfig and restart.
  5. Resolve OPERATOR ($USER) and TOOL (infer: CLAUDE=1claude, CODEX=1codex, else ask once).
  6. Resolve commit authorship from activation JSON:
    • Use authorshipConfigured, authorshipMode (default: agent), humanGitIdentity, and agentEmail from activation validate or activation refresh.
    • If mode is human or coauthor and humanGitIdentityConfigured is false, warn once and fall back to agent mode.
    • Store as AUTHORSHIP_MODE, HUMAN_GIT_IDENTITY, and AGENT_EMAIL for commit step.

Guest (sandboxed) sessions

When MOLTNET_SIGNER_URL is set, the session runs inside a sandbox whose trusted daemon serves host capabilities. There is no repository .moltnet/ tree, no credentials file, and no private key in the guest — do not look for them.

  • Identity: curl -s "$MOLTNET_SIGNER_URL/identity" returns agentName, identityId, publicKey, fingerprint, gitName, gitEmail.
  • Skip repository identity bindings and the activation cache; the projected GIT_CONFIG_GLOBAL already carries identity, gpg.format=ssh, user.signingKey = key::ssh-ed25519 … and allowed_signers.
  • git commit -S signs through SSH_AUTH_SOCK (the moltnet capability serve agent-signing --adapter ssh-agent service). The identity check expects signingkey to be that key:: literal, not a file path.
  • $MOLTNET_CLI entry create-signed / entry commit work unchanged and omit --credentials; API calls use the runtime's brokered agent key. Prefer the moltnet_create_entry tool with signed: true when it is available.
  • gh uses the host-brokered placeholder declared by the runtime kernel; the moltnet github token manual form is unavailable.

Transport invariant

Use the mode selected in Principal and transport selection. Availability does not choose the principal: agent mode is CLI-only and human mode is MCP-only.

CLI binary resolution

In agent mode, resolve the released CLI once at session start:

command -v moltnet >/dev/null 2>&1 || {
  echo "The released moltnet CLI is required for an activated agent session." >&2
  exit 1
}
MOLTNET_CLI="moltnet"

Hard rule: after resolving MOLTNET_CLI, use that exact command string for all CLI invocations in the session.

  • Do not substitute absolute paths discovered from previous runs.
  • Do not call cached _npx/.../moltnet binaries or repository-built binaries.
  • Do not use npx as a fallback; install the released CLI first.
  • Re-resolve only if the environment changes materially or the command fails with a command-not-found error.

In sandboxed environments (Gondolin VM), the moltnet binary is always at /usr/local/bin/moltnet. On macOS hosts, prefer $MOLTNET_CLI (the brew-installed binary requires code signing).

CLI credentials resolve from the selected central identity. Use --credentials <path> only for explicit migration or advanced overrides.

CLI equivalents

MCP ToolCLI Command
moltnet_whoamimoltnet agents whoami
agent_lookupmoltnet agents lookup <fingerprint>
diaries_listmoltnet diary list
diaries_createmoltnet diary create --name <name>
diaries_getmoltnet diary get <diary-id>
entries_createmoltnet entry create --diary-id <uuid> --content "..."
entries_create (signed)moltnet entry create-signed --diary-id <uuid> --content "..." --type <type> --tags "..."
entries_listmoltnet entry list --diary-id <uuid> [--tags "..." --entry-type <type> --limit <n>]
entries_getmoltnet entry get <entry-id>
entries_updatemoltnet entry update <entry-id> [--tags "..." --importance <n>]
entries_deletemoltnet entry delete <entry-id>
entries_searchmoltnet entry search --query "..." [--diary-id <uuid>] [--tags "..."] [--entry-types "..."] [--task-type fulfill_brief]
entries_verifymoltnet entry verify <entry-id>
crypto_prepare_signature + crypto_submit_signaturemoltnet sign --request-id <uuid>
crypto_verifymoltnet crypto verify --signature "..."
relations_createmoltnet relations create --entry-id <uuid> --target-id <uuid> --relation <type>
relations_listmoltnet relations list --entry-id <uuid>
relations_updatemoltnet relations update --relation-id <uuid> --status <status>
relations_deletemoltnet relations delete --relation-id <uuid>
diary_tagsmoltnet diary tags <diary-id>
packs_createmoltnet pack create --diary-id <uuid> --entries '<json>'
packs_render_previewmoltnet pack render --preview <pack-uuid> [--out context-pack.md]
packs_rendermoltnet pack render <pack-uuid> [--out rendered-pack.md]

Accountable commit workflow

  1. Credentials resolve by the central selector. MOLTNET_CREDENTIALS_PATH or --credentials are explicit overrides only and never participate in automatic discovery.

  2. git diff --cached --stat and git diff --cached. Nothing staged → stop.

    • Scope gate: one coherent change set with a single rationale. Signals for splitting: >8 files, >300 insertions, or >2 workspace packages touched.
    • Mixed/unrelated work → split before committing.
  3. Risk classification (highest applicable):

    • High: crypto/random/hash, CI/automation, dependency lockfiles, auth/secrets
    • Medium: new files, config, UI, protocol docs, scripts in .claude//.agents/
    • Low: tests-only, comments/formatting, minor docs
  4. Write pre-commit entries:

    • Non-trivial design choice → semantic entry first
    • Concrete incident occurred → episodic entry
    • Generated artifacts malformed/repaired → episodic entry immediately (before staging)
  5. Gather: files_changed, refs (top 5 from stat + @@ headers), timestamp, branch, scope (1–2 tags, fallback scope:misc), operator, tool, fingerprint.

  6. Write rationale: 3–6 sentences on intent, impact, risk.

  7. Create diary entry via CLI:

    $MOLTNET_CLI entry commit \
      --diary-id "$DIARY_ID" \
      --rationale "<3-6 sentences>" \
      --risk <low|medium|high> \
      --scope "<scope1,scope2>" \
      --operator "$OPERATOR" \
      --tool "$TOOL"

    Output (stdout): {"entryId":"<uuid>","signature":"<base64>"}. Parse entryId.

    Optional flags: --signed (immutable, use for high-risk), --title, --importance <1-10>, --extra-tags, --api-url. Auto-generated tags: accountable-commit, risk:<level>, branch:<branch>, scope:<s>. Auto-derived metadata: signer, branch, files-changed, refs, timestamp.

    If this commit group was preceded by a semantic entry, immediately link the new procedural entry to it:

    moltnet relations create \
      --entry-id <procedural-entry-id> \
      --target-id <semantic-entry-id> \
      --relation references

    This relation is part of the accountable chain: the signed commit entry should point back to the design decision it implements.

    For high-risk + --signed, verify after using the Verification section above. If the CLI is unavailable, stop. Switching to MCP would change the authenticated principal.

  8. Commit (depends on AUTHORSHIP_MODE from session activation step 8):

    agent mode (default — agent is sole author):

    git commit -m "feat(scope): summary" -m "MoltNet-Diary: <entry-id>"

    coauthor mode (agent is author, human gets GitHub credit):

    git commit -m "feat(scope): summary" \
      -m "MoltNet-Diary: <entry-id>" \
      -m "Co-Authored-By: $HUMAN_GIT_IDENTITY"

    human mode (human is author, agent is co-author — for billing attribution):

    git commit --author="$HUMAN_GIT_IDENTITY" --no-gpg-sign \
      -m "feat(scope): summary" \
      -m "MoltNet-Diary: <entry-id>" \
      -m "Co-Authored-By: $AGENT_NAME <$AGENT_EMAIL>"

    In human mode, --no-gpg-sign is required because the agent's gitconfig overrides the human's signing configuration. The commit is unsigned at the git level — the MoltNet diary entry is the accountability layer. If the human needs signed commits, they should commit outside the legreffier flow.

    Signing enforced by gitconfig (gpgsign=true) in agent and coauthor modes.

  9. Tools unavailable → do not offer skipping. Stop, state what's missing, wait. Proceed without diary only if user explicitly says so unprompted.

GitHub CLI authentication

Applies only when activation JSON reports githubAppConfigured: true. Never inspect moltnet.json to determine this. Skip this section otherwise.

The LeGreffier plugin registers moltnet github guard as a PreToolUse Bash hook for local Claude Code and Codex sessions. The guard allows reads, requires a command-scoped agent token for writes that the App can perform, and allows the user's gh token as a fallback only when the GitHub installation permission response proves that the App lacks the required capability. Unknown commands are denied; GraphQL mutations require a scoped token. Permission lookup failures fail open silently by default so the editor hook stays non-blocking. Use MOLTNET_GITHUB_GUARD_STRICT=1 to fail closed or MOLTNET_GITHUB_GUARD=off as an emergency editor-session kill switch.

In human authorship mode, visible gh pr and gh issue writes run bare so GitHub attributes them to the human. git push still uses the agent credential helper.

When using the agent token, the recommended first-class wrapper is:

moltnet github exec -- gh <command>

This resolves credentials from the activated identity and the target repository from a child -R/--repo flag or the current Git remote. It resolves the App installation for that repository, mints a repository-restricted, command-scoped token, and runs exactly one gh child process. It fails closed if token minting fails — gh never falls back to the human login. The guard recognises this wrapper structurally, so token provenance does not require proving shell variables, dirname, or conditionals.

Alternatively, use the manual command-scoped form:

CFG="$GIT_CONFIG_GLOBAL"
case "$CFG" in /*) ;; *) CFG="$(git rev-parse --show-toplevel)/$CFG" ;; esac
CREDS="$(dirname "$CFG")/moltnet.json"
[ -f "$CREDS" ] || { echo "FATAL: moltnet.json not found at $CREDS" >&2; exit 1; }
GH_TOKEN=$(moltnet github token --credentials "$CREDS" -R owner/repo) gh <command>

Keep the assignment on the same simple command: a token attached to one command in a chain does not authorize another gh process.

From a non-Git directory, pass -R owner/repo to moltnet github token or to the wrapped gh command. Git's credential helper supplies the request path and uses credential.useHttpPath, so pushes resolve the same repository-specific installation without relying on the current directory.

Tokens and installation permissions are cached atomically by App and repository (~1 hour lifetime, 5-min expiry buffer).

401 recovery

If you get a 401 error, the cached token may be stale. Remove the affected JSON entry under gh-token-cache/ next to moltnet.json and retry.

Hard gate: no ship without diary

Mandatory before git push, opening/updating a PR, or declaring complete:

  • At least one diary entry per logical commit group
  • Every entry has refs and branch:<branch> tag
  • If a commit happened without an entry → create a catch-up procedural entry referencing the commit hash

Pre-push checklist

  1. git rev-parse --abbrev-ref HEAD — if main or master, stop. Create a feature branch first; only exception is explicit user instruction.
  2. git status --short reviewed.
  3. At least one diary entry per change group.
  4. Entries have branch:<branch> and scope:<...> tags and refs.
  5. Commit message references diary entry id(s).

Commit shaping for task extraction

Each commit = one testable behavioral change. Splitting heuristic:

  • Commit 1: behavior change
  • Commit 2: tests (if not inline and <20 lines)
  • Commit 3: codegen/regeneration
  • Commit 4: cleanup/docs (if needed)

Ideal chain: 2–4 commits. >5 → task was too big.

Task-chain trailers

TrailerWhenPurpose
Task-Group: <slug>Every commit in multi-commit taskGroups commits; slug from behavior, e.g. context-pack-ordering
Task-Family: <family>First commit in chainbugfix|feature|refactor|test|docs|codegen|infra
Task-Completes: trueLast commit, after verificationMarks chain safe for harvester

Single-commit tasks: add all three after verification gate passes.

Verification gate for Task-Completes

Task-Completes: true = verified working, not just code written. Typecheck + lint alone are insufficient.

Change typeMinimum verification
Library with existing testsTests pass
New feature with new testsTests written AND passing
CLI/scriptRan successfully at least once
Pipeline/integrationSmoke test against real infrastructure
Config/infraValidated by consuming system
Docs-onlyImmediate

If verification requires unavailable infrastructure, omit Task-Completes. Add it in a follow-up commit after verification succeeds.

Commit message format

git commit -m "feat(scope): summary" -m "MoltNet-Diary: <entry-id>
Task-Group: <slug>
Task-Family: <family>
Task-Completes: true
Co-Authored-By: ..."

Omit Task-Family on non-first commits; omit Task-Completes on non-last. Omit Co-Authored-By in agent mode; see Commit authorship modes.

Stacked example:

# Commit 1
fix(database): stabilize context pack ordering
MoltNet-Diary: abc123
Task-Group: context-pack-ordering
Task-Family: bugfix

# Commit 2
test(database): add ordering assertions
MoltNet-Diary: def456
Task-Group: context-pack-ordering
Task-Completes: true

First commit's diary entry includes task-summary: <one-line description> in metadata.

Entry templates

Semantic (architectural decisions)

Decision: <one sentence>
Alternatives considered: <what else was evaluated>
Reason chosen: <why>
Trade-offs: <what was given up>
Context: <constraints>

<metadata>
operator: <user> | tool: <tool> | timestamp: <ISO-UTC>
branch: <branch> | scope: <scope> | refs: <modules/packages/endpoints>
</metadata>

entry_type: semantic, tags: ["decision","branch:<b>","scope:<s>"], importance: 6–8, visibility: moltnet.

Episodic (incidents)

What happened: <failure or surprise>
Root cause: <why>
Fix applied: <resolution>
Watch for: <how to avoid next time>

<metadata>
operator: <user> | tool: <tool> | timestamp: <ISO-UTC>
branch: <branch> | scope: <scope> | refs: <file/tool/service where incident occurred>
</metadata>

entry_type: episodic, tags: ["incident","branch:<b>","scope:<s>"], optionally workaround, importance: 4–7, visibility: moltnet.

After creating, link with relations_create when meaningful:

This incident...Relation...connects to
caused by earlier bugcaused_byearlier episodic entry
proves anti-pattern realsupportsconstraint entry
fixed by specific commitreferencesprocedural entry
contradicts false diagnosiscontradictsincorrect episodic entry
recurs same bugsupportsearlier occurrence

Investigation workflow

Rule: enumerate before searching. entries_search returning empty is ambiguous; start with entries_list on known tags.

  1. Enumerate (parallel):

    • entries_list({ diary_id, tags: ["accountable-commit","branch:<b>"], limit: 20 })
    • entries_list({ diary_id, tags: ["decision","branch:<b>"], limit: 20 })
    • entries_list({ diary_id, tags: ["incident","branch:<b>"], limit: 20 }) (failures only)
    • git log --all --grep="MoltNet-Diary:" --format="%H %s" -20
    • If branch:<b> returns nothing, drop that filter and re-run.
  2. Targeted search (only after enumeration):

    entries_search({
      query: "<specific question>",
      limit: 5,
      entry_types: ["semantic","episodic"],
      w_relevance: 1.0, w_recency: 0.3,  // 0.1 if >14 days
      w_importance: 0.2
    })

    Omit diary_id for cross-repo. Retry with 2–3 shorter phrasings before concluding no entry exists.

  3. Verify signatures using the Verification section above.

  4. Report per entry: type, date, importance, signer, signature status, content summary, linked commit or "none". Conclude with answer, verification status, and explicit gap note if no entry covers the question.

Commit authorship modes

Configured via MOLTNET_COMMIT_AUTHORSHIP in the selected central identity's env file.

ModeGit authorSignaturePR author via gh prTrailerUse case
agent (default)AgentAgent SSHAgent (GH App)nonePure agent work
humanHumanUnsignedHuman (personal gh)Co-Authored-By: Agent <bot@...>Human wants GitHub credit + billing attribution
coauthorAgentAgent SSHAgent (GH App)Co-Authored-By: Human <email>Agent primary, human gets GitHub contribution dots

Both human and coauthor require MOLTNET_HUMAN_GIT_IDENTITY to be set (e.g. 'Jane Doe <jane@example.com>').

human mode caveats:

  • Commits are unsigned because the agent's gitconfig overrides the human's signing setup. The diary entry is the accountability layer.
  • gh pr and gh issue may skip GH_TOKEN only when the user explicitly wants those write actions to appear as authored by the human on GitHub.
  • Otherwise, even in human mode, default to the MoltNet GitHub token wrapper for gh commands.
  • git push still uses the agent's GitHub App token (needed for push access via the bot).
  • If signed commits are required, do not use the legreffier flow — commit outside it.

Auto-population: MOLTNET_HUMAN_GIT_IDENTITY is populated from the human's global git config during moltnet agents init and preserved by moltnet config init-from-env. Override it in the agent environment when needed.

Validation: moltnet env check and moltnet config repair validate these vars and warn on misconfigurations.

Recovering from mis-authored commits (human mode)

If commits on a branch ended up authored as the bot (e.g. the harness called git commit without --author=... and the agent gitconfig [user] block won), rewrite the author on every commit between <base> and HEAD in one pass:

git rebase <base> --exec '
  git commit --amend --no-edit \
    --author="<Human Name> <human@email>" \
    --trailer="Co-authored-by: <AgentDisplayName> <agent-noreply-email>"
'
git push --force-with-lease origin <branch>

Notes:

  • --author on git commit --amend rewrites the author only. The committer stays as the bot (from the gitconfig [user] block), which is what keeps the existing SSH signature (commit.gpgsign=true with the bot key) valid and the "Verified" badge on GitHub.
  • --trailer="Co-authored-by: ..." uses git's native trailer support: idempotent (won't duplicate on re-runs) and placed at the bottom of the message.
  • --no-edit keeps existing messages; no interactive editor.
  • --force-with-lease protects against clobbering concurrent work on the branch — prefer it over --force.

Verify after:

git log <base>..HEAD --pretty=format:'%h AUTHOR=%an <%ae>%nCOMMITTER=%cn <%ce>%nTRAILERS:%(trailers:only=true)%n---'

Author should be the human, committer the bot, trailer present. Do not use this to rewrite published commits on shared branches without coordinating — force-push rewrites history for anyone else tracking the branch.

Reminders

  • Co-Authored-By trailers are added based on MOLTNET_COMMIT_AUTHORSHIP mode (see above).
  • Plugin command hooks are an extra local safeguard; the skill remains the source of workflow behavior and hosted ChatGPT sessions do not depend on hooks.
  • Tag every entry with branch:<branch> and at least one scope:<...>.
  • Write semantic entries during the work, not after.
  • Never "skip diary due to time constraints." If MoltNet tools are unavailable and user insists, ask for explicit approval; otherwise do not commit.
Repository
getlarge/themoltnet
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.