plugins/lisa-agy/skills/lisa-usage-accounting/SKILL.md
Shared usage-ledger utility for Lisa lifecycle flows and artifact writers. Delegates all direct-entry recording and rollup refreshes through one vendor-neutral contract so PRDs, tickets, evidence comments, PRs, and markdown artifacts preserve the canonical `## Lisa Usage` section instead of inventing per-flow formats.
npx skillsauth add codyswanngt/lisa lisa-usage-accountingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Single chokepoint for Lisa usage-ledger writes. Caller skills (research, plan,
implement, verify, debrief, intake, prd-source-write, tracker-write,
tracker-evidence, later rollup/monitor flows) MUST delegate usage-entry writes and
rollup refreshes through this skill rather than hand-editing artifact bodies or comments.
This skill does not define the ledger format itself. The durable schema, token order,
rewrite invariants, and rollup semantics live in the usage-accounting rule. This skill
applies that contract to real artifacts and chooses the safest writable surface.
The caller passes exactly one operation plus its arguments:
operation: record
artifact_ref: github:CodySwannGT/lisa#729
artifact_kind: github-issue
entry: { ...LisaUsageEntry fields... }
operation: rollup
artifact_ref: github:CodySwannGT/lisa#724
artifact_kind: github-issue
child_refs:
- github:CodySwannGT/lisa#729
- github:CodySwannGT/lisa#730
operation: record_and_rollup
artifact_ref: github:CodySwannGT/lisa#724
artifact_kind: github-issue
entry: { ...LisaUsageEntry fields... }
child_refs:
- github:CodySwannGT/lisa#729
Required arguments:
operation: one of record, rollup, or record_and_rollup.artifact_ref: canonical artifact identifier for the target being updated.artifact_kind: the writable host surface (github-issue, github-pr-comment, jira-ticket,
linear-issue, notion-page, confluence-page, markdown-file, or another caller-defined
host string with a matching read/write adapter).Operation-specific arguments:
record requires entry.rollup requires child_refs (empty is allowed when the caller wants a direct-only refresh).record_and_rollup requires entry and may also pass child_refs.Optional arguments:
attachment_preference: body-first (default) or comment-only.comment_ref: existing managed comment identifier when the ledger already lives in a comment.parent_artifact_ref: explicit parent for callers that need to anchor descendant rollups.existing_body: caller-supplied body snapshot when it already owns a fresh read.The entry payload MUST satisfy the canonical usage-entry contract from the rule: stable
entry_id, flow, run_id, provider/model, source semantics, token fields, pricing fields,
and artifact refs. Callers do not get to omit the "unavailable" case; when trustworthy usage is
missing they still pass an explicit entry with source: unavailable and nullable token/cost
fields.
When the runtime exposes only a trustworthy subtotal, callers MUST use source: measured-subset,
write the subtotal to measured_subset_tokens, and leave total_tokens: null. Do not coerce a
known subset into total_tokens; rollups use total_tokens only for complete totals. The
measured_subset_tokens field is optional for backward compatibility with callers that construct
ordinary observed, estimated, or unavailable entries; the shared serializer normalizes omission
to null. A trustworthy whole-run cost remains valid independently of incomplete token telemetry.
Return structured output so callers can persist or log what happened without reparsing prose:
outcome: updated | comment-fallback | no-op | blocked
artifact_ref: "github:CodySwannGT/lisa#729"
surface:
kind: body | comment
ref: "<artifact or comment identifier>"
entry_ids:
direct:
- "<entry-id>"
child:
- "<rolled-up-child-entry-id>"
rollup:
direct_tokens: 1200
child_tokens: 450
total_tokens: 1650
direct_cost: 0.42
child_cost: 0.17
total_cost: 0.59
warnings:
- "<warning text>"
error:
code: "<stable-code>"
message: "<exact failure text>"
remediation: "<next step>"
updated means the preferred writable surface was updated successfully.comment-fallback means body/description edits were unsafe, so the canonical ledger landed in a
managed comment instead.no-op means the requested operation produced byte-identical ledger output.blocked means the caller asked for a write that could not be completed; preserve the exact host
failure text.artifact_ref / artifact_kind.existing_body when present and trustworthy for this write.comment_ref, read that managed comment body too.Never guess the prior ledger state. Always start from the current managed body/comment so rewrite idempotency is preserved.
Default policy is body first:
## Lisa Usage section there.attachment_preference: comment-only, skip the body attempt and
write the managed comment directly.The fallback is part of the contract, not an error. Writers should prefer the artifact body they already own, but evidence comments, immutable PR descriptions, or size-limited hosts may require the managed comment path.
All three operations use the shared utilities and rule contract; they differ only in which inputs they require and whether they recompute child totals:
record: upsert exactly one direct usage entry on the target artifact. Rewrite the entire
## Lisa Usage section in place using the canonical serializer; never append ad hoc rows.rollup: recompute the rollup token and visible totals from the target's current direct entries
plus usage discovered from child_refs. Dedupe strictly by stable entry_id.record_and_rollup: first upsert the direct entry, then refresh totals against child_refs in
the same managed write so callers do not produce split-brain ledger states.The implementation path should use the shared utility layer (parseLisaUsageSection,
mergeLisaUsageEntries, createLisaUsageRollup, upsertLisaUsageSection) rather than duplicating
token parsing or markdown rendering in each caller.
outcome: no-op.verifyLisaUsageSectionIntegrity(<stored body>, { entryIds: <ids just written> }). A write is
successful only when that returns ok: true. The host's mutation result is not evidence — a
Linear issueUpdate returned success: true while silently discarding every entry token
(2026-08-04), which is the defect this step exists to catch.outcome: comment-fallback with a warning naming the failed
surface and the issue codes.outcome: blocked with the issue codes in
error.message. Never leave a rollup token behind whose direct_entry_ids names entries that
cannot be parsed from the same surface — restore the prior managed content rather than
reporting success over an unreadable ledger.If the host write fails, preserve the exact error text in error.message. Do not collapse write
failures into a generic "usage update failed."
usage-accounting rule.## Lisa Usage section or a second managed usage comment.source: unavailable entries.null token rollups, while trustworthy whole-run cost rolls up
independently.child_refs were not refreshed. Preserve it through ordinary direct-entry rewrites.entry_id, not by child ref count.outcome: comment-fallback so the caller can surface the
writable surface that actually holds the ledger.updated on the strength of a mutation's return value. Verification is read-back
and parse, on every surface, every write.development
Prepare a machine — a fresh laptop or a throwaway container — to run coding agents, before any repository exists. Detects which of Lisa's supported agents (Claude Code, Codex, Cursor, OpenCode, Antigravity, Copilot) are already installed, asks which credential manager the machine uses (Bitwarden, 1Password, Doppler, Vault, AWS, or none), and installs only what is missing, each by its vendor's own preferred method. Idempotent, headless by default, and emits a Dockerfile for a spin-up/spin-down environment. Run it on a new machine, in a container, or before cloning anything.
tools
Provision and verify a remote execution environment for a host project — Codex Cloud today, other remote surfaces as they are added. Generates a repository-owned setup script that installs the declared toolchain, materializes secrets through lisa-secrets-access, and runs the project's own hook. Provisions by API where one exists, by driving the vendor console where one does not, and by emitting exact config otherwise — then proves the result with the same read-back regardless of which tier did the work. Use before dispatching any work with executionEnv.
tools
Bring a developer's machine in line with the toolchain the project declares. Reports every tool in remoteEnv.tools that is missing, outdated, or unpinned for this platform, and installs the missing ones into ~/.local/bin from the same pinned, checksummed entries the remote surfaces use — but only when asked. Same manifest, same pins, same installers as lisa-setup-remote-env; what differs is consent and that the pin is a floor rather than an equality. Run it on a fresh checkout, after a manifest change, or when a tool fails at the moment of use.
tools
Route one unit of work to a remote execution surface. Reads the executionEnv parameter (local by default, codex-cloud or claude-web today), verifies the environment is provisioned and bound to this repository, submits a thin skill invocation, records the task identifier to .lisa/remote-dispatch.json, and exits without polling. Routing only — the remote runs the identical skill from the identical repository. Composable and inline: other skills invoke it via the Skill tool rather than users calling it directly.