agentfootprint-lens 0.68.1 → 0.70.0

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/README.md CHANGED
@@ -1084,6 +1084,100 @@ summary card, the transport and the commentary under a native **More detail**
1084
1084
  Needs agentfootprint ≥ 9.116.0 (the release that ships `AnswerAccount` and the
1085
1085
  op) — the lens's peer floor since 0.68.0.
1086
1086
 
1087
+ ## Time — what the run took "now" to be, and which window each call read
1088
+
1089
+ **Every time decision an armed agent makes, as the record holds it.** With
1090
+ agentfootprint's time layer armed (`.time()`, 9.129.0), the run files rows on
1091
+ its honesty ledger: the clock it froze for the turn, what it read from the
1092
+ person's words, which window each call carries and how, whether a call reads
1093
+ MORE than was asked, and how far the wall clock had moved by the time the
1094
+ tool ran. `<TimeBand>` draws them; `<ContextView>` mounts it under the
1095
+ Findings band, so it moves with the one cursor.
1096
+
1097
+ ### Why
1098
+
1099
+ A time bug is quiet. "Yesterday" sent to a tool that only takes a look-back
1100
+ reads from yesterday's midnight to NOW — a day and a half, not a day — and
1101
+ the answer looks fine. After a 30-minute pause, a "last hour" look-back reads
1102
+ a different hour than the person asked about. The library records each of
1103
+ these; this band is where a person sees them: a widened fill says **wider
1104
+ than asked** with the extra ranges, a drift says `redrawn` or `shifted` and by
1105
+ how much, a result whose held range is unknown says **clock unknown**.
1106
+
1107
+ ### Mount it
1108
+
1109
+ ```tsx
1110
+ import { ContextView, TimeBand } from 'agentfootprint-lens/context';
1111
+
1112
+ <ContextView runner={recording} /> // the band appears once the ledger holds a time row
1113
+
1114
+ // or on its own, over rows you already hold:
1115
+ <TimeBand rows={state.findingsLedger} coverage={state.coverageDeclared} />
1116
+ ```
1117
+
1118
+ A paused ask with a time field (`requestInput` with `format`) shows its time
1119
+ half inside `<AwaitingPane>` — the choices with the library's labels and, on
1120
+ a re-ask, the refused value with the library's reason. A `dataset/rows`
1121
+ artifact that declares a time axis shows it above the table
1122
+ (`<TimeAxisLine meta rows>`), judged by the library: column, unit, zone,
1123
+ grain, and how many values have no known clock.
1124
+
1125
+ ### The laws it keeps
1126
+
1127
+ - **Omit, never deny.** No time row at the stop, no band — an unarmed run has
1128
+ no band, never an empty one. A row prints no field it does not carry.
1129
+ - **Never infer.** Nothing here compares two instants. `wider than asked`
1130
+ renders only on a row that carries `differs`; a drift only on a call row
1131
+ that carries `drift`; `clock unknown` only where the record says `unknown`;
1132
+ a result check only where the `period` row carries it; `settled by the
1133
+ person` only where a `time-answer` row of the turn names the mention.
1134
+ - **No sentence of its own.** Every printed string is a value off the record
1135
+ or a `TIME_LABELS` entry; the one sentence it shows — an ask's refusal
1136
+ reason — is the library's, printed as data.
1137
+
1138
+ ### One tab: `<TimeView>` (agentfootprint 9.132.0)
1139
+
1140
+ ```tsx
1141
+ import { TimeView } from 'agentfootprint-lens'; // also on 'agentfootprint-lens/context'
1142
+
1143
+ <TimeView
1144
+ rows={agent.findings()} // the ledger: time rows + period rows
1145
+ coverage={state.coverageDeclared} // optional — each call's declared period
1146
+ ask={pause} // optional — a paused ask with a time field
1147
+ assessment={await agent.assessment()} // optional — the library's standing
1148
+ />
1149
+ ```
1150
+
1151
+ It draws, in one view: the **time reasons** the library filed on the answer
1152
+ (`period-differs-from-asked`, `period-beyond-retention`, `period-not-held`,
1153
+ `period-partly-held`, `period-unknown`, `period-undeclared`,
1154
+ `derived-from-reading`, and `argument-assumed` when its witness is a period
1155
+ argument), each with a plain line and the calls it names; the **time ask**;
1156
+ and the **band**. Since 9.132.0 the band also shows the person's **answer**
1157
+ to a reading (`settled by the person` · `confirmed` / `edited` · the window
1158
+ they settled — the reading's own `open` choice is still printed as filed),
1159
+ the values the library **derived from a reading**, each call's **source
1160
+ clock** zone, and the `period` row's result checks — **differs from asked**
1161
+ (against, the range compared, what was read, `missing`, `extra`), `shifted`
1162
+ by how much, and beyond retention.
1163
+
1164
+ **The law: never compute a reason.** The standing section lists a reason
1165
+ only when the assessment you pass names it; the ledger is read only to
1166
+ resolve the library's own witness pointers to the calls they name. A period
1167
+ row that carries `differs` with no assessment passed shows the check in the
1168
+ band and no reason above it:
1169
+
1170
+ ```ts
1171
+ timeStandingOf(undefined, ledger); // undefined — nothing filed, nothing listed
1172
+ timeStandingOf(await agent.assessment(), ledger);
1173
+ // { standing: 'not-sure', reasons: [{ reason: 'period-differs-from-asked',
1174
+ // calls: [{ toolCallId: 'c1', toolName: 'client_activity' }] }, …] }
1175
+ ```
1176
+
1177
+ Headless: `foldTimeRows(ledger, coverage?)`, `answerOfReading(turn, reading)`,
1178
+ `timeStandingOf(assessment, ledger?)`, `timeAskOf(pause)`,
1179
+ `datasetTimeAxisOf(meta, rows?)`.
1180
+
1087
1181
  ## The Served tab
1088
1182
 
1089
1183
  **At every LLM call, exactly what the model was served — provable from the log.**