@codyswann/lisa 2.328.2 → 2.328.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +5 -2
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/utils/usage-accounting.d.ts +42 -0
- package/dist/utils/usage-accounting.d.ts.map +1 -1
- package/dist/utils/usage-accounting.js +116 -3
- package/dist/utils/usage-accounting.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-usage-accounting/SKILL.md +16 -2
- package/plugins/lisa/rules/reference/usage-accounting.md +37 -4
- package/plugins/lisa/skills/lisa-usage-accounting/SKILL.md +16 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-usage-accounting/SKILL.md +16 -2
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/rules/reference/usage-accounting.md +37 -4
- package/plugins/lisa-copilot/skills/lisa-usage-accounting/SKILL.md +16 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/usage-accounting-reference.mdc +37 -4
- package/plugins/lisa-cursor/skills/lisa-usage-accounting/SKILL.md +16 -2
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/reference/usage-accounting.md +37 -4
- package/plugins/src/base/skills/lisa-usage-accounting/SKILL.md +16 -2
|
@@ -154,12 +154,24 @@ The implementation path should use the shared utility layer (`parseLisaUsageSect
|
|
|
154
154
|
`mergeLisaUsageEntries`, `createLisaUsageRollup`, `upsertLisaUsageSection`) rather than duplicating
|
|
155
155
|
token parsing or markdown rendering in each caller.
|
|
156
156
|
|
|
157
|
-
### Step 4 — Persist and report
|
|
157
|
+
### Step 4 — Persist, verify by read-back, and report
|
|
158
158
|
|
|
159
159
|
1. If the rendered ledger body is byte-identical to the current managed surface, return `outcome:
|
|
160
160
|
no-op`.
|
|
161
161
|
2. Otherwise write the body or managed comment through the host adapter.
|
|
162
|
-
3.
|
|
162
|
+
3. **Read the written surface back from the host and parse it.** Run
|
|
163
|
+
`verifyLisaUsageSectionIntegrity(<stored body>, { entryIds: <ids just written> })`. A write is
|
|
164
|
+
successful only when that returns `ok: true`. The host's mutation result is not evidence — a
|
|
165
|
+
Linear `issueUpdate` returned `success: true` while silently discarding every entry token
|
|
166
|
+
(2026-08-04), which is the defect this step exists to catch.
|
|
167
|
+
4. If verification fails on the body, retry the identical payload as a managed comment and verify
|
|
168
|
+
that surface the same way. Return `outcome: comment-fallback` with a warning naming the failed
|
|
169
|
+
surface and the issue codes.
|
|
170
|
+
5. If verification fails on every surface, return `outcome: blocked` with the issue codes in
|
|
171
|
+
`error.message`. **Never leave a rollup token behind whose `direct_entry_ids` names entries that
|
|
172
|
+
cannot be parsed from the same surface** — restore the prior managed content rather than
|
|
173
|
+
reporting success over an unreadable ledger.
|
|
174
|
+
6. Return the exact writable surface used, direct entry ids, rolled-up child entry ids, totals, and
|
|
163
175
|
any fallback warning.
|
|
164
176
|
|
|
165
177
|
If the host write fails, preserve the exact error text in `error.message`. Do not collapse write
|
|
@@ -179,4 +191,6 @@ failures into a generic "usage update failed."
|
|
|
179
191
|
- Never skip rollup dedupe. Child totals are keyed by stable `entry_id`, not by child ref count.
|
|
180
192
|
- Never silently drop to comments. Return `outcome: comment-fallback` so the caller can surface the
|
|
181
193
|
writable surface that actually holds the ledger.
|
|
194
|
+
- Never report `updated` on the strength of a mutation's return value. Verification is read-back
|
|
195
|
+
and parse, on every surface, every write.
|
|
182
196
|
- Never overwrite unrelated artifact body content. Rewrite only the managed usage section/comment.
|
|
@@ -80,14 +80,24 @@ cost rollups under the normal pricing and currency rules.
|
|
|
80
80
|
|
|
81
81
|
## Machine-readable tokens
|
|
82
82
|
|
|
83
|
-
Every visible direct entry row
|
|
83
|
+
Every visible direct entry row has a corresponding backward-compatible 17-field primary token:
|
|
84
84
|
|
|
85
85
|
```text
|
|
86
86
|
<!-- lisa:usage-entry entry_id=<id> flow=<flow> run_id=<run-id> provider=<provider> model=<model> source=<source> input_tokens=<n|null> cached_input_tokens=<n|null> output_tokens=<n|null> reasoning_tokens=<n|null> total_tokens=<n|null> cost=<decimal|null> currency=<code|null> pricing_status=<status> pricing_source=<ref|null> artifact_ref=<ref> parent_artifact_ref=<ref-or-empty> -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
**Entry tokens are never rendered inside a table row.** They occupy their own lines below the
|
|
90
|
+
visible table, and they correlate to their rows by `entry_id`, not by position. Hosts that
|
|
91
|
+
normalize markdown re-serialize a table from its parsed cell model and discard anything that is
|
|
92
|
+
not a cell: measured against Linear on 2026-08-04, an HTML comment trailing a table row is
|
|
93
|
+
destroyed on write while the same comment on its own line round-trips byte-identically. The
|
|
94
|
+
row-trailing layout therefore produced a ledger that reported a successful write, rendered
|
|
95
|
+
correctly for humans, and enumerated **zero** entries — with a surviving rollup token still naming
|
|
96
|
+
them. Parsing is position-agnostic and always has been, so sections written in the historical
|
|
97
|
+
row-trailing layout still enumerate, and migrate to the own-line layout on their next rewrite.
|
|
98
|
+
|
|
99
|
+
The primary token is immediately followed on the same line by a correlated measured-subset
|
|
100
|
+
extension. Writers serialize an omitted value as `null` instead of `undefined`:
|
|
91
101
|
|
|
92
102
|
```text
|
|
93
103
|
<!-- lisa:usage-entry-measured-subset entry_id=<id> measured_subset_tokens=<n|null> -->
|
|
@@ -146,7 +156,9 @@ _Managed by Lisa. Regenerated on each usage update; do not edit by hand._
|
|
|
146
156
|
|
|
147
157
|
| Flow | Model | Source | Tokens | Cost |
|
|
148
158
|
|---|---|---|---:|---:|
|
|
149
|
-
| ...human-readable rows
|
|
159
|
+
| ...human-readable rows, cells only, no tokens... |
|
|
160
|
+
|
|
161
|
+
<!-- lisa:usage-entry ... --> <!-- lisa:usage-entry-measured-subset ... -->
|
|
150
162
|
|
|
151
163
|
### Rollup
|
|
152
164
|
|
|
@@ -159,8 +171,29 @@ _Managed by Lisa. Regenerated on each usage update; do not edit by hand._
|
|
|
159
171
|
<!-- lisa:usage-rollup ... -->
|
|
160
172
|
```
|
|
161
173
|
|
|
174
|
+
Every machine-readable token sits on its own line, outside every table. One entry contributes one
|
|
175
|
+
token line; multiple entries contribute consecutive token lines in the same order as their visible
|
|
176
|
+
rows.
|
|
177
|
+
|
|
162
178
|
Writers may add host-specific surrounding prose, but they must preserve the heading, the managed-note line, the direct-entry tokens, and the single rollup token.
|
|
163
179
|
|
|
180
|
+
## Write verification
|
|
181
|
+
|
|
182
|
+
A write surface can accept a section, report success, and silently destroy part of it. **Verify
|
|
183
|
+
every managed write by reading the stored bytes back and parsing them — never by the mutation's
|
|
184
|
+
return value.** A write is successful only when the stored surface satisfies the rollup/entry
|
|
185
|
+
agreement invariant below. A caller that cannot verify a surface must fall back to one it can, or
|
|
186
|
+
fail loudly; it must never report success over an unreadable ledger.
|
|
187
|
+
|
|
188
|
+
- Every `entry_id` in the rollup's `direct_entry_ids` resolves to a parseable direct entry in the
|
|
189
|
+
same section.
|
|
190
|
+
- Every parseable direct entry in the section appears in the rollup's `direct_entry_ids`.
|
|
191
|
+
- Every entry the caller just wrote is parseable from the stored surface.
|
|
192
|
+
|
|
193
|
+
`verifyLisaUsageSectionIntegrity` in the shared utility layer implements exactly these checks and
|
|
194
|
+
returns structured issue codes (`missing-section`, `missing-entry-token`, `missing-rollup-token`,
|
|
195
|
+
`unrecorded-entry`). Callers run it against the read-back body, not against the payload they sent.
|
|
196
|
+
|
|
164
197
|
## Rollup and dedupe behavior
|
|
165
198
|
|
|
166
199
|
Rollups aggregate descendant usage from native tracker hierarchy, documented generated-work references, and explicit `parent_artifact_ref` links. Within one artifact rollup:
|
|
@@ -154,12 +154,24 @@ The implementation path should use the shared utility layer (`parseLisaUsageSect
|
|
|
154
154
|
`mergeLisaUsageEntries`, `createLisaUsageRollup`, `upsertLisaUsageSection`) rather than duplicating
|
|
155
155
|
token parsing or markdown rendering in each caller.
|
|
156
156
|
|
|
157
|
-
### Step 4 — Persist and report
|
|
157
|
+
### Step 4 — Persist, verify by read-back, and report
|
|
158
158
|
|
|
159
159
|
1. If the rendered ledger body is byte-identical to the current managed surface, return `outcome:
|
|
160
160
|
no-op`.
|
|
161
161
|
2. Otherwise write the body or managed comment through the host adapter.
|
|
162
|
-
3.
|
|
162
|
+
3. **Read the written surface back from the host and parse it.** Run
|
|
163
|
+
`verifyLisaUsageSectionIntegrity(<stored body>, { entryIds: <ids just written> })`. A write is
|
|
164
|
+
successful only when that returns `ok: true`. The host's mutation result is not evidence — a
|
|
165
|
+
Linear `issueUpdate` returned `success: true` while silently discarding every entry token
|
|
166
|
+
(2026-08-04), which is the defect this step exists to catch.
|
|
167
|
+
4. If verification fails on the body, retry the identical payload as a managed comment and verify
|
|
168
|
+
that surface the same way. Return `outcome: comment-fallback` with a warning naming the failed
|
|
169
|
+
surface and the issue codes.
|
|
170
|
+
5. If verification fails on every surface, return `outcome: blocked` with the issue codes in
|
|
171
|
+
`error.message`. **Never leave a rollup token behind whose `direct_entry_ids` names entries that
|
|
172
|
+
cannot be parsed from the same surface** — restore the prior managed content rather than
|
|
173
|
+
reporting success over an unreadable ledger.
|
|
174
|
+
6. Return the exact writable surface used, direct entry ids, rolled-up child entry ids, totals, and
|
|
163
175
|
any fallback warning.
|
|
164
176
|
|
|
165
177
|
If the host write fails, preserve the exact error text in `error.message`. Do not collapse write
|
|
@@ -179,4 +191,6 @@ failures into a generic "usage update failed."
|
|
|
179
191
|
- Never skip rollup dedupe. Child totals are keyed by stable `entry_id`, not by child ref count.
|
|
180
192
|
- Never silently drop to comments. Return `outcome: comment-fallback` so the caller can surface the
|
|
181
193
|
writable surface that actually holds the ledger.
|
|
194
|
+
- Never report `updated` on the strength of a mutation's return value. Verification is read-back
|
|
195
|
+
and parse, on every surface, every write.
|
|
182
196
|
- Never overwrite unrelated artifact body content. Rewrite only the managed usage section/comment.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.328.
|
|
3
|
+
"version": "2.328.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.328.
|
|
3
|
+
"version": "2.328.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.328.
|
|
3
|
+
"version": "2.328.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.328.
|
|
3
|
+
"version": "2.328.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.328.
|
|
3
|
+
"version": "2.328.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -75,14 +75,24 @@ cost rollups under the normal pricing and currency rules.
|
|
|
75
75
|
|
|
76
76
|
## Machine-readable tokens
|
|
77
77
|
|
|
78
|
-
Every visible direct entry row
|
|
78
|
+
Every visible direct entry row has a corresponding backward-compatible 17-field primary token:
|
|
79
79
|
|
|
80
80
|
```text
|
|
81
81
|
<!-- lisa:usage-entry entry_id=<id> flow=<flow> run_id=<run-id> provider=<provider> model=<model> source=<source> input_tokens=<n|null> cached_input_tokens=<n|null> output_tokens=<n|null> reasoning_tokens=<n|null> total_tokens=<n|null> cost=<decimal|null> currency=<code|null> pricing_status=<status> pricing_source=<ref|null> artifact_ref=<ref> parent_artifact_ref=<ref-or-empty> -->
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
**Entry tokens are never rendered inside a table row.** They occupy their own lines below the
|
|
85
|
+
visible table, and they correlate to their rows by `entry_id`, not by position. Hosts that
|
|
86
|
+
normalize markdown re-serialize a table from its parsed cell model and discard anything that is
|
|
87
|
+
not a cell: measured against Linear on 2026-08-04, an HTML comment trailing a table row is
|
|
88
|
+
destroyed on write while the same comment on its own line round-trips byte-identically. The
|
|
89
|
+
row-trailing layout therefore produced a ledger that reported a successful write, rendered
|
|
90
|
+
correctly for humans, and enumerated **zero** entries — with a surviving rollup token still naming
|
|
91
|
+
them. Parsing is position-agnostic and always has been, so sections written in the historical
|
|
92
|
+
row-trailing layout still enumerate, and migrate to the own-line layout on their next rewrite.
|
|
93
|
+
|
|
94
|
+
The primary token is immediately followed on the same line by a correlated measured-subset
|
|
95
|
+
extension. Writers serialize an omitted value as `null` instead of `undefined`:
|
|
86
96
|
|
|
87
97
|
```text
|
|
88
98
|
<!-- lisa:usage-entry-measured-subset entry_id=<id> measured_subset_tokens=<n|null> -->
|
|
@@ -141,7 +151,9 @@ _Managed by Lisa. Regenerated on each usage update; do not edit by hand._
|
|
|
141
151
|
|
|
142
152
|
| Flow | Model | Source | Tokens | Cost |
|
|
143
153
|
|---|---|---|---:|---:|
|
|
144
|
-
| ...human-readable rows
|
|
154
|
+
| ...human-readable rows, cells only, no tokens... |
|
|
155
|
+
|
|
156
|
+
<!-- lisa:usage-entry ... --> <!-- lisa:usage-entry-measured-subset ... -->
|
|
145
157
|
|
|
146
158
|
### Rollup
|
|
147
159
|
|
|
@@ -154,8 +166,29 @@ _Managed by Lisa. Regenerated on each usage update; do not edit by hand._
|
|
|
154
166
|
<!-- lisa:usage-rollup ... -->
|
|
155
167
|
```
|
|
156
168
|
|
|
169
|
+
Every machine-readable token sits on its own line, outside every table. One entry contributes one
|
|
170
|
+
token line; multiple entries contribute consecutive token lines in the same order as their visible
|
|
171
|
+
rows.
|
|
172
|
+
|
|
157
173
|
Writers may add host-specific surrounding prose, but they must preserve the heading, the managed-note line, the direct-entry tokens, and the single rollup token.
|
|
158
174
|
|
|
175
|
+
## Write verification
|
|
176
|
+
|
|
177
|
+
A write surface can accept a section, report success, and silently destroy part of it. **Verify
|
|
178
|
+
every managed write by reading the stored bytes back and parsing them — never by the mutation's
|
|
179
|
+
return value.** A write is successful only when the stored surface satisfies the rollup/entry
|
|
180
|
+
agreement invariant below. A caller that cannot verify a surface must fall back to one it can, or
|
|
181
|
+
fail loudly; it must never report success over an unreadable ledger.
|
|
182
|
+
|
|
183
|
+
- Every `entry_id` in the rollup's `direct_entry_ids` resolves to a parseable direct entry in the
|
|
184
|
+
same section.
|
|
185
|
+
- Every parseable direct entry in the section appears in the rollup's `direct_entry_ids`.
|
|
186
|
+
- Every entry the caller just wrote is parseable from the stored surface.
|
|
187
|
+
|
|
188
|
+
`verifyLisaUsageSectionIntegrity` in the shared utility layer implements exactly these checks and
|
|
189
|
+
returns structured issue codes (`missing-section`, `missing-entry-token`, `missing-rollup-token`,
|
|
190
|
+
`unrecorded-entry`). Callers run it against the read-back body, not against the payload they sent.
|
|
191
|
+
|
|
159
192
|
## Rollup and dedupe behavior
|
|
160
193
|
|
|
161
194
|
Rollups aggregate descendant usage from native tracker hierarchy, documented generated-work references, and explicit `parent_artifact_ref` links. Within one artifact rollup:
|
|
@@ -154,12 +154,24 @@ The implementation path should use the shared utility layer (`parseLisaUsageSect
|
|
|
154
154
|
`mergeLisaUsageEntries`, `createLisaUsageRollup`, `upsertLisaUsageSection`) rather than duplicating
|
|
155
155
|
token parsing or markdown rendering in each caller.
|
|
156
156
|
|
|
157
|
-
### Step 4 — Persist and report
|
|
157
|
+
### Step 4 — Persist, verify by read-back, and report
|
|
158
158
|
|
|
159
159
|
1. If the rendered ledger body is byte-identical to the current managed surface, return `outcome:
|
|
160
160
|
no-op`.
|
|
161
161
|
2. Otherwise write the body or managed comment through the host adapter.
|
|
162
|
-
3.
|
|
162
|
+
3. **Read the written surface back from the host and parse it.** Run
|
|
163
|
+
`verifyLisaUsageSectionIntegrity(<stored body>, { entryIds: <ids just written> })`. A write is
|
|
164
|
+
successful only when that returns `ok: true`. The host's mutation result is not evidence — a
|
|
165
|
+
Linear `issueUpdate` returned `success: true` while silently discarding every entry token
|
|
166
|
+
(2026-08-04), which is the defect this step exists to catch.
|
|
167
|
+
4. If verification fails on the body, retry the identical payload as a managed comment and verify
|
|
168
|
+
that surface the same way. Return `outcome: comment-fallback` with a warning naming the failed
|
|
169
|
+
surface and the issue codes.
|
|
170
|
+
5. If verification fails on every surface, return `outcome: blocked` with the issue codes in
|
|
171
|
+
`error.message`. **Never leave a rollup token behind whose `direct_entry_ids` names entries that
|
|
172
|
+
cannot be parsed from the same surface** — restore the prior managed content rather than
|
|
173
|
+
reporting success over an unreadable ledger.
|
|
174
|
+
6. Return the exact writable surface used, direct entry ids, rolled-up child entry ids, totals, and
|
|
163
175
|
any fallback warning.
|
|
164
176
|
|
|
165
177
|
If the host write fails, preserve the exact error text in `error.message`. Do not collapse write
|
|
@@ -179,4 +191,6 @@ failures into a generic "usage update failed."
|
|
|
179
191
|
- Never skip rollup dedupe. Child totals are keyed by stable `entry_id`, not by child ref count.
|
|
180
192
|
- Never silently drop to comments. Return `outcome: comment-fallback` so the caller can surface the
|
|
181
193
|
writable surface that actually holds the ledger.
|
|
194
|
+
- Never report `updated` on the strength of a mutation's return value. Verification is read-back
|
|
195
|
+
and parse, on every surface, every write.
|
|
182
196
|
- Never overwrite unrelated artifact body content. Rewrite only the managed usage section/comment.
|