Compare commits

..

8 Commits

Author SHA1 Message Date
Gud Boi 7c8c1c4cb6 Merge pull request 'moar_ai_skillz' (#93) from moar_ai_skillz into main
Reviewed-on: #93
2026-10-07 07:06:04 +00:00
Gud Boi 45d0f003fc Move Piker skills to `.agents` discovery
- keep repository-owned skill sources provider-neutral
- retain Claude discovery through portable relative links
- drop tracked local settings and the superseded style guide

Prompt-IO: ai/prompt-io/opencode/20260908T043134Z_f148fbcc_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-09-08 00:35:01 -04:00
Gud Boi f148fbcc23 Add neutral `.ai` workflow config
Select the provider-neutral backend and port repo-owned commit-msg
and test-harness refs into `.ai`.

Also,
- ignore local `.agents` links and generated runtime state.
- retain legacy Claude archives for recovery.
- record Prompt-IO provenance for the migration.

Prompt-IO: ai/prompt-io/opencode/20260907T214000Z_9115d24_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-09-07 19:07:00 -04:00
Gud Boi 00e7ca45f6 Refresh `ai.skillz` provider deployment
Move managed worktree ignores to the provider-neutral `/wkts/` root
and remove obsolete `commit-msg` session state.

Add `code-nav-refs` links and the remaining OpenCode command shims so
both provider deployments validate against the current manifest.

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-23 19:59:15 -04:00
Gud Boi 4880f0d3c6 Deploy cross-provider AI skills
Replace the tracked global `commit-msg` symlink with ignored local
deployments for the complete Claude and OpenCode skill sets.

Add OpenCode command shims for review, commit, test, PR, Taken, and
session-cleaning workflows while preserving repository-local runtime
artifacts.

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-12 14:37:44 -04:00
Gud Boi 7b7ecb6747 Add `skills/commit-msg/conf.toml` to `.gitignore`
(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-03-27 12:09:45 -04:00
Gud Boi 899e3ed992 Symlink `commit-msg` SKILL.md to global skill
Replace the repo-local 84-line `SKILL.md` with a
symlink to `~/.claude/skills/commit-msg/SKILL.md`
so the skill definition is maintained in one place
across all repos.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-03-27 12:09:45 -04:00
Gud Boi e9cf1d7379 Move commit-msg output to `msgs/` subdir
Relocate generated commit message files from
`.claude/` root into `.claude/skills/commit-msg/msgs/`
and switch timestamp format to filesystem-safe UTC
(`%Y%m%dT%H%M%SZ`).

Also,
- add `msgs/` dir and `git_commit_msg_LATEST.md` to
  `.gitignore`.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-03-17 21:18:05 -04:00
237 changed files with 3263 additions and 22740 deletions

View File

@ -1,174 +0,0 @@
---
name: piker-clearing-expert
description: >
Piker clearing, EMS/order-control, accounting, position, and
trade-ledger expertise. Apply when changing or debugging Order,
Status, Brokerd* protocols, live or paper fills, dark orders,
order IDs, TransactionLedger persistence, Account/Position/PPU,
FQME/bs_mktid identity, SymbologyCache lookups, or broker trade
normalization.
compatibility: >
Requires a piker checkout and familiarity with Python, trio,
tractor, msgspec Structs, and backend-specific trading APIs.
metadata:
author: goodboy
version: "1.0"
---
# Piker Clearing Expert
Use this mental model before touching order control or accounting:
```text
OrderClient / UI
-> emsd routes intent and owns order-dialog state
-> live brokerd OR paperboi executes and reports events
-> executing backend owns fill-to-accounting integration
-> emsd translates and broadcasts broker events
-> UI consumes order state and position summaries
```
The EMS is not the trade ledger. It correlates IDs, runs dark
predicates, and relays lifecycle events. Paper and accounting-aware
live backends may normalize fills into transactions, update local
ledger/account state, and emit `BrokerdPosition` summaries. Inspect
each live backend; this integration is not uniform.
## Runtime ownership
- `OrderClient` owns client intent and local sent-order tracking.
- `emsd` owns `Router`, `DarkBook`, active `Status` dialogs,
subscribers, and `oid <-> reqid` correlation.
- `brokerd.<broker>` owns credentialed live order control.
- `paperboi.<broker>` owns simulated execution and paper accounting.
- `TransactionLedger` owns trade-record persistence, not order state.
- `Account` owns positions keyed by backend-system market identity.
- UI `Position.update_from_msg()` is a summary reset, not durable
transaction accounting.
For daemon placement, context streams, cancellation, and actor-local
state, also load `piker-conc-expert`.
## Event lifecycle
1. A client sends `Order` or `Cancel` through `OrderClient`.
2. `process_client_order_cmds()` creates or updates EMS `Status`.
3. EMS routes a `BrokerdOrder` or stores a dark trigger predicate.
4. The executing backend acknowledges with `BrokerdOrderAck`.
5. EMS records the current `oid <-> reqid` relation.
6. Accepted, ack-correlated status/fill events become client updates.
7. The backend integrates fills into accounting when supported.
8. A resulting `BrokerdPosition` is relayed through EMS to clients.
Cancellation may arrive before acknowledgement. Preserve
`Status.cancel_called`; once the ack supplies `reqid`, EMS can issue
the deferred `BrokerdCancel`.
## Identifier namespaces
Never substitute one namespace merely because two values happen to
match in a backend:
| ID | Owner and invariant |
|---|---|
| `oid` | Stable client/EMS order-dialog ID across submit, modify, cancel |
| `reqid` | Backend order-control ID established by an ack; it may change |
| venue order ID | Native API identity; may differ from both IDs above |
| `tid` | Stable clear ID used to deduplicate position events and TOML keys |
| `fqme` | Piker-normalized market address and symcache lookup key |
| `bs_fqme` | FQME without its final broker suffix |
| `bs_mktid` | Backend-system market key and `Account.pps` key |
Normalize every durably persisted `tid` to a stable string. Although
`Transaction.tid` permits integers, TOML mapping keys do not.
Paper transactions commonly set `Transaction.bs_mktid` to the full
FQME. The embedded `Position.mkt.bs_mktid` can still retain the
provider-native market ID. Check the concrete object and table owner
before asserting key equality.
## Accounting invariants
- `Transaction.size` is signed; preserve side semantics during
broker normalization.
- `Transaction` is the normalized in-memory interchange. Live ledger
records may remain backend-native and normalize through
`mod.norm_trade()` when read.
- `Position._events` is keyed by `tid`; `add_clear()` is the
idempotence boundary.
- `Position.ppu` and `Position.cumsize` are derived from transaction
events, not independent mutable truth.
- Normalized accounting transactions need a stable, non-null
`bs_mktid`; `Account.pps` uses it as the position key.
- `Account.update_from_ledger()` resolves market metadata from
`SymbologyCache.mktmaps` or its explicit fallback table.
- UI position messages are projections. Do not feed their synthetic
reset event back into durable broker accounting.
## Persistence contracts
Trade ledgers live under the accounting ledger directory as
`trades_<broker>_<account>.toml`. Top-level keys are transaction IDs;
record schemas are backend-specific unless the paper engine wrote a
normalized transaction dictionary.
`open_trade_ledger()` writes on context exit when its data comparison
detects a change or `rewrite=True`. Its snapshot is shallow, so nested
in-place record mutation can evade dirty detection. Explicit writes can
also fail inside fill handlers. Treat all persistence points as part of
the live execution path.
Accounts persist active positions. `dump_active()` separates open and
net-zero positions. Do not assume `minimized_clears()` safely preserves
size/PPU: current sign-transition and longer net-zero slicing lacks
round-trip coverage and can retain the wrong event subset.
## Market identity and symcache
`SymbologyCache` has three distinct key-addressed mappings:
- `assets`: provider asset ID to `Asset`;
- `pairs`: native `bs_mktid` to backend pair `Struct`;
- `mktmaps`: searchable FQME or explicit alias to normalized
`MktPair`.
Search mapping keys, then resolve values. RapidFuzz treats mapping
values as choices; passing `mktmaps` directly makes it operate on
`MktPair` objects. Preserve in-memory aliases because IB can store both
native IDs and FQMEs for one `MktPair`. Do not persist such aliases
without fixing reload: `from_dict()` currently requires every key to
equal `mkt.fqme`.
## Change workflow
Before editing:
1. Identify the owning layer: client, EMS, executor, accounting, or UI.
2. Write down every ID/key transition across that boundary.
3. Trace both normal and cancel-before-ack event ordering.
4. Determine whether records are native, normalized, or summaries.
5. Check actor-local caches and context-exit writes.
6. Add a deterministic regression at the narrowest broken contract.
7. Run live/backend tests only when their credentials and side effects
are explicitly authorized.
Do not fix an accounting defect by adding state to EMS, or fix an EMS
correlation defect by rewriting durable transaction history.
## Canonical source map
- `piker/clearing/_messages.py`: client and brokerd protocol types.
- `piker/clearing/_client.py`: `OrderClient` and `open_ems()`.
- `piker/clearing/_ems.py`: router, dark book, ID mapping, translation.
- `piker/clearing/_paper_engine.py`: simulated execution/accounting.
- `piker/accounting/_ledger.py`: transactions and ledger persistence.
- `piker/accounting/_pos.py`: positions, accounts, PPU event state.
- `piker/accounting/_mktinfo.py`: `Asset`, `MktPair`, FQME schema.
- `piker/data/_symcache.py`: provider symbology mappings and search.
- `piker/accounting/calc.py`: transaction ordering and PPU/PnL math.
- `piker/brokers/*/broker.py`: backend order-control integration.
- `piker/brokers/*/ledger.py`: backend trade normalization.
See [architecture.md](architecture.md) for complete flows,
[gotchas.md](gotchas.md) for symptom-driven diagnosis, and
[test-map.md](test-map.md) for verification choices.

View File

@ -1,210 +0,0 @@
# Clearing And Accounting Architecture
## Protocol direction
Client-facing messages and broker-facing messages intentionally differ.
```text
client -> EMS
Order, Cancel
EMS -> executor
BrokerdOrder, BrokerdCancel
executor -> EMS
BrokerdOrderAck, BrokerdStatus, BrokerdFill,
BrokerdError, BrokerdPosition
EMS -> subscribed clients
Status, BrokerdPosition
```
`Order` carries the client `oid`, account, market, price, size, action,
and execution mode. `BrokerdOrderAck` establishes the executor's
`reqid`; subsequent broker messages should carry that ID so EMS can
resolve the client dialog.
`Status` is mutable current dialog state, not a history envelope. Exact
client states include `pending`, `open`, `dark_open`, `triggered`,
`fill`, `closed`, `canceled`, and `error`. Audit existing translation
before adding a state; backend `BrokerdStatus` vocabulary is narrower
and current producers are not fully conformant.
## EMS routing
`_emsd_main()` serves each client/market context. The actor-local
`Router` owns books, subscribers, order dialogs, and cached live trades
relays. Paper mode opens per-symbol relay contexts under the same broker
key, a current overwrite/pop hazard for concurrent paper symbols.
`open_brokerd_dialog()` is the session live-versus-paper selection
point:
- live execution talks to `brokerd.<broker>`;
- paper execution talks to `paperboi.<broker>`;
- chart-only and paper sessions should not boot credentialed brokerd.
Do not infer paper execution from each order's `exec_mode`. Session
mode selects the executor; per-order mode primarily distinguishes dark
from immediately routed orders, despite incomplete literal annotations.
`process_client_order_cmds()` handles submit, modify, cancel, dark,
and alert intent. It updates EMS dialog state before routing broker
commands. `translate_and_relay_brokerd_events()` applies acks, statuses,
fills, errors, and positions to dialogs and subscribers.
The `DarkBook` stores local predicates and watches quote ticks. When a
predicate triggers, `clear_dark_triggers()` emits the live broker order
and updates the existing client dialog rather than inventing a second
order identity.
## Ack and cancel ordering
Required actionable ordering is submit, ack, open, zero or more fills,
then terminal status. EMS handles cancel-before-ack, but it does not
buffer arbitrary status-before-ack events; those currently fall through
as unhandled. Backends must ack before actionable statuses.
The important race is:
```text
client Cancel(oid)
-> EMS has no reqid yet
-> mark Status.cancel_called
BrokerdOrderAck(oid, reqid)
-> install mapping
-> send deferred BrokerdCancel(reqid)
```
Do not drop a pre-ack cancel and do not send a broker cancel with an
`oid` unless the backend explicitly uses that value as its `reqid`.
## Paper execution
`PaperBoi` maintains simulated orders, opens the market feed, and fills
orders when L1 ask/bid quotes cross their prices. `trade`/`last` ticks
zip buy and sell iterators, so a lone resting side currently may not
fill from those tick types. `fake_fill()` is the core fill-to-account
path:
1. emit `BrokerdFill`;
2. emit terminal `BrokerdStatus` for the simulated order;
3. construct a signed normalized `Transaction`;
4. `TransactionLedger.update_from_t()`;
5. `Account.update_from_ledger()`;
6. persist the ledger and account;
7. emit `BrokerdPosition` with current size and PPU.
The protocol notifications and persistence occur in one task but are
not a database transaction. If persistence fails after fill/status
publication, restart/reconciliation behavior matters. Do not reorder
the sequence casually.
Partial fills currently reuse `oid` as `tid`. A later partial therefore
overwrites the paper ledger record and is rejected by position-event
dedupe. Fix unique fill IDs before relying on paper partial-fill math.
`open_trade_dialog()` opens symcache, paper ledger, account, and feed
resources under structured concurrency. An exception from any nested
resource, including ledger context exit, cancels the dialog and its feed
stream.
## Live backend variation
There is no universal live-broker accounting implementation:
- IB normalizes execution/commission events, updates ledger/account
state, and emits position updates.
- Kraken has backend trade normalization and position reconstruction,
but its live path writes account state without inserting every new
trade into `TransactionLedger`.
- Binance currently relays venue order/position events and does not
share every local `TransactionLedger`/`Account` path.
Inspect the backend's `broker.py`, `ledger.py`, and `norm_trade()` before
moving generic logic. A paper behavior is not automatically a live
backend contract.
## Ledger normalization
`TransactionLedger.data` is the durable record mapping. For paper it
contains transaction-like dictionaries. For live brokers it can contain
raw provider records.
`iter_txns()` sorts records and chooses normalization:
- paper uses `_paper_engine.norm_trade()`;
- live accounts use `brokermod.norm_trade()`.
Normalizer output should carry datetime, signed size, price, cost,
FQME, backend market ID, and transaction ID. Some normalizers return
`None` for unusable records; `iter_txns()` does not filter it, while
`to_txns()` does. Audit direct iterator consumers.
`write_config()` sorts records for stable persistence. Paper rewrite
logic migrates old symbol fields and qualifies legacy FQMEs through the
symcache. Search can return no matches; callers which select the first
result need an explicit fallback or a descriptive failure policy.
## Position event model
`Position` holds a market and a transaction-event mapping. New clears
are deduplicated by `tid`. Current size and PPU are recomputed from the
event sequence.
`Account.update_from_ledger()`:
1. receives normalized transactions;
2. resolves each market through `mktmaps` or a fallback table;
3. looks up or creates the position by `Transaction.bs_mktid`;
4. adds unseen clears;
5. returns visited positions, including duplicates whose clear was
rejected by `add_clear()`.
`minimized_clears()` intends to discard irrelevant history after
net-zero or sign transitions, but current slicing is not proven safe
and can reconstruct the wrong active size/PPU. Treat it as a known bug
surface until sign-transition round trips are covered.
`Position.update_from_msg()` serves UI summaries by replacing local
event state with a synthetic clear representing reported size and PPU.
That projection is intentionally lossy.
## Symbology contracts
`MktPair.fqme` is a normalized endpoint address assembled from pair,
venue, expiry/contract information, and broker. `MktPair.bs_fqme`
drops the broker suffix. `MktPair.bs_mktid` is the provider-native
market identity.
`SymbologyCache.load()` attempts to obtain provider assets and pair
structs, calls `get_mkt_info()`, and populates conventional mappings.
Assets are optional; missing/empty pair support returns early.
```text
assets[provider_asset_id] -> Asset
pairs[pair.bs_mktid] -> backend Pair Struct
mktmaps[mkt.fqme] -> MktPair
```
Some backends add aliases such as `mktmaps[bs_mktid]`. Search must
return the matched mapping key rather than rebuilding a key from the
value, otherwise aliases silently collapse. Current serialization then
writes aliases which reload rejects because `from_dict()` asserts each
key equals `mkt.fqme`.
## Persistence boundaries
`open_trade_ledger()` loads account TOML and compares a shallow snapshot
in `finally`. Top-level additions/replacements trigger writes; nested
in-place mutation may not. `open_account()` similarly mediates account
state. These contexts run inside actor tasks, so serialization errors
are runtime failures, not merely offline maintenance failures.
When changing schemas:
- preserve backend-native records unless migration is explicit;
- keep old paper field migration deterministic;
- avoid fuzzy qualification when an exact `bs_mktid`/FQME exists;
- test context exit, not only in-memory updates;
- inspect emitted positions after disk round trips.

View File

@ -1,146 +0,0 @@
# Clearing And Ledger Gotchas
## Trade dialog dies immediately after a fill
Likely cause: an explicit ledger/account write in the fill handler, or
a later context-exit write, raised after event publication.
Inspect, in order:
1. the first non-cancellation exception in the actor traceback;
2. `PaperBoi.fake_fill()` or the live backend fill handler;
3. explicit and context-exit `write_config()` calls;
4. FQME/`bs_mktid` qualification and TOML-compatible values;
5. the persisted ledger/account files for a partial update.
Tractor cancellation logs are often the consequence. Root-cause the
inner serialization, lookup, or normalization exception first.
## `MktPair` has no `len()` in RapidFuzz
Cause: a mapping of string keys to `MktPair` values was passed directly
to `rapidfuzz.process.extract()`. Mapping values become fuzzy choices.
Fix: search a list/view of string keys and resolve matched keys back
through the original mapping. Do not add sequence methods to `MktPair`
and do not use `processor=str` when aliases must be preserved.
## Fuzzy qualification raises `IndexError`
Cause: the caller selected the first match from an empty result after
the score cutoff rejected every key.
Decide explicitly whether to retain the input identity, reject the
record with a descriptive exception, or obtain missing market metadata.
Do not lower the cutoff blindly; the wrong market corrupts accounting.
## Cancel is ignored or sent with the wrong ID
Cause: confusion between client `oid` and backend `reqid`, commonly
during cancel-before-ack ordering.
Verify the ack installed both mapping directions and that
`Status.cancel_called` survives until `reqid` exists. Log both IDs and
the actor/backend account at every transition.
## Fills appear but positions do not move
Check these boundaries:
- the backend emitted `BrokerdFill` but never normalized a transaction;
- transaction size lost its buy/sell sign;
- `tid` collided with an existing position event;
- `Transaction.bs_mktid` selected a different `Account.pps` key;
- `mktmaps` lacked the exact transaction identity;
- position publication happened before accounting update;
- the backend intentionally reports venue positions instead of local
ledger-derived positions.
## Duplicate or inflated position size
Do not deduplicate by price/time alone. Confirm stable transaction IDs,
chronological sorting, and `Position.add_clear()` idempotence. Broker
execution IDs and order IDs are not interchangeable.
For partial fills, several `tid`s may correctly share one order
`reqid`. Collapsing them loses clears; replaying one `tid` twice
inflates nothing only if the dedupe boundary is preserved.
Current paper fills use `tid=oid`, so later partials overwrite the
ledger record and are deduplicated out of the position. Treat paper
partial fills as broken until each clear receives a stable unique ID.
## Paper and live state disagree
Paper uses normalized local transactions and can use the full FQME as
its account position key. A live backend may use native IDs, raw ledger
records, or venue-reported positions.
Compare normalized `Transaction`s and emitted `BrokerdPosition`s, not
raw TOML dictionaries across backends.
## Account appears under the wrong name
Separate UI/EMS account aliases from backend account IDs and ledger file
names. Backends may prefix account names for routing while persistence
uses an unprefixed native account key.
Trace account identity through `open_ems()`, broker dialog startup,
ledger opening, and `BrokerdPosition.account` before changing naming.
## A module-global cache is unexpectedly empty
Symcache, clients, contracts, and order tables are actor-local. Data
loaded in `datad` is not automatically available in `brokerd` or
`paperboi`. Also, `_symcache._caches` is currently read but never
populated, so do not assume repeated `open_symcache()` calls hit it.
Load `piker-conc-expert` and audit actor-local globals, async caches,
and dialog startup warming. Never rely on an import side effect from a
sibling actor.
## Teardown emits a cancellation storm
Find the first application exception. Structured cancellation then
closes feed streams, broker streams, and nested contexts. Avoid masking
the originating exception with broad cancellation handling.
For stream ownership and context cancellation semantics, use
`piker-conc-expert`.
## Broker status is logged as unhandled
EMS currently accepts only ack-correlated `open`, `closed`, and
`canceled` broker statuses. Declared `pending` and backend-produced
`fill`/`filled` variants fall through, as do statuses arriving before
ack. Verify producer vocabulary and ack ordering before adding another
consumer branch.
## Another client sees order or position events
Current translation broadcasts order updates by FQME and positions to
all attached clients; `Router.dialogs` is not used as an event privacy
filter. Treat subscriber isolation as incomplete, not guaranteed.
## Debug breadcrumb
Capture one row per event with:
```text
actor, backend, account, fqme, bs_mktid,
oid, reqid, venue_order_id, tid,
message_type, status, action, signed_size, price, timestamp
```
Then compare:
1. client command order;
2. EMS status history;
3. broker event order;
4. normalized transactions;
5. position event IDs and computed size/PPU;
6. ledger/account disk state;
7. emitted position summaries.
This separates protocol loss, identity skew, accounting math, and
persistence failure without guessing from UI state.

View File

@ -1,84 +0,0 @@
# Clearing And Accounting Test Map
## Deterministic first-pass tests
Use the narrowest test that owns the broken contract:
| Area | First target |
|---|---|
| Ledger/account persistence | targeted node in `tests/test_accounting.py` |
| EMS bad-backend handling | `tests/test_ems.py::test_ems_err_on_bad_broker` |
| IB request/response routing | `tests/test_ib_method_proxy.py` |
| IB history normalization | `tests/test_ib_history.py` |
| Service/actor startup | targeted node in `tests/test_services.py` |
Known missing high-value regressions include paper partial-fill IDs,
status-before-ack handling, `minimized_clears()` sign-transition round
trips, nested ledger dirty detection, and symcache alias reload.
For `SymbologyCache.search()` and paper ledger qualification, cover:
- real `Asset` and `MktPair` values;
- a native-ID alias and canonical FQME key;
- the actual `TransactionLedger.write_config()` path;
- persisted TOML fields after the round trip;
- no use of live APIs or user configuration.
## Side-effectful tests
Do not run these without explicit authorization and the repository test
harness guidance:
- paper EMS tests which open live market/symbology feeds;
- live Binance/Kraken feed suites;
- IB account tests using configured accounts;
- tests which write tracked ledger/account fixtures;
- broker dialogs requiring credentials or venue connectivity.
After any accounting test using `tests/_inputs`, inspect its diff. Some
context managers can rewrite fixture ledgers on exit.
## Regression design
Prefer a direct contract regression over a full actor test when the
failure is synchronous and deterministic. Use an actor-level test when
the bug depends on:
- ack/cancel or fill/status interleaving;
- context cancellation or stream ownership;
- actor-local state/cache separation;
- daemon selection or startup;
- publication ordering across EMS and broker streams.
Every regression should document the original failure, triggering
state, violated invariant, arrangement, and proof of the fix.
## Verification layers
1. `git diff --cached --check` for the exact staged boundary.
2. Ruff with the repository's intended rule profile.
3. A deterministic unit/filesystem regression.
4. Adjacent accounting or EMS tests which do not require live state.
5. Explicitly authorized backend/actor integration tests.
Do not interpret a passing ellipsis-body or hard-skipped test as
behavioral coverage. Read the selected node before using it as a gate.
## Manual reconciliation check
For production-only failures, compare one fill end to end:
```text
BrokerdFill
-> normalized Transaction
-> ledger record
-> Position._events[tid]
-> Position.cumsize / ppu
-> account TOML
-> BrokerdPosition
-> UI summary
```
All identities, sign, price, and account values should remain explainable
at each arrow. A mismatch identifies the owning boundary for the next
focused test.

View File

@ -5,11 +5,7 @@ description: >
across distributed actor systems. Apply when
adding profiling, debugging perf regressions, or
optimizing hot paths in piker code.
compatibility: >
Requires a piker checkout and Python profiling work.
metadata:
author: goodboy
version: "1.0"
user-invocable: false
---
# Piker Profiling Subsystem

View File

@ -5,11 +5,7 @@ description: >
ethos. Apply when communicating with piker devs,
writing commit messages, code review comments, or
any collaborative interaction.
compatibility: >
Harness-independent communication guidance.
metadata:
author: goodboy
version: "1.0"
user-invocable: false
---
# Piker Slang & Communication Style

View File

@ -47,7 +47,7 @@ that's why it's like 1000x faster ya know?"
- Wrap all code symbols: `function()`,
`ClassName`, `field_name`
- File paths: `piker/ui/_remote_ctl.py`
- Commands: `git status`, `piker store shm`
- Commands: `git status`, `piker store ldshm`
**Explain like you're pair programming:**
```

View File

@ -5,12 +5,7 @@ description: >
for piker's UI. Apply when optimizing graphics
performance, adding new chart annotations, or
working with `QGraphicsItem` subclasses.
compatibility: >
Requires a piker checkout with PyQtGraph and Qt source
available for inspection.
metadata:
author: goodboy
version: "1.0"
user-invocable: false
---
# PyQtGraph Rendering Optimization

View File

@ -1 +0,0 @@
../../../../../../taken/wkts/federated_project_stores/.agents/skills/taken/SKILL.md

View File

@ -1 +0,0 @@
../../../../../../../taken/wkts/federated_project_stores/.agents/skills/taken/agents/openai.yaml

View File

@ -1 +0,0 @@
../../../../../../../taken/wkts/federated_project_stores/.agents/skills/taken/references/agents.md

View File

@ -1 +0,0 @@
../../../../../../../taken/wkts/federated_project_stores/.agents/skills/taken/references/writes.md

View File

@ -6,12 +6,7 @@ description: >
with OHLCV arrays, timestamp lookups, gap
detection, or any array/dataframe operations in
piker.
compatibility: >
Requires a piker checkout with NumPy and optionally
Polars.
metadata:
author: goodboy
version: "1.0"
user-invocable: false
---
# Timeseries Optimization: NumPy & Polars
@ -66,14 +61,11 @@ ts_array = np.array(timestamps)
# binary search for all timestamps at once
indices = np.searchsorted(time_arr, ts_array)
# bounds check before indexing: searchsorted may return
# len(time_arr) for values above the final timestamp
in_bounds = indices < len(time_arr)
valid_mask = np.zeros(indices.shape, dtype=bool)
valid_mask[in_bounds] = (
time_arr[indices[in_bounds]]
==
ts_array[in_bounds]
# bounds check and exact match verification
valid_mask = (
(indices < len(array))
&
(time_arr[indices] == ts_array)
)
valid_indices = indices[valid_mask]

View File

@ -1 +1 @@
{"version": 1, "backend": "legacy"}
{"version": 1, "backend": "neutral"}

View File

@ -1,12 +0,0 @@
{
"permissions": {
"allow": [
"Bash(chmod:*)",
"Bash(/tmp/piker_commits.txt)",
"Bash(python:*)",
"Bash(ls:*)"
],
"deny": [],
"ask": []
}
}

View File

@ -1 +0,0 @@
../../.agents/skills/piker-clearing-expert

View File

@ -1,155 +0,0 @@
---
name: piker-conc-expert
description: >
Distributed-runtime and structured-concurrency
expertise for piker's `tractor` actor-tree. Apply
when working on daemon/service architecture, actor
spawning/discovery, cross-actor RPC (ctx/stream
eps), `to_asyncio` integration, cancellation
semantics, or debugging hangs/wedges/skews in the
actor system.
compatibility: >
Requires a piker checkout and familiarity with Python,
trio, and tractor.
metadata:
author: goodboy
version: "1.0"
---
# Piker Concurrency & Runtime Expertise
The distilled mental model for piker's distributed
runtime: a `trio`-structured actor tree supervised by
`tractor` (pinned to git main) where every long-lived
subsystem is a named daemon-actor talking over
ctx/stream IPC.
## Actor tree & daemon taxonomy
```
pikerd root supervisor + registry
├── datad.<broker> feed bus, shm writers, tsp
│ history, symbol search
├── brokerd.<broker> live order-ctl ONLY; lazily
│ spawned by emsd, credentialed
├── emsd dark-clearing + order routing
│ └── paperboi.<broker> sim-clearing (paper mode)
└── samplerd singleton OHLC clock/increment
```
Key invariants:
- `datad` hosts all `piker.data.validate._eps['datad']`
eps; `brokerd` only the `['brokerd']` (order-ctl)
ones. The `_eps` table in `piker/data/validate.py`
is the authoritative contract; `get_eps(mod, kind)`
introspects a backend's support.
- `brokerd.<broker>` is booted in EXACTLY one place:
`open_brokerd_dialog()` in `piker/clearing/_ems.py`
(with a `portal:` override for the `piker ledger`
ad-hoc actor). Chart-only + paper sessions run with
ZERO brokerd procs. Never add a data-path spawn!
- backends declare per-daemon-kind submods via
`_datad_mods`/`_brokerd_mods` in their
`__init__.py` (fallback: `__enable_modules__`).
## Daemon lifecycle conventions
Every daemon-kind follows the same trio of fns (see
`piker/brokers/_daemon.py` + `piker/data/_daemon.py`
as the canonical pair):
- `_setup_persistent_<kind>()`: a `@tractor.context`
"lifetime fixture" run via
`Services.start_service_task()`; does console-log
setup ONCE for the actor, allocs any actor-global
state (eg. datad's `_FeedsBus`), then
`await ctx.started()` + `trio.sleep_forever()`.
- `<kind>_init()`: builds `enable_modules` + actor
name `f'<kind>.{brokername}'` and copies backend
`_spawn_kwargs` (CRITICAL: `ib` needs
`infect_asyncio=True` in EVERY daemon-kind).
- `spawn_<kind>()` + `maybe_spawn_<kind>()`: thin
wrappers over `Services.actor_n.start_actor()` and
`piker.service.maybe_spawn_daemon()` (registry
find-or-spawn w/ per-service-name locking).
Caps-sec model: `enable_modules` gates RPC entry ONLY
— python imports are unrestricted in-proc. Keep each
daemon's enable set minimal; the (credentialed)
`brokerd` must never RPC-enable `piker.data.*` feed
mods.
## Actor-local state: the #1 split hazard
Module-globals and instance caches are PER-ACTOR.
Anything that "just worked" because two subsystems
shared a process will break when they're split into
sibling actors. Canonical example: `ib`'s
`Client._contracts` was warmed by feed-side
`get_mkt_info()` in-proc; post datad/brokerd-split
the trading actor must warm it itself (eagerly at
`open_trade_dialog()` startup for open pps/orders +
lazily per order request via
`symbols.cache_contract()`).
When moving code across actor boundaries ALWAYS audit:
- module-global registries (`feed._bus`,
`_accounts2clients`, `_client_cache`, ..)
- `@async_lifo_cache`/`maybe_open_context` caches
(NOTE: `async_lifo_cache` keys on POSITIONAL args
only; a cache-hit SKIPS the fn body and thus any
side-effect writes!)
- logging handler placement (see gotchas.md)
## tractor primitives as used here
- `@tractor.context` eps: `await ctx.started(val)`
unblocks the caller w/ `val`; long-lived eps then
`ctx.open_stream()` or `sleep_forever()`.
- discovery: `tractor.find_actor()` via
`piker.service.find_service()`;
`wait_for_actor(name, registry_addr=...)`;
`query_actor(name, regaddr=...)` yields
`(sockaddr, portal)`. Addrs are wrapped
`tractor.discovery._addr.Address` types — use
`wrap_address()` to normalize raw tuples and
`.unwrap()` for comparisons.
- runtime-vars: `_runtime_vars['piker_vars']` is
inherited down the spawn tree; used eg. for
`piker_test_dir` config isolation — read LAZILY at
use-time, never at import time (subactors only get
vars post runtime-boot).
- cancellation semantics (modern tractor): a
`ContextCancelled` whose `.canceller` is your own
actor is ABSORBED (clean exit, nothing raised);
single-exc groups collapse (`collapse_eg`) so eg.
a KBI propagates bare. Exc attrs:
`RemoteActorError.boxed_type` (not `.type`).
## `to_asyncio` (infect-asyncio) integration
For `ib` (and `deribit`) the backend client runs on
an embedded `asyncio` loop via
`tractor.to_asyncio.open_channel_from()` +
`LinkedTaskChannel`.
Rules learned the hard way:
- a shared req/resp channel MUST correlate responses
to requests (see `MethodProxy._run_method()`'s
`mid` protocol in `piker/brokers/ib/api.py`):
caller cancellation (eg. `move_on_after` timeouts)
otherwise orphans a response and silently skews
every later result off-by-one.
- the aio-side relay must catch + ship back ALL
(non-cancel) exceptions as `{'exception': err}`
resps; an escaping error kills the relay task ->
channel -> proxy nursery -> the whole dialog,
bypassing every caller-side guard.
- `TrioTaskExited` ("child asyncio task is still
running?") on teardown is a known wart family;
prefer upstream `tractor` fixes over piker-side
bandaids.
See [gotchas.md](gotchas.md) for the symptom->cause
registry and [debug-recipes.md](debug-recipes.md) for
forensics techniques.

View File

@ -1,100 +0,0 @@
# Debug recipes: actor-system forensics
Field-tested techniques for diagnosing hangs, wedges
and cross-actor state bugs WITHOUT a debugger attached
(or when `py-spy` ain't installed).
## Wedged actor triage (no REPL)
1. find the tree:
`ps -eo pid,etime,args | grep -E 'pytest|tractor._child'`
— long-`etime` `tractor._child` procs w/ a stuck
parent = wedge.
2. kernel state:
`cat /proc/<pid>/wchan` + `status | grep -E
'State|Threads'` — `do_epoll_wait` + sleeping =
idle event loop, NOT cpu-spin.
3. **the money read** — socket queues:
`ss -tnp | grep <pid>`
- `Recv-Q > 0` on the parent-IPC conn = the actor
STOPPED CONSUMING its msg loop (runtime bug),
parent is waiting on it.
- zero external (api/ws) conns = wedged before/
without provider IO; don't blame the network.
- `CLOSE-WAIT` lingerers = unclean peer teardown.
4. cleanup: `pkill -f tractor._child` (NB: in
compound shell cmds `pkill`'s exit code poisons
`&&` chains — run it standalone).
## Hang-proof test gating
- per-suite, never combined (cross-suite session
state interacts w/ the 2nd-boot wedge):
`timeout -k 5 300 python -m pytest tests/<one>.py -q`
- rc 124/143 = hang-kill -> retry ONCE before
investigating.
- isolate a flaky test w/ a 3x loop; ~50% hit-rate
signatures match the known 2nd-boot wedge (see
gotchas.md).
## Regression vs pre-existing attribution
When a failure appears mid-refactor:
1. `git stash -u` (or checkout the file subset) and
re-run the EXACT failing case at baseline.
2. if baseline can't even run, selectively revert
ONLY the suspect layer:
`git diff <files> > /tmp/x.patch;
git checkout <files>` -> test ->
`git apply /tmp/x.patch`.
3. flake-rate compare (3x runs) beats single-shot
conclusions.
## Off-by-one / stale IPC resp detection
Mismatched query->result content in logs (resp
payload obviously for a prior request) = shared
req/resp channel w/o correlation + a cancelled
caller. Grep the ep for `move_on_after`/`fail_after`
around proxied calls. Fix = req-id (`mid`) tagging,
never "just a lock" (cancellation still orphans).
## Logging-chain audits
When records double-print or go bare (see gotchas.md):
```python
import logging
l = logging.getLogger('piker.brokers.ib.broker')
while l:
print(l.name, l.level, l.handlers, l.propagate)
l = l.parent
```
Exactly ONE stderr handler should exist in the chain,
attached by the actor's daemon fixture.
## Live actor-tree smoke (headless)
Boot against an ALT registry port so a user's running
stack is untouched; script in a REAL file (tractor
children re-exec `__main__` from path — stdin scripts
crash w/ `FileNotFoundError: .../<stdin>`):
```python
async with maybe_open_pikerd(
registry_addrs=[('127.0.0.1', 6979)],
):
async with open_feed(['xbtusdt.kraken']) as feed:
assert await check_for_service('datad.kraken')
assert not await check_for_service(
'brokerd.kraken'
)
```
## In-proc fail-fast unit checks
Spawn-path guards that raise BEFORE touching the
runtime can be tested w/ a bare `trio.run()` (eg
`spawn_brokerd('kucoin')` raising the datad-only
error) — no pikerd needed.

View File

@ -1,116 +0,0 @@
# Known gotchas: symptom -> cause -> fix
A registry of distributed-runtime failure modes hit
(and diagnosed) in the field; check here FIRST when a
log/traceback matches.
## "Can not order ..., no qualified contract cached"
- **Symptom**: `RuntimeError` from
`ib.api.Client.submit_limit()` w/ empty
`Client._contracts` in `brokerd.ib`.
- **Cause**: per-actor cache never warmed; feed-side
qualification now lives in `datad.ib`.
- **Fix(ed)**: eager warmup at `open_trade_dialog()`
start + lazy per-order `get_mkt_info()` +
`cache_contract()` (writes BOTH `mkt.bs_fqme` and
`mkt.fqme` keys; different consumers read each!).
## Search returns results for the WRONG pattern
- **Symptom**: fqme search for 'gld' returns nvda
results; next query returns the prior query's set.
- **Cause**: `MethodProxy` channel off-by-one — a
caller cancelled (search `move_on_after` timeout)
after sending its request orphans the response;
every later caller consumes the previous resp.
- **Fix(ed)**: `mid` req-id correlation in
`_run_method()` + relay; stale resps are dropped w/
a "Dropping stale method-resp" warning. If that
warning spams, some caller is being cancelled
mid-call habitually — find + fix its timeout.
## One bad request crashes a whole dialog/actor
- **Symptom**: `TrioTaskExited` storm + nursery
teardown after a single method error (eg ambiguous
contract `AttributeError`).
- **Cause**: exception escaped the aio-side relay
loop (`open_aio_client_method_relay()`) killing
channel + proxy nursery; caller-side `try/except`
CANNOT catch it.
- **Fix(ed)**: relay catches `Exception` -> ships
`{'exception': err, 'mid': ...}` resp; order
handler converts to EMS `BrokerdError` msgs.
## Ambiguous ib contracts -> `NoneType` attr errors
- **Symptom**: `'NoneType' object has no attribute
'primaryExchange'` in `find_contracts()`.
- **Cause**: `qualifyContractsAsync()` returns `None`
entries for ambiguous (eg venue-less stonk fqme
matching multiple listings: 'gld' -> ARCA/USD +
VENTURE/CAD).
- **Fix(ed)**: filter `None`s + raise descriptive
`ValueError` ("use 'gld.arca.ib'").
## Double-printed log records (same task id, 2x)
- **Symptom**: every record from some subsys printed
twice w/ identical task ids.
- **Cause**: stderr handlers attached at TWO levels
of one logger-propagation chain (eg daemon fixture
on `piker.brokers.ib` + an ep calling
`get_console_log(name=__name__)` on the child).
tractor's handler-dedup only checks the SAME
logger, not ancestors.
- **Rule**: console handlers are attached ONCE per
actor in the `_setup_persistent_*()` fixture; eps
needing a different level use `log.setLevel()`
ONLY, never `get_console_log()`.
## Bare/non-colorized log lines
- **Symptom**: records w/ no timestamp/actor prefix.
- **Cause**: NO handler anywhere in the emitting
logger's chain -> stdlib `logging.lastResort`. Post
actor-splits, a daemon fixture may only cover its
own subsys subtree (eg datad's `piker.data.*` but
not the backend's `piker.brokers.<broker>.*`).
- **Fix(ed)**: `_setup_persistent_datad()` enables
BOTH `piker.data.<broker>` and
`piker.brokers.<broker>` subtrees.
## 2nd in-proc runtime boot wedges (~50%)
- **Symptom**: test hangs when one test proc boots a
2nd `pikerd` (eg `test_multi_fill_positions`'s
persistence re-check); a zombie `*.{broker}` child
lingers w/ unread bytes in its parent-IPC Recv-Q.
- **Cause**: pre-existing `tractor`-main runtime
teardown bug (confirmed independent of piker-layer
changes via revert-testing 2026-06).
- **Mitigation**: run suites per-file wrapped in
`timeout -k 5 300 ...`; retry once on rc 124/143.
Do NOT chase as a regression of unrelated changes.
## ib client-id collisions post-split
- **Symptom**: 2nd ib daemon burns the full
conn-timeout retry cycle connecting to gw/tws.
- **Cause**: `datad.ib` + `brokerd.ib` both default
`client_id=6116` w/ linear `+i` retries.
- **Fix(ed)**: role-based offsets in
`load_aio_clients()`: datad +16, ad-hoc (test/cli)
actors +32.
## `async_lifo_cache` skipped side-effects
- **Symptom**: a fn's cache-write side effect
(eg `get_mkt_info()` -> `_contracts`) missing for
a 2nd client/proxy.
- **Cause**: cache keys on POSITIONAL args only; a
hit skips the body entirely.
- **Rule**: never rely on cached-fn side effects;
perform required writes explicitly at the call
site (eg `cache_contract()` after `get_mkt_info`).

View File

@ -0,0 +1 @@
../../.agents/skills/piker-profiling

View File

@ -0,0 +1 @@
../../.agents/skills/piker-slang

View File

@ -0,0 +1 @@
../../.agents/skills/pyqtgraph-optimization

View File

@ -0,0 +1 @@
../../.agents/skills/timeseries-optimization

2
.gitattributes vendored
View File

@ -1,2 +0,0 @@
# Taken requires a blank line after every Org subtree, including EOF.
.taken/*.org whitespace=-blank-at-eof

354
.gitignore vendored
View File

@ -107,14 +107,11 @@ ENV/
.git/
# any commit-msg gen tmp files
.claude/*_commit_*.md
.claude/*_commit*.toml
# ai.skillz/commit-msg
.claude/skills/commit-msg/msgs/
.claude/skills/commit-msg/conf.toml
.claude/git_commit_msg_LATEST.md
.opencode/skills/commit-msg/SKILL.md
.claude/*_commit_*.md
.claude/*_commit*.toml
# nix develop --profile .nixdev
.nixdev*
@ -137,61 +134,6 @@ gitea/
# LLM conversations that should remain private
docs/conversations/
# BEGIN ai.skillz: direct:symlink:claude:run-tests
/.claude/skills/run-tests/SKILL.md
# END ai.skillz: direct:symlink:claude:run-tests
# BEGIN ai.skillz: direct:symlink:opencode:run-tests
/.opencode/skills/run-tests/SKILL.md
# END ai.skillz: direct:symlink:opencode:run-tests
# BEGIN ai.skillz: direct:symlink:opencode:command:run-tests
/.opencode/commands/run-tests.md
# END ai.skillz: direct:symlink:opencode:command:run-tests
# BEGIN ai.skillz: direct:symlink:claude:close-wkt
/.claude/skills/close-wkt
# END ai.skillz: direct:symlink:claude:close-wkt
# BEGIN ai.skillz: direct:symlink:opencode:close-wkt
/.opencode/skills/close-wkt
# END ai.skillz: direct:symlink:opencode:close-wkt
# BEGIN ai.skillz: runtime:code-review-changes
.claude/review_context.md
.claude/review_regression.md
# END ai.skillz: runtime:code-review-changes
# BEGIN ai.skillz: direct:symlink:claude:code-review-changes
/.claude/skills/code-review-changes
# END ai.skillz: direct:symlink:claude:code-review-changes
# BEGIN ai.skillz: direct:symlink:opencode:code-review-changes
/.opencode/skills/code-review-changes
# END ai.skillz: direct:symlink:opencode:code-review-changes
# BEGIN ai.skillz: runtime:commit-msg
.claude/skills/commit-msg/msgs/
.claude/skills/commit-msg/conf.toml
.claude/git_commit_msg_LATEST.md
# END ai.skillz: runtime:commit-msg
# BEGIN ai.skillz: direct:symlink:claude:commit-msg
/.claude/skills/commit-msg/SKILL.md
# END ai.skillz: direct:symlink:claude:commit-msg
# BEGIN ai.skillz: direct:symlink:opencode:commit-msg
/.opencode/skills/commit-msg/SKILL.md
# END ai.skillz: direct:symlink:opencode:commit-msg
# BEGIN ai.skillz: direct:symlink:claude:dep-supersede-scan
/.claude/skills/dep-supersede-scan
# END ai.skillz: direct:symlink:claude:dep-supersede-scan
# BEGIN ai.skillz: direct:symlink:opencode:dep-supersede-scan
/.opencode/skills/dep-supersede-scan
# END ai.skillz: direct:symlink:opencode:dep-supersede-scan
# BEGIN ai.skillz: direct:symlink:claude:gish
/.claude/skills/gish
# END ai.skillz: direct:symlink:claude:gish
@ -200,17 +142,7 @@ docs/conversations/
/.opencode/skills/gish
# END ai.skillz: direct:symlink:opencode:gish
# BEGIN ai.skillz: direct:symlink:claude:inter-skill-review
/.claude/skills/inter-skill-review
# END ai.skillz: direct:symlink:claude:inter-skill-review
# BEGIN ai.skillz: direct:symlink:opencode:inter-skill-review
/.opencode/skills/inter-skill-review
# END ai.skillz: direct:symlink:opencode:inter-skill-review
# BEGIN ai.skillz: runtime:open-wkt
.claude/wkts/
claude_wkts
/wkts/
# END ai.skillz: runtime:open-wkt
@ -222,6 +154,121 @@ claude_wkts
/.opencode/skills/open-wkt
# END ai.skillz: direct:symlink:opencode:open-wkt
# BEGIN ai.skillz: direct:symlink:claude:run-tests
/.claude/skills/run-tests/SKILL.md
# END ai.skillz: direct:symlink:claude:run-tests
# BEGIN ai.skillz: direct:symlink:opencode:run-tests
/.opencode/skills/run-tests/SKILL.md
# END ai.skillz: direct:symlink:opencode:run-tests
# BEGIN ai.skillz: direct:symlink:claude:close-wkt
/.claude/skills/close-wkt
# END ai.skillz: direct:symlink:claude:close-wkt
# BEGIN ai.skillz: direct:symlink:opencode:close-wkt
/.opencode/skills/close-wkt
# END ai.skillz: direct:symlink:opencode:close-wkt
# BEGIN ai.skillz: runtime:code-review
.ai/code-review/reports/
# END ai.skillz: runtime:code-review
# BEGIN ai.skillz: direct:symlink:claude:code-review
/.claude/skills/code-review
# END ai.skillz: direct:symlink:claude:code-review
# BEGIN ai.skillz: direct:symlink:opencode:code-review
/.opencode/skills/code-review
# END ai.skillz: direct:symlink:opencode:code-review
# BEGIN ai.skillz: runtime:code-review-changes
.ai/state/review/
.claude/review_context.md
.claude/review_regression.md
.claude/review_replies/
# END ai.skillz: runtime:code-review-changes
# BEGIN ai.skillz: direct:symlink:claude:code-review-changes
/.claude/skills/code-review-changes
# END ai.skillz: direct:symlink:claude:code-review-changes
# BEGIN ai.skillz: direct:symlink:opencode:code-review-changes
/.opencode/skills/code-review-changes
# END ai.skillz: direct:symlink:opencode:code-review-changes
# BEGIN ai.skillz: runtime:commit-msg
.ai/state/commit-msg/
.ai/state/migrations/
.ai/commit-msg/conf.toml
.claude/skills/commit-msg/msgs/
.claude/git_commit_msg_LATEST.md
# END ai.skillz: runtime:commit-msg
# BEGIN ai.skillz: direct:symlink:claude:commit-msg
/.claude/skills/commit-msg/SKILL.md
# END ai.skillz: direct:symlink:claude:commit-msg
# BEGIN ai.skillz: direct:symlink:opencode:commit-msg
/.opencode/skills/commit-msg/SKILL.md
# END ai.skillz: direct:symlink:opencode:commit-msg
# BEGIN ai.skillz: direct:symlink:claude:commit-plan
/.claude/skills/commit-plan
# END ai.skillz: direct:symlink:claude:commit-plan
# BEGIN ai.skillz: direct:symlink:opencode:commit-plan
/.opencode/skills/commit-plan
# END ai.skillz: direct:symlink:opencode:commit-plan
# BEGIN ai.skillz: direct:symlink:claude:dep-supersede-scan
/.claude/skills/dep-supersede-scan
# END ai.skillz: direct:symlink:claude:dep-supersede-scan
# BEGIN ai.skillz: direct:symlink:opencode:dep-supersede-scan
/.opencode/skills/dep-supersede-scan
# END ai.skillz: direct:symlink:opencode:dep-supersede-scan
# BEGIN ai.skillz: direct:symlink:claude:resolve-conflicts
/.claude/skills/resolve-conflicts
# END ai.skillz: direct:symlink:claude:resolve-conflicts
# BEGIN ai.skillz: direct:symlink:opencode:resolve-conflicts
/.opencode/skills/resolve-conflicts
# END ai.skillz: direct:symlink:opencode:resolve-conflicts
# BEGIN ai.skillz: direct:symlink:claude:git-mgmt
/.claude/skills/git-mgmt
# END ai.skillz: direct:symlink:claude:git-mgmt
# BEGIN ai.skillz: direct:symlink:opencode:git-mgmt
/.opencode/skills/git-mgmt
# END ai.skillz: direct:symlink:opencode:git-mgmt
# BEGIN ai.skillz: direct:symlink:claude:harness-perf
/.claude/skills/harness-perf
# END ai.skillz: direct:symlink:claude:harness-perf
# BEGIN ai.skillz: direct:symlink:opencode:harness-perf
/.opencode/skills/harness-perf
# END ai.skillz: direct:symlink:opencode:harness-perf
# BEGIN ai.skillz: direct:symlink:claude:inter-skill-review
/.claude/skills/inter-skill-review
# END ai.skillz: direct:symlink:claude:inter-skill-review
# BEGIN ai.skillz: direct:symlink:opencode:inter-skill-review
/.opencode/skills/inter-skill-review
# END ai.skillz: direct:symlink:opencode:inter-skill-review
# BEGIN ai.skillz: direct:symlink:claude:opencode-cleaning
/.claude/skills/opencode-cleaning
# END ai.skillz: direct:symlink:claude:opencode-cleaning
# BEGIN ai.skillz: direct:symlink:opencode:opencode-cleaning
/.opencode/skills/opencode-cleaning
# END ai.skillz: direct:symlink:opencode:opencode-cleaning
# BEGIN ai.skillz: direct:symlink:claude:plan-io
/.claude/skills/plan-io
# END ai.skillz: direct:symlink:claude:plan-io
@ -231,6 +278,8 @@ claude_wkts
# END ai.skillz: direct:symlink:opencode:plan-io
# BEGIN ai.skillz: runtime:pr-msg
.ai/state/pr-msg/
.ai/pr-msg/conf.toml
.claude/skills/pr-msg/msgs/
.claude/skills/pr-msg/pr_msg_LATEST.md
# END ai.skillz: runtime:pr-msg
@ -263,14 +312,6 @@ claude_wkts
/.opencode/skills/py-codestyle
# END ai.skillz: direct:symlink:opencode:py-codestyle
# BEGIN ai.skillz: direct:symlink:claude:resolve-conflicts
/.claude/skills/resolve-conflicts
# END ai.skillz: direct:symlink:claude:resolve-conflicts
# BEGIN ai.skillz: direct:symlink:opencode:resolve-conflicts
/.opencode/skills/resolve-conflicts
# END ai.skillz: direct:symlink:opencode:resolve-conflicts
# BEGIN ai.skillz: runtime:taken-export
.ai/taken/exports/
# END ai.skillz: runtime:taken-export
@ -291,31 +332,160 @@ claude_wkts
/.opencode/skills/yt-url-lookup
# END ai.skillz: direct:symlink:opencode:yt-url-lookup
# BEGIN ai.skillz: direct:symlink:claude:command:branch-in-new-terminal
/.claude/commands/branch-in-new-terminal.md
# END ai.skillz: direct:symlink:claude:command:branch-in-new-terminal
# BEGIN ai.skillz: direct:symlink:opencode:command:run-tests
/.opencode/commands/run-tests.md
# END ai.skillz: direct:symlink:opencode:command:run-tests
# BEGIN ai.skillz: runtime:branch-in-new-terminal
.claude/.current_session
# END ai.skillz: runtime:branch-in-new-terminal
# BEGIN ai.skillz: direct:symlink:opencode:command:code-review
/.opencode/commands/code-review.md
# END ai.skillz: direct:symlink:opencode:command:code-review
# BEGIN ai.skillz: direct:symlink:opencode:command:code-review-changes
/.opencode/commands/code-review-changes.md
# END ai.skillz: direct:symlink:opencode:command:code-review-changes
# BEGIN ai.skillz: direct:symlink:opencode:command:commit-msg
/.opencode/commands/commit-msg.md
# END ai.skillz: direct:symlink:opencode:command:commit-msg
# BEGIN ai.skillz: direct:symlink:opencode:command:commit-plan
/.opencode/commands/commit-plan.md
# END ai.skillz: direct:symlink:opencode:command:commit-plan
# BEGIN ai.skillz: direct:symlink:opencode:command:opencode-cleaning
/.opencode/commands/opencode-cleaning.md
# END ai.skillz: direct:symlink:opencode:command:opencode-cleaning
# BEGIN ai.skillz: direct:symlink:opencode:command:pr-msg
/.opencode/commands/pr-msg.md
# END ai.skillz: direct:symlink:opencode:command:pr-msg
# BEGIN ai.skillz: direct:symlink:opencode:command:taken-export
/.opencode/commands/taken-export.md
# END ai.skillz: direct:symlink:opencode:command:taken-export
# Local worktrees and taken runtime artifacts
/.ai/state/
.*.taken.lock
# BEGIN ai.skillz: direct:symlink:claude:code-nav-refs
/.claude/skills/code-nav-refs
# END ai.skillz: direct:symlink:claude:code-nav-refs
# Version the federated project store despite local excludes
!/.taken/
!/.taken/current.org
!/.taken/sources.toml
!/.taken/README.md
# BEGIN ai.skillz: direct:symlink:opencode:code-nav-refs
/.opencode/skills/code-nav-refs
# END ai.skillz: direct:symlink:opencode:code-nav-refs
# BEGIN ai.skillz: direct:symlink:opencode:command:gish
/.opencode/commands/gish.md
# END ai.skillz: direct:symlink:opencode:command:gish
# BEGIN ai.skillz: direct:symlink:opencode:command:resolve-conflicts
/.opencode/commands/resolve-conflicts.md
# END ai.skillz: direct:symlink:opencode:command:resolve-conflicts
# BEGIN ai.skillz: direct:symlink:opencode:command:git-mgmt
/.opencode/commands/git-mgmt.md
# END ai.skillz: direct:symlink:opencode:command:git-mgmt
# BEGIN ai.skillz: direct:symlink:opencode:command:open-wkt
/.opencode/commands/open-wkt.md
# END ai.skillz: direct:symlink:opencode:command:open-wkt
# BEGIN ai.skillz: direct:symlink:opencode:command:close-wkt
/.opencode/commands/close-wkt.md
# END ai.skillz: direct:symlink:opencode:command:close-wkt
# BEGIN ai.skillz: direct:symlink:opencode:command:dep-supersede-scan
/.opencode/commands/dep-supersede-scan.md
# END ai.skillz: direct:symlink:opencode:command:dep-supersede-scan
# BEGIN ai.skillz: direct:symlink:opencode:command:harness-perf
/.opencode/commands/harness-perf.md
# END ai.skillz: direct:symlink:opencode:command:harness-perf
# BEGIN ai.skillz: direct:symlink:opencode:command:yt-url-lookup
/.opencode/commands/yt-url-lookup.md
# END ai.skillz: direct:symlink:opencode:command:yt-url-lookup
# BEGIN ai.skillz: direct:symlink:agents:gish
/.agents/skills/gish
# END ai.skillz: direct:symlink:agents:gish
# BEGIN ai.skillz: direct:symlink:agents:resolve-conflicts
/.agents/skills/resolve-conflicts
# END ai.skillz: direct:symlink:agents:resolve-conflicts
# BEGIN ai.skillz: direct:symlink:agents:git-mgmt
/.agents/skills/git-mgmt
# END ai.skillz: direct:symlink:agents:git-mgmt
# BEGIN ai.skillz: direct:symlink:agents:open-wkt
/.agents/skills/open-wkt
# END ai.skillz: direct:symlink:agents:open-wkt
# BEGIN ai.skillz: direct:symlink:agents:run-tests
/.agents/skills/run-tests
# END ai.skillz: direct:symlink:agents:run-tests
# BEGIN ai.skillz: direct:symlink:agents:close-wkt
/.agents/skills/close-wkt
# END ai.skillz: direct:symlink:agents:close-wkt
# BEGIN ai.skillz: direct:symlink:agents:code-review
/.agents/skills/code-review
# END ai.skillz: direct:symlink:agents:code-review
# BEGIN ai.skillz: direct:symlink:agents:code-nav-refs
/.agents/skills/code-nav-refs
# END ai.skillz: direct:symlink:agents:code-nav-refs
# BEGIN ai.skillz: direct:symlink:agents:code-review-changes
/.agents/skills/code-review-changes
# END ai.skillz: direct:symlink:agents:code-review-changes
# BEGIN ai.skillz: direct:symlink:agents:commit-msg
/.agents/skills/commit-msg
# END ai.skillz: direct:symlink:agents:commit-msg
# BEGIN ai.skillz: direct:symlink:agents:commit-plan
/.agents/skills/commit-plan
# END ai.skillz: direct:symlink:agents:commit-plan
# BEGIN ai.skillz: direct:symlink:agents:dep-supersede-scan
/.agents/skills/dep-supersede-scan
# END ai.skillz: direct:symlink:agents:dep-supersede-scan
# BEGIN ai.skillz: direct:symlink:agents:harness-perf
/.agents/skills/harness-perf
# END ai.skillz: direct:symlink:agents:harness-perf
# BEGIN ai.skillz: direct:symlink:agents:inter-skill-review
/.agents/skills/inter-skill-review
# END ai.skillz: direct:symlink:agents:inter-skill-review
# BEGIN ai.skillz: direct:symlink:agents:opencode-cleaning
/.agents/skills/opencode-cleaning
# END ai.skillz: direct:symlink:agents:opencode-cleaning
# BEGIN ai.skillz: direct:symlink:agents:plan-io
/.agents/skills/plan-io
# END ai.skillz: direct:symlink:agents:plan-io
# BEGIN ai.skillz: direct:symlink:agents:pr-msg
/.agents/skills/pr-msg
# END ai.skillz: direct:symlink:agents:pr-msg
# BEGIN ai.skillz: direct:symlink:agents:prompt-io
/.agents/skills/prompt-io
# END ai.skillz: direct:symlink:agents:prompt-io
# BEGIN ai.skillz: direct:symlink:agents:py-codestyle
/.agents/skills/py-codestyle
# END ai.skillz: direct:symlink:agents:py-codestyle
# BEGIN ai.skillz: direct:symlink:agents:taken-export
/.agents/skills/taken-export
# END ai.skillz: direct:symlink:agents:taken-export
# BEGIN ai.skillz: direct:symlink:agents:yt-url-lookup
/.agents/skills/yt-url-lookup
# END ai.skillz: direct:symlink:agents:yt-url-lookup
# BEGIN ai.skillz: workflow-state
/.ai/state/

View File

@ -1,22 +0,0 @@
# piker project store
`current.org` contains the intact piker scope moved from the
LNS working corpus. Task/checkbox states, carry metadata and prose
remain human-owned. `sources.toml` selects this branch's store.
Read the local `taken` skill through `.agents/skills/taken/SKILL.md`.
It requires a complete-file revision guard for each authorized save.
Use an explicitly selected source; do not write a global LNS copy.
This migration preserves a historical project scope, not a claim that
its old task descriptions or branch paths reflect current reality.
The global storespace is registered in the LNS migration worktree's
`taken/sources.toml`. Modden, Tractor and Piker include snapshots of their pre-existing
local stores. The LNS consolidation ledger pins those inputs. Before
landing, reconcile any newer edits there and retarget active agents;
do not overwrite another agent's source or infer acceptance.
Before removing this migration worktree after landing, update the
global registration and the cross-repository taken skill link to the
landed locations. The skill link intentionally points to the Taken
migration branch until that code and documentation land.

View File

@ -1,651 +0,0 @@
# vim: et sw=2 ts=2
#+TITLE: piker project store
#+TODO: TODO(t) WIP(w!) WAIT(a@) | DONE(d!) NOPE(n@)
# Checkbox states: [ ] open, [-] partial, [x] complete
* piker
:PROPERTIES:
:CATEGORY: piker
:END:
** TODO prs
:PROPERTIES:
:CREATED: [2026-07-15]
:CARRIED: 29
:END:
- [ ] move the below into *** todos with pr/branch links
* [ ] DPI-aware font scaling + manual kb bindings.
* [ ] gap_annotator for time gaps.
* [ ] moar `claude`-y skills,
* [ ] /lint with ruff
* [ ] /run-tests
*** WIP qualify known-FQME history backfill
:PROPERTIES:
:CREATED: [2026-07-24]
:CARRIED: 21
:REPO: /home/goodboy/repos/piker
:END:
- [x] preserve the dirty `flake_update` main checkout before
switching branches
- [x] check out `backfiller_deep_fixes` in the main checkout and
verify every process imports it
- [ ] complete the below qualification plan
* [ ] select one known-problem provider, FQME, timeframe, date range,
and original symptom
* [ ] preserve and checksum any known-bad parquet
* [ ] bootstrap `pikerd` with disposable config and NativeDB storage
* [ ] record baseline timestamps, rows, uniqueness, nulls,
ordering,
indexes, gaps, and readability
* [ ] reproduce fresh-backfill, restart, and append behavior for
only
the selected case
* [ ] convert each reproduced failure into a failing deterministic
test before fixing it
* [ ] rerun the exact manual lifecycle after every production
correction
* [ ] add deterministic subprocess coverage for process death and
cross-process locking
* [ ] exercise Ctrl-C, SIGTERM, SIGKILL, provider interruption, and
restart recovery
* [ ] qualify MarketStore and actual sampler backpressure separately
* [ ] expand to other timeframes and providers only after the
selected FQME passes
**** TODO fixed-FQME-case backfill qualify
:PROPERTIES:
:CREATED: [2026-07-29]
:CARRIED: 17
:REPO: piker/
:END:
- [ ] follow through using both new files,
* ./docs/manual_backfill_qualification.rst
* ./snippets/nativedb_backfill_audit.xsh
- [ ] choose and record one known-problem FQME, timeframe, UTC range,
and original chart symptom
- [ ] source `snippets/nativedb_backfill_audit.xsh` and initialize a
private disposable root with only the required provider config
- [ ] run repository and environment preflight at commit `0846cbd4`
- [ ] seed and audit the known-bad baseline, then replay repair and run
`bfq_compare()` without losing original timestamps
- [ ] clear only the disposable Parquet and qualify a fresh backfill
- [ ] restart against fresh storage and compare `fresh` to `restart`
- [ ] leave one subsequent run active long enough to append, then compare
`restart` to `append` with `require_newer=True`
- [ ] restart QQQ 1s on fresh datad SHM and verify the former 653-row
zero-time reservation does not recur
- [ ] preserve chart logs, audit JSON, Parquet snapshots, and exact UTC
gap endpoints for review
**** TODO review ^qualify^ evidence and close follow-ups
:PROPERTIES:
:CREATED: [2026-07-29]
:CARRIED: 17
:REPO: /piker
:END:
- [ ] verify every qualification process imports commit `0846cbd4`
- [ ] review baseline, repair, fresh, restart, and append reports for
structural, timestamp, endpoint, and gap regressions
- [ ] distinguish durable Parquet gaps from SHM hydration or chart-only
gaps using the runbook triage table
- [ ] convert each reproduced failure into a deterministic regression
before changing production code
- [ ] prepare the final qualification summary and any required patch,
PR, or worktree-lifecycle follow-ups
*** TODO cross-harness AI skill integration
:PROPERTIES:
:CREATED: [2026-07-21]
:CARRIED: 24
:REPO: /home/goodboy/repos/piker
:ISSUE: https://www.pikers.dev/pikers/piker/issues/79
:END:
- [ ] review and land the portable piker skill and OpenCode docs patch
- [ ] reconcile the active global `commit-msg` override with the
repo-local shared skill and style guide
- [ ] verify skill and command discovery after restarting Claude Code
and OpenCode
- [ ] fold remaining skill-content review into the canonical trackers:
* [ ] https://www.pikers.dev/pikers/piker/issues/69
* [ ] https://www.pikers.dev/pikers/piker/issues/79
*** TODO vectorize `gap_annotator` client spec building
:PROPERTIES:
:CREATED: [2026-07-21]
:CARRIED: 24
:REPO: /home/goodboy/repos/piker
:END:
- [ ] replace per-row Polars slicing and filtering in
`piker/tsp/_annotate.py:139` with extracted columns and batched
lookups
- [ ] preserve missing-prior-row, epoch-skip, direction, label, and
batch-payload behavior
- [ ] benchmark the 1285-gap case against the handoff in
`notes_to_self/claudy/gapsannotator_sesh.md`
- [ ] add focused correctness coverage for generated rectangle, arrow,
and text specs
*** TODO integrate the piker `ruff` lint skill
:PROPERTIES:
:CREATED: [2026-07-21]
:CARRIED: 24
:REPO: /home/goodboy/repos/piker
:END:
- [ ] review the clean but unmerged `claudy_writes_ruff_conf` branch
- [ ] validate its `ruff.toml` policy and staged-file checker against
the current tree
- [ ] port the `/lint` skill to shared Agent Skills frontmatter with
thin harness-specific commands
- [ ] rebase and prepare the accepted lint/config changes for landing
*** TODO reconcile stale Claude plans and worktrees
:PROPERTIES:
:CREATED: [2026-07-21]
:CARRIED: 24
:REPO: /home/goodboy/repos/piker
:END:
- [ ] reconcile `ai/claude-code/plans/shm_port.md` with the implemented
`tractor.ipc._shm` shim
- [ ] classify `datad_service.md` as an architecture record rather than
an active implementation plan
- [ ] inspect generated state before retiring the merged
`wkt/flake_update` and `worktree-ngi0_submission` worktrees
- [ ] preserve the unmerged lint worktree until its branch is reviewed
** TODO chart-local gap overlay follow-ups
:PROPERTIES:
:CREATED: [2026-08-14]
:CARRIED: 7
:REPO: /home/goodboy/repos/piker
:END:
- [ ] trigger `GapOverlayMngr.refresh()` from an explicit history
revision/publication event after repair or prepend
- [ ] expose gap-overlay UX through UI config
* [ ] startup visibility and enabled timeframes
* [ ] default `Ctrl+G` key binding
- [ ] live-qualify chart-local overlay behavior
* [ ] actor startup and focused 1s/60s toggling
* [ ] multi-symbol and duplicate-FQME cached charts
* [ ] secondary-`Viz` placement and backfill repositioning
* [ ] remote disconnect and owner-scoped graphics cleanup
- [ ] add focused Qt/actor regressions for the qualified lifecycle
** TODO factor typed chart annotation IPC dialogs
:PROPERTIES:
:CREATED: [2026-08-14]
:CARRIED: 7
:REPO: /home/goodboy/repos/piker
:END:
- [ ] exercise the strict `SetGapOverlay`/`GapOverlay`
dialog under a live Tractor context
* [ ] wrong-direction and unrelated payload rejection
* [ ] timeout, cancellation, stale reply, and disconnect recovery
- [ ] factor keyed send/receive locking, fresh request IDs, and stale
response correlation into a generic IPC dialog helper after a
second typed consumer establishes the interface
- [ ] migrate legacy `remote_annotate()` dict commands to tagged
request/response message types
- [ ] decide whether to fold `remote_gap_overlays()` into the general
annotation endpoint after the legacy protocol is typed
** proj_mgmt
:PROPERTIES:
:CATEGORY: project
:END:
*** TODO ngi0 aug01 funding submit!
DEADLINE: <2026-08-01 Sat>
:PROPERTIES:
:CREATED: [2026-06-01]
:CARRIED: 33
:END:
- [ ] wip pr: https://github.com/goodboy/tractor/pull/431
https://nlnet.nl/propose/
https://nlnet.nl/foundation/policies/generativeAI/
https://nlnet.nl/commonsfund/
*** TODO MEETING(s)
:PROPERTIES:
:CREATED: [2026-05-21]
:CARRIED: 33
:END:
** ui
:PROPERTIES:
:CATEGORY: piker.ui
:END:
*** TODO dpi_auto_calc
:PROPERTIES:
:CREATED: [2026-07-15]
:CARRIED: 29
:END:
- [ ] PUT PRs here
** brokers
:PROPERTIES:
:CATEGORY: piker.brokers
:END:
*** TODO IB: follow-up for search results bs!
:PROPERTIES:
:CREATED: [2026-05-21]
:CARRIED: 33
:END:
* https://www.pikers.dev/pikers/piker/issues/85
- [X] fix the `si.expiry..ib` search result?
- [ ] introspect why `Client.search_symbols()` is returning the
empty `.<venue>` case!
- presumably by something weird in the server-side endpoint?
- [ ] figure out better tuning of client side fuzzy-filter versus
server-side versus UI final display pass!
*** TODO ish for port to `uv`,
:PROPERTIES:
:CREATED: [2026-05-21]
:CARRIED: 33
:END:
* https://github.com/ib-api-reloaded/ib_async/issues/204
- [ ] mention to track in #68
*** TODO profiling: try newer libs,
:PROPERTIES:
:CREATED: [2026-05-21]
:CARRIED: 33
:END:
- [ ] https://github.com/pikers/piker/issues/337
** perf/tooling
:PROPERTIES:
:CATEGORY: piker.profile
:END:
- [ ] link existing GH issues for trying new
libs!
** FSP backfill: branch work
*** TODO review and commit FSP backfill synchronization
:PROPERTIES:
:ID: piker-fsp-backfill-sync-review-and-commit
:CREATED: [2026-09-03]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker/wkts/fsp_backfill_sync
:END:
- [ ] review committed token-targeted history graphics change
(`fadab3d2`)
- [ ] review and commit the FSP stream-contract boundary
* yo yo yo
* `piker/data/__init__.py`
* `piker/data/ticktools.py`
* `piker/fsp/_api.py`
* `piker/fsp/_momo.py`
* staged portion of `piker/fsp/_volume.py`
- [ ] review and commit the synchronization and live-volume boundary
* explicit `Flume` RT/history cadence
* immutable history snapshots and absolute SHM-bound synchronization
* relevant backfill filtering and non-duplicating destination steps
* nonnegative sampled and derived volume
* M4 graphics-cache invalidation and unchanged-update suppression
* FSP synchronization regressions and Prompt-IO provenance
- [ ] review and commit the `piker-fsp-expert` skill boundary
- [ ] run boundary checks and the final test suite
- [ ] inspect each staged diff and commit message before committing
*** TODO add cumulative M4 downsampling for volume curves
:PROPERTIES:
:ID: piker-cumulative-m4-volume-downsampling
:CREATED: [2026-09-03]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker/wkts/fsp_backfill_sync
:END:
- [ ] define cumulative bucket semantics for step-style data
* sum all source values represented by each pixel bucket
* preserve bucket time/index placement and zero-volume gaps
- [ ] add a sum-reducer variant alongside price min/max M4
- [ ] route unit and dollar-volume curves through cumulative downsampling
- [ ] keep price, OHLC, and non-cumulative signal curves on min/max M4
- [ ] preserve incremental appends, view changes, and cache invalidation
- [ ] test sum conservation across zoom levels and partial edge buckets
- [ ] profile the cumulative path against the existing M4 implementation
** TODO review and save the Trend Calculus prototype
:PROPERTIES:
:ID: piker-trend-calculus-prototype-review
:CREATED: [2026-10-05]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:ISSUE: https://github.com/pikers/piker/issues/187
:END:
[[file:/home/goodboy/repos/piker/docs/trend_calculus.rst][Research and prototype guide]]
- [ ] Regenerate and review six Trend Calculus behavior boundaries
on trend_calc_on_jev after workflow commit f148fbcc on
moar_ai_skillz lands; retain source/test pairs and inspect every
message before saving.
- [ ] Run each boundary check from the pinned package and the final
safe regression sequence; the working-tree offline suite passed 253
tests.
- [ ] Qualify one selected live source through startup, quiet bars,
skipped wakeups, history repair, replay and owner cancellation.
- [ ] Coordinate inherited stream/backfill work with
[[id:piker-fsp-backfill-sync-review-and-commit][the existing FSP synchronization task]].
*** TODO split draft TC commit after upstream history is settled
:PROPERTIES:
:ID: piker-trend-calculus-draft-commit-split
:CREATED: [2026-10-06]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:TAKEN_APPEND_OP: 85c6bdbe-7655-4323-b366-2732ac86e16c
:TAKEN_APPEND_REQUEST: 10de3a5f301761e43ba80988385d9eb180d41fc3025ed1cd66255f80e3c9fa98
:AI_DLOG: 01a109d6-d0ec-70d3-b2cf-2112a6780aa3
:AI_WKT: /home/goodboy/repos/piker
:END:
Draft snapshot: =e815fd77cfbf89b241bfabf19bda7b1c5f25c784=.
- [ ] Wait until upstream branches and their landing order are
settled; preserve a reference to the draft snapshot.
- [ ] Reset/unpack draft commit e815fd77 while retaining the full TC
changeset and preserving unrelated working-tree and staged work.
- [ ] Prepare a proper commit plan for that changeset with coherent
behavior boundaries, matching tests, docs and provenance.
- [ ] Run each boundary's checks and review its diff and message
before recommitting.
** TODO qualify Jev regime judgments against real responses
:PROPERTIES:
:ID: piker-jev-live-regime-qualification
:CREATED: [2026-10-05]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:END:
[[file:/home/goodboy/repos/piker/docs/trend_calculus.rst][Research and prototype guide]]
- [ ] Once TYPESAFE_API_KEY is available and a live request is
authorized, send one small synthetic multi-timeframe request
through the HTTPX/Trio client.
- [ ] Verify the documented request/response schema, model identity,
distributions, usage, errors and measured end-to-end latency.
- [ ] Evaluate useful regime labels and confidence on held-out trend
snapshots, including flat, reversing, aligned and conflicting
timeframes.
- [ ] Measure sustained pacing, coalescing, source freshness and cost
before enabling realtime judgments.
- [ ] Consider an SDK AnyIO port or Trio backend only after the
direct HTTP prototype demonstrates useful classifications.
** TODO connect finalized trends to the Jev provider-service
:PROPERTIES:
:ID: piker-jev-provider-service-integration
:CREATED: [2026-10-05]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:END:
[[file:/home/goodboy/repos/piker/docs/trend_calculus.rst][Research and prototype guide]]
- [ ] Obtain the separate system-1 provider-service repository or
interface and identify its input, output, lifecycle and ownership
contracts.
- [ ] Adapt serve_regimes and RegimeClassifier to the service nursery
and typed publication interface without mixing model labels into
deterministic trend state.
- [ ] Configure market, periods, model, credentials, request pacing,
evidence retention and freshness limits explicitly.
- [ ] Verify reconnect, revision/gap invalidation, backpressure,
stale-response rejection and shutdown with the actual service.
** TODO recover Pine source and check Trend Calculus parity
:PROPERTIES:
:ID: piker-trend-calculus-pine-parity
:CREATED: [2026-10-05]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:ISSUE: https://github.com/pikers/piker/issues/103
:END:
[[file:/home/goodboy/repos/piker/docs/trend_calculus.rst][Research and prototype guide]]
- [ ] Recover the human's Pine implementation and record its
provenance/version alongside the pinned Lua and Scala research.
- [ ] Compare startup seeding, extrema ties, FHLS splitting, opposing
pivots and recursive reversal orders.
- [ ] Add independent fixtures for meaningful semantic differences;
distinguish extremum time from confirmation time and mutable-bar
previews.
** TODO qualify multitimeframe pivots and regime annotations
:PROPERTIES:
:ID: piker-trend-regime-chart-qualification
:CREATED: [2026-10-05]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:END:
[[file:/home/goodboy/repos/piker/docs/trend_calculus.rst][Research and prototype guide]]
- [ ] Inspect actual 1/5/15-second layers and hover information on a
selected live market; compare confirmed pivots and regime
boundaries to finalized source evidence.
- [ ] Verify chart-axis placement, gaps, revisions, hidden charts,
duplicate cached feeds and owner-scoped cleanup.
- [ ] Qualify model rectangles at response receipt and expiry,
including stale classifications and source-segment changes.
- [ ] Measure quiet-bar display delay before deciding whether
publication needs an explicit output notification.
- [ ] Coordinate shared history-overlay lifecycle with the existing
chart-local gap overlay follow-ups; route any annotation IPC
factoring to the existing typed-dialog task.
** TODO qualify a native subsecond source for trend regimes
:PROPERTIES:
:ID: piker-trend-native-subsecond-sampling
:CREATED: [2026-10-05]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker
:AI_BRANCH: trend_calc_on_jev
:END:
[[file:/home/goodboy/repos/piker/docs/trend_calculus.rst][Research and prototype guide]]
- [ ] Define the required high-frequency periods and producer
contract; the numeric/MTF APIs accept fractional periods but the
current native clock uses whole seconds.
- [ ] Extend or select the source/sampler time grid before enabling
subsecond chart/service periods; retain strictly increasing
coordinates and complete aligned buckets.
- [ ] Measure compute, SHM publication, service latency and chart
refresh under the selected cadence, including gaps, replay and
cancellation.
** TODO migrate clearing to strict typed messaging
:PROPERTIES:
:ID: piker-typed-clearing-migration
:CREATED: [2026-10-06]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:AI_HARNESS: codex
:AI_WORKTREE: /home/goodboy/repos/piker/wkts/typed_clearing_protocol
:AI_BRANCH: wkt/typed_clearing_protocol
:END:
[[file:/home/goodboy/repos/piker/wkts/typed_clearing_protocol/plans/opencode/typed-ems-messaging.md::823][Migration plan and commit boundaries]]
Foundation evidence: plan commit 1793b47c and implementation commit
7fee9b86; human reports both pushed. Strict schemas, validation,
directional stream helpers and the pure OrderState reducer are
implemented. Prior qualification: 65 offline tests and eight IPC
tests passed. Production endpoints still use the legacy protocol.
- [ ] Port paper and its paired EMS consumer together.
* [ ] Typed startup, requests, events and open-order completion.
* [ ] Deterministic synthetic ticks and distinct execution IDs.
- [ ] Port Binance, Kraken and IB individually with paired EMS handling.
* [ ] Shared offline conformance and provider translation fixtures.
* [ ] Preserve execution identity, signed positions and account mapping.
- [ ] Integrate OrderState into EMS routing and broker-event handling.
* [ ] Bound pre-ack buffering by age in its asynchronous owner.
* [ ] Preserve cancel intent, fill deduplication and late-event handling.
- [ ] Migrate client/EMS startup, local queues and UI consumers together.
* [ ] Replace wire snapshot mutation and dictionary reconstruction.
- [ ] Enforce each migrated endpoint pair with Tractor payload specs.
* [ ] Narrow receive sets; validate startup, RPC arguments and results.
* [ ] Reject malformed, wrong-direction and wrong-phase messages.
- [ ] Qualify real adapter and actor behavior offline.
* [ ] Cancel-before-ack; early, duplicate and late fills.
* [ ] Empty/populated startup snapshots and two-client order isolation.
* [ ] Abrupt transport EOF, cancellation and bounded failure teardown.
* [ ] Repeated lifecycle tests under supported spawn methods.
- [ ] Resolve the duplicate pytest --ll option before a Tractor pin upgrade.
- [ ] Document the position-broadcast isolation limitation and policy.
- [ ] Remove legacy IPC paths after all paired migrations qualify.
- [ ] Propose a reviewable commit plan for each qualified implementation.
* TODO Qualify chart disconnect and reattach with independent service ownership
:PROPERTIES:
:ID: piker-chart-disconnect-reattach-e2e
:CREATED: [2026-10-20]
:CARRIED: 0
:REPO: /home/goodboy/repos/piker
:CATEGORY: piker.testing
:AI_HARNESS: opencode
:TAKEN_APPEND_OP: piker-chart-disconnect-reattach-e2e-20261020-v2
:TAKEN_APPEND_REQUEST: 5963b29d2e6372c8864831fdee8945a3e064f5084d9abf0331f92c0b5171647c
:END:
Build process-isolated chart journeys that distinguish surviving shared
services and consumers from clean chart exit. Preserve original errors
and deterministic phase evidence; do not declare a journey green merely
because another chart remains usable.
Next action: reconcile the current testing and evaluation branches and
their actual Piker/Tractor imports, then implement a suite-owned pikerd
with independent chart processes. No implementation has started for this
handoff as of this entry; source/state inspection is recorded below.
Context:
Human-directed assignment to e2e_qa_mngr from proj_super. The source
handoff describes proposed tests, not existing runnable nodes:
[[file:/home/goodboy/repos/piker/wkts/ib_downstream_pin_eval/ai/plans/20261019-chart-disconnect-e2e-handoff.md][Chart disconnect and reattach specification and manual evidence]]
Existing foundations, inspected 2026-10-20:
- wkt/live_chart_qtractor at 4ab49082: structured lifecycle 1a2d4893,
prerequisite fixes 5c17419c, opt-in Kraken reproducer 4ab49082.
Application/test work is committed; only local workflow configuration
remains dirty. Use this as the initial working candidate, not proof
that the evaluation fixes are integrated.
- wkt/human_iface_e2e at aadfd1cf is clean and supplies the headless
QApplication isolation foundation.
- wkt/replay_provider_e2e at 06fee700 is clean. Its real feed/control
fixture has acknowledged sequence barriers. The observed disconnect
races justify narrow controlled input, not a replay-first rewrite.
- wkt/ib_downstream_pin_eval remains at eed58566 with dirty dependency,
logger, daemon and EMS compatibility changes.
- wkt/ib_disconnect_integration at c0dae89a contains committed IB
disconnect work; its provenance/tooling state remains dirty.
- Tractor wkt/ctx_final_return_disconnect in address_logging_levels is
at 0553fcf8 with dirty final-Return guard and regression changes.
Read them as candidate evidence, not an already-landed fix.
Reuse tests/ui/conftest.py, the Qtractor lifecycle regression,
tests/conftest.py open_test_pikerd and owned config propagation, and
the replay branch's acknowledged feed controls where applicable.
[[file:/home/goodboy/repos/piker/wkts/live_chart_qtractor/tests/ui/test_live_chart.py][Committed live-chart reproducer]]
[[file:/home/goodboy/repos/piker/wkts/replay_provider_e2e/plans/opencode/live-backend-chart-e2e-review.md][Live-provider-first roadmap]]
The current sanitized live_chart_qtractor interpreter resolves Piker
from that worktree but Tractor from its py313 site-packages; installed
Trio is 0.32.0 and PyQt6 is 6.10.1. This is not the manual evaluation's
Tractor checkout or PyQt6 6.11.0 environment. Resolve exact versions and
module paths again before any comparison. Inspect the duplicate pytest
--ll registration blocker before selecting the evaluation environment.
Concerns and authority:
This assignment does not authorize commits, history changes, live IB
connections, any orders, or attachment to the human's running daemon.
Order journeys may be designed and implemented as gated tests; do not
execute them without explicit authorization. Live-provider qualification
requires explicit selection and applicable human permission.
The existing Kraken run reached history and paper EMS but readiness
preceded rt_linked.mode, Qt reported abstract paint calls, and teardown
left a paperboi child. That exact orphan was subsequently stopped by
human-authorized SIGINT. Guest completion did not prove descendant exit.
Manual IB trials demonstrate daemon/survivor continuity, not clean exit.
Cancellation-only groups, DebugRequestError, hard-reaping and SIGSEGV
remain unresolved. Do not suppress any of these to make E2E green.
Canonical native-crash investigation, separate from this test assignment:
[[id:piker-qt6-chart-teardown-sigsegv][Diagnose Qt6 chart teardown SIGSEGV with native backtraces]]
[[file:../ai/diagnostics/20261019-chart-253598/README.md][SIP wrapper access during PyQt atexit: diagnostics and limits]]
The core locates the native fault; it does not establish the underlying
ownership cause. This task records exit evidence without claiming repair.
Coordinate order replay/cancellation assertions with
[[id:piker-typed-clearing-migration][Strict typed clearing migration]];
do not duplicate its protocol migration or infer it has landed.
Execution:
- [ ] Reconcile source revisions and dirty work before integrating; record
the selected branch, reused fixtures, and exact runtime imports.
- [ ] Own registrar/pikerd A independently of chart processes B and C;
give each chart its own QApplication and Tractor root. Separate discovery
from listener addresses, use a test-unique registry and loopback port
zero, and assert actual chart listeners are nonzero and distinct.
- [ ] Isolate config, storage, settings and account state before imports
in every child; never reuse human ports 6116/3333 or human accounts.
- [ ] Provide an external observation/control channel and owned process
handles that outlive charts. Capture actor UUID/name/PID/listeners,
child relations and exact SHM ownership including unpublished child SHM.
- [ ] Establish readiness after feed/history attachment, bound views,
FSP streams, search handlers and EMS entry. Race waits against original
process/session failure, not only timeouts.
- [ ] Implement same-market alternating departures: ready B/C, close B,
prove the SAME C consumes a post-close quote/FSP update, reopen B,
close C, prove replacement B survives, then close/reopen the last chart.
Add the distinct-market variant to prove sibling-feed independence.
- [ ] Implement last-consumer repeated reattachment to the SAME A and
service/client generations. Compare actual window close, structured
shutdown, root-only SIGINT and terminal-equivalent process-group SIGINT
as separate variants, with PID/PGID ownership recorded before signaling.
- [ ] Drive actual search results with QtBot in the chart worker; compare
visible versus normally dismissed results before detach and reattach.
- [ ] Gate startup cancellation with entered/release acknowledgements at
early acquisition, FSP child bootstrap before imports/registration,
history publication and FSP stream establishment. Hold only C's work,
retain B's progress, permit unwind, and prove a new C can start afterward.
- [ ] Repeat gated startup aborts with no other consumer. Include debug
mode during FSP imports; retain the original interruption independently
from a secondary local-actor IPC stdio-lock DebugRequestError.
- [ ] Implement separately selected order continuity journeys for Piker
paper EMS, IB paper-account broker-routed limits, and EMS-held dark
orders. Execution remains blocked pending explicit order authorization.
Include multi-expiry market-specific dialogs and cancellation of both
order types after reattach.
Verification:
- [ ] Report service survival and chart exit as separate outcomes even
when either fails. Collect survivor evidence after departure errors,
then aggregate originals rather than hiding them behind cleanup.
- [ ] Prove fresh service RPCs and post-action provider data in the same
survivor, including FSP consumption. Deterministic inputs need a matched
sequence; live quotes need not change price. Sampler ticks alone fail.
- [ ] Assert stable service/provider generations, owned child exit and
SHM lifetime according to its actual owner. Shared cached feed SHM may
remain with A; endpoint closure alone does not prove PID exit.
- [ ] Fail clean-exit checks for SIGSEGV/abort, stuck children, hard reap,
unexpected debugger entry and cancellation-only application errors.
Do not blanket-suppress TransportClosed or mixed exception groups.
- [ ] Preserve baseline/fixed results, stdout/stderr, return codes,
source versions, phase acknowledgements, actor/RPC/context identities,
cancellation provenance, and available fault-handler/core evidence.
- [ ] For authorized order qualification, verify canonical OID/reqid
continuity, idempotent replay, market routing, working-order counts,
position continuity and terminal cancellation. Repeated status messages
alone do not prove duplicate orders. Cover reqid 5042-style error replies
with oid=None and the unsubmitted-order-None cancellation symptom.
- [ ] Run each selected tier headlessly with bounded ownership-scoped
cleanup. Preserve fresh-process fixture isolation; no broad process
killing, SHM cleanup, or human-daemon access.
Handback:
Return results to source piker, task piker-chart-disconnect-reattach-e2e:
- Selected implementation branch, exact source revisions and reused
fixtures, including any unintegrated prerequisites.
- Exact implemented runnable test node IDs and synchronization gates;
distinguish proposed names from implemented nodes.
- Baseline/fixed results with service survival and chart/process exit
reported independently, including unresolved failures.
- Remaining coverage gaps, required public/live-IB qualification and
order authorization, linked to the separate native-crash concern.
Use guarded store updates for evidence. Preserve all human-owned task
and checkbox states; passing tests and commits are not acceptance.

View File

@ -1,8 +0,0 @@
version = 1
[[sources]]
id = "piker"
path = "current.org"
repo = ".."
enabled = true
agenda = true

View File

@ -17,21 +17,6 @@ track new integration ideas and proposals in
| Tool | Directory | Status |
|------|-----------|--------|
| [Claude Code](https://github.com/anthropics/claude-code) | [`claude-code/`](claude-code/) | active |
| [OpenCode](https://opencode.ai/) | [`opencode/`](opencode/) | active |
## Shared Skills
Provider-neutral skill bundles should use the portable Agent Skills
subset and live under `.agents/skills/` as their single source.
OpenCode discovers that project directory natively. Relative links in
provider directories such as `.claude/skills/` may bridge clients which
do not yet scan `.agents/skills/`; never copy the skill body.
Existing repo skills under `.claude/skills/` predate this convention
and can migrate separately without coupling their history to new skills.
Harness-specific command files should only delegate to a
shared skill. They must not duplicate the skill body.
## Adding a New Integration
@ -47,7 +32,7 @@ ai/
├── README.md # <- you are here
├── claude-code/
│ └── README.md
├── opencode/
├── opencode/ # future
│ └── README.md
└── <your-tool>/
└── README.md
@ -60,7 +45,6 @@ ai/
- Each integration doc should describe **what**
the skill does, **how** to invoke it, and any
**output** artifacts it produces
- Keep docs concise; link to the shared skill source files
- Keep docs concise; link to the actual skill
source files (under `.claude/skills/`, etc.)
rather than duplicating content
- Keep skill bodies harness-neutral; isolate slash-command
syntax and permissions in each harness integration

View File

@ -1,18 +1,15 @@
# Claude Code Integration
[Claude Code](https://github.com/anthropics/claude-code)
integration for piker's shared coding-harness skills.
skills and workflows for piker development.
## Skills
| Skill | Invocable | Description |
|-------|-----------|-------------|
| [`commit-msg`](#commit-msg) | `/commit-msg` | Generate piker-style commit messages |
| `piker-clearing-expert` | auto | Clearing, order-control, and accounting invariants |
| `piker-conc-expert` | auto | Actor-tree and structured-concurrency invariants |
| `piker-profiling` | auto | `Profiler` API patterns for perf work |
| `piker-slang` | auto | Communication style + slang guide |
| `py-codestyle` | auto | Python source conventions |
| `pyqtgraph-optimization` | auto | Batch rendering patterns |
| `timeseries-optimization` | auto | NumPy/Polars perf patterns |
@ -20,12 +17,8 @@ Skills marked **auto** are background knowledge
applied automatically when Claude detects relevance.
Only `commit-msg` is user-invoked via slash command.
New portable skill source files live under
`.agents/skills/<skill-name>/SKILL.md`. Relative links under
`.claude/skills/` expose them to Claude Code without copying bodies.
Existing pre-migration skills can remain under `.claude/skills/`.
Claude-specific behavior belongs in command or settings files, not
shared skill bodies.
Skill source files live under
`.claude/skills/<skill-name>/SKILL.md`.
---
@ -91,7 +84,8 @@ description context. Examples:
**Footer** (always):
```
(this patch was generated in some part by
`claude-code` using `<model>` (`<provider>`))
[`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
```
### Output Files
@ -100,8 +94,7 @@ After generation, the commit message is written to:
```
.claude/
├── skills/commit-msg/msgs/
│ └── <timestamp>_<hash>_commit_msg.md
├── <timestamp>_<hash>_commit_msg.md # archived
└── git_commit_msg_LATEST.md # latest
```
@ -109,10 +102,18 @@ Where `<timestamp>` is ISO-8601 with seconds and
`<hash>` is the first 7 chars of the current
`HEAD` commit.
Use the latest file with an editor review before commit:
Use the latest file to feed into `git commit`:
```bash
git commit --edit --file .claude/git_commit_msg_LATEST.md
git commit -F .claude/git_commit_msg_LATEST.md
```
Or review/edit before committing:
```bash
cat .claude/git_commit_msg_LATEST.md
# edit if needed, then:
git commit -F .claude/git_commit_msg_LATEST.md
```
### Examples
@ -127,32 +128,56 @@ Add `MktPair.fqme` property for symbol resolution
Factor `.claude/skills/` into proper subdirs
Deats,
- use portable Agent Skills frontmatter
- keep harness commands as thin delegates
- share supporting references across harnesses
- `commit_msg/` -> `commit-msg/` w/ enhanced
frontmatter
- all background skills set `user-invocable: false`
- content split into supporting files
(this patch was generated in some part by
`claude-code` using `<model>` (`<provider>`))
[`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
```
### Shared Frontmatter
### Frontmatter Reference
Skills use the Agent Skills fields understood by both
Claude Code and OpenCode:
The skill's `SKILL.md` uses these Claude Code
frontmatter fields:
```yaml
---
name: commit-msg
description: >
Generate piker-style git commit messages. Use when...
compatibility: Requires git.
metadata:
author: goodboy
version: "1.0"
Generate piker-style git commit messages...
argument-hint: "[optional-scope-or-description]"
disable-model-invocation: true
allowed-tools:
- Bash(git *)
- Read
- Grep
- Glob
- Write
---
```
Live git context is gathered by the skill at execution
time. Claude-only dynamic interpolation and tool-policy
frontmatter are intentionally excluded so another harness
can execute the same workflow.
| Field | Purpose |
|-------|---------|
| `argument-hint` | Shows hint in autocomplete |
| `disable-model-invocation` | Only user can trigger via `/commit-msg` |
| `allowed-tools` | Tools the skill can use |
### Dynamic Context
The skill injects live data at invocation time
via `!`backtick`` syntax in the `SKILL.md`:
```markdown
## Current staged changes
!`git diff --staged --stat`
## Recent commit style reference
!`git log --oneline -10`
```
This means the staged diff stats and recent log
are always fresh when the skill runs -- no stale
context.

View File

@ -1,143 +0,0 @@
# Split `brokerd.<broker>` into trading-only `brokerd` + new `datad.<broker>`
## Context
Today a single `brokerd.<broker>` actor hosts BOTH concerns:
- **data feed service tasks**: the `_FeedsBus` + `open_feed_bus()` ep (`piker/data/feed.py:464`), per-symbol `allocate_persistent_feed()` tasks (shm writers via `sample_and_broadcast()`, history backfill via `piker.tsp`), plus backend eps `stream_quotes`, `open_history_client`, `open_symbol_search`, `get_mkt_info` from `piker/brokers/<backend>/feed.py`/`symbols.py`,
- **live order-control tasks**: `open_trade_dialog()` from `piker/brokers/<backend>/broker.py`, driven by `emsd`.
The codebase already anticipates this split: `piker/data/validate.py:70-91` groups backend eps into `'datad'` vs `'brokerd'` kinds, `piker/brokers/ib/__init__.py:62-70` already declares `_brokerd_mods`/`_datad_mods`, and `piker/brokers/_daemon.py:62` carries the literal TODO *"rename the daemon to datad prolly once we split up broker vs. data tasks into separate actors?"*. This work executes that split.
**User-decided constraints:**
- `datad.<broker>` is a **sibling** of `brokerd.<broker>` under `pikerd`, spawned via the existing `Services` + `maybe_spawn_daemon()` machinery (`piker/service/_daemon.py:46`).
- **Hard cutover, staged by layer** — no dual-mode runtime flag; every stage lands fully working.
- Post-split `brokerd` is **trading-only and lazily spawned solely by emsd's** `open_brokerd_dialog` path; UI/CLI/feed code never spawns it. Chart-only and paper sessions run with **zero** brokerd processes.
## Target topology
```
pikerd
├── datad.ib feed bus, shm writers, tsp history, symbol search
├── brokerd.ib open_trade_dialog only (EMS-spawned, lazy)
├── emsd
│ └── paperboi.ib (paper mode; opens its feed via datad)
└── samplerd
```
## Key verified facts (load-bearing)
- `feed.portals` has exactly ONE trading consumer: `piker/clearing/_ems.py:671` (`portal = feed.portals[brokermod]` → handed to `open_brokerd_dialog`). This is the single coupling forcing feed + trading into one actor.
- `assert 'brokerd' in servicename` at `piker/data/feed.py:502` is the only actor-name assert in the tree.
- `piker ledger` (`piker/accounting/cli.py:100-157`) is a hidden consumer: it calls `broker_init()` directly, spawns its own ad-hoc actor, enters `_setup_persistent_brokerd`, then calls `open_brokerd_dialog(brokermod, portal, ...)` **with an explicit portal** — the new signature must keep a `portal:` override param.
- kraken's feed→broker coupling is mild: `kraken/broker.py:77-81` imports `NoBsWs`/`open_autorecon_ws` (really from `piker.data._web_bs`) and `stream_messages` (pure parser) from `feed.py`. In-process imports only — `enable_modules` gates RPC, not imports. No live shared state; each actor opens its own WS.
- ib: default `client_id=6116` (`ib/api.py:1320`) with linear retry `clientId=client_id + i` (`:1403`). Two ib actors connecting concurrently will collide → needs a role-based id offset. Both daemons need `_spawn_kwargs={'infect_asyncio': True}` (copied by both init fns).
- binance has no `symbols.py` (`get_mkt_info`/`open_symbol_search` live in `binance/feed.py`); kucoin/questrade/robinhood are flat single-file with NO `__enable_modules__`; deribit has no `broker.py`.
- `tests/test_services.py:80,185` assert `brokerd` actor names incl. the paper-mode flow asserting `brokerd.kraken` spawns (`:229,:237`) — must invert post-split.
- `_root_modules` (`piker/service/_actor_runtime.py:156`) must gain the new datad daemon mod so `pikerd_portal.run(spawn_datad, ...)` resolves.
- `piker/brokers/core.py:175` `symbol_search` does `portal.run(search_w_brokerd)` where the target fn lives in `piker.brokers.core` → that mod must stay RPC-enabled in datad.
## Module decision
New file **`piker/data/_daemon.py`** hosts all datad machinery (`_setup_persistent_datad`, `datad_init`, `spawn_datad`, `maybe_spawn_datad`, `_datad_service_mods`). Mirrors the `piker.brokers._daemon` / `piker.data._sampling` (samplerd) per-subsystem convention and satisfies the existing TODO at `brokers/_daemon.py:49` ("move this def to the `.data` subpkg"). `piker.brokers._daemon` keeps brokerd-only code, slimmed. Do NOT over-DRY the two ~40-line init fns into a shared factory yet (samplerd precedent accepts the duplication).
---
## Stage 0 — prep: backend module grouping + ep introspection (no topology change)
1. `piker/data/validate.py`: add a `get_eps(mod, kind) -> dict[str, Callable]` helper returning the backend's defined eps for a daemon-kind from `_eps` (missing eps excluded). Used later by both init fns + fail-fast checks.
2. Declare daemon-kind module groups in each split backend's `__init__.py`, keeping `__enable_modules__` as the (deduped) union so behavior is unchanged:
- `kraken`: `_brokerd_mods = ['api', 'broker']`, `_datad_mods = ['api', 'feed', 'symbols']`
- `binance`: `_brokerd_mods = ['api', 'broker']`, `_datad_mods = ['api', 'feed']`
- `deribit`: `_brokerd_mods = []`, `_datad_mods = ['api', 'feed']`
- `ib`: adjust existing groups so each includes `'api'`
- flat backends (kucoin etc.): no attrs — init fns fall back to enabling just `modpath` (existing behavior).
3. Hygiene: `kraken/broker.py:77-81` imports `NoBsWs`/`open_autorecon_ws` from `piker.data._web_bs` directly (keep the `stream_messages` import from `.feed`).
**Gate**: full pytest green, zero behavior change.
## Stage 1 — introduce `datad` daemon machinery (additive)
New `piker/data/_daemon.py`:
- `_datad_service_mods: list[str]` — datad-always-enabled mods (successor to the data side of `_data_mods` from `brokers/_daemon.py:52`): `['piker.brokers.core', 'piker.brokers.data', 'piker.data', 'piker.data.feed', 'piker.data._sampling', 'piker.data._daemon']`.
- `_setup_persistent_datad(ctx, brokername, loglevel)` — `@tractor.context` fixture; logging boilerplate (as `_setup_persistent_brokerd:81-88`), then allocates the actor-global feed bus exactly as the brokerd fixture does today (`brokers/_daemon.py:105-121`): `assert not feed._bus`, open service nursery, `feed.get_feed_bus(brokername, service_nursery)`, `ctx.started()`, `sleep_forever()`.
- `datad_init(brokername, ...)` — mirrors `broker_init()` (`brokers/_daemon.py:132`): actor name `f'datad.{brokername}'`, copies backend `_spawn_kwargs` (**critical for ib infect_asyncio**), builds `enable_modules` from `getattr(brokermod, '_datad_mods', getattr(brokermod, '__enable_modules__', []))`.
- `spawn_datad(brokername, ...)` — mirrors `spawn_brokerd()` (`brokers/_daemon.py:202`): `Services.actor_n.start_actor(dname, enable_modules=_datad_service_mods + backend_mods, ...)` + `Services.start_service_task(dname, portal, _setup_persistent_datad, ...)`.
- `maybe_spawn_datad(brokername, ...)` — wraps `maybe_spawn_daemon(service_name=f'datad.{brokername}', service_task_target=spawn_datad, ...)` exactly like `maybe_spawn_brokerd` (`brokers/_daemon.py:256`).
Supporting edits:
- `piker/service/_actor_runtime.py:156`: add `'piker.data._daemon'` to `_root_modules` (keep `'piker.brokers._daemon'`).
- `piker/service/__init__.py`: re-export `spawn_datad`/`maybe_spawn_datad` next to the brokerd ones (`:56-57`).
- `tests/test_services.py`: new `test_datad_spawn` — `open_test_pikerd` + `maybe_spawn_datad('kraken')` + `ensure_service('datad.kraken')`. (Do NOT route a feed through it yet — `open_feed_bus`'s assert still says brokerd.)
**Gate**: suite green + new spawn test; nothing routes through datad yet.
## Stage 2 — clearing layer: emsd self-spawns brokerd (decouple from `feed.portals`)
Sequenced BEFORE the feed cutover so live trading works at every boundary (otherwise `feed.portals` would hand emsd a datad portal).
`piker/clearing/_ems.py`:
1. `open_brokerd_dialog()` (`:336`) new signature: `(brokermod, exec_mode, fqme=None, portal: tractor.Portal|None = None, loglevel=None)`. Internals: keep trades-ep detection (`:400-417`); acquire the brokerd actor ONLY when a live ep will actually open, via a small inner `@acm _acquire_live_portal()` that yields the passed `portal` if given (the `piker ledger` path) else `async with maybe_spawn_brokerd(brokermod.name, loglevel=loglevel)` — **the single place brokerd boots post-split**. Move the eager `portal.open_context(trades_endpoint, ...)` construction (`:425`) inside that block; the paper short-circuit (`:432`) never touches it.
2. `Router.maybe_open_brokerd_dialog()` (`:581`) — drop the `portal` param; `Router.open_trade_relays()` (`:640`) — delete `portal = feed.portals[brokermod]` (`:671`) and the pass-through (`:685`).
3. `piker/accounting/cli.py:144`: switch to keyword form `open_brokerd_dialog(brokermod, exec_mode=..., portal=portal, loglevel=...)`.
Pre-cutover this is a pure refactor: emsd's `maybe_spawn_brokerd` just *finds* the already-running brokerd via the registry.
**Gate**: `tests/test_ems.py` + services suite green; manual paper order on kraken; `piker ledger` smoke.
## Stage 3 — feed layer hard cutover to datad
1. `piker/data/feed.py`: import `maybe_spawn_datad` (replacing `maybe_spawn_brokerd`, `:56-58`); `open_feed()` `:895` → `maybe_spawn_datad(...)` (rename `brokerd_ctxs` → `datad_ctxs`); `open_feed_bus()` `:502` → `assert 'datad' in servicename`; comment sweep.
2. `piker/brokers/_daemon.py` `_setup_persistent_brokerd()`: slim to trading-only fixture — logging setup, `ctx.started()`, `sleep_forever()`. Drop the bus alloc, `assert not feed._bus`, the service nursery (backend `open_trade_dialog` ctxs own their task trees), the `eg.ExceptionGroup` handler, and the stale `_FeedsBus` TYPE_CHECKING import. (`piker ledger`'s ad-hoc actor enters this same slimmed fixture — exactly what it needs.)
3. Repoint remaining data-flavored spawn sites `maybe_spawn_brokerd` → `maybe_spawn_datad`:
- `piker/ui/_app.py:40,57` (symbol search; optionally rename `install_brokerd_search` → `install_datad_search`, def at `piker/data/feed.py:766`)
- `piker/brokers/core.py:33,175` (`symbol_search`)
- `piker/brokers/cli.py:38,190,320` (`brokercheck`, `record`)
- `piker/ui/cli.py:30,72,121` (legacy kivy monitor/optschain) + best-effort `piker/ui/kivy/option_chain.py:498` `wait_for_actor('brokerd')` → `'datad'`
4. `tests/test_services.py`: `:80,:185` `actor_name = 'datad'`; paper-mode test asserts `datad.kraken` + `paperboi.kraken` + `emsd` AND adds the headline negative check: `assert 'brokerd.kraken' not in services.service_tasks`.
**Gate**: full suite with inverted assertions; manual: chart on binance/kraken shows `datad.<broker>` in `piker services` and NO brokerd; paper order fills; symbol search works; history backfill sane.
## Stage 4 — caps-sec slimming, validation, ib client-id
1. `piker/brokers/_daemon.py`: delete `_data_mods` (`:52`); `spawn_brokerd()` `:236` → `enable_modules=tractor_kwargs.pop('enable_modules')`; `broker_init()` `:184` reads `getattr(brokermod, '_brokerd_mods', getattr(brokermod, '__enable_modules__', []))`. Resulting brokerd enable set has no `piker.data.*` at all.
2. Fail-fast ep validation via Stage-0 `validate.get_eps()`: `broker_init` raises a clear error when `get_eps(mod, 'brokerd')` is empty (e.g. "kucoin is datad-only — use paper mode"); `datad_init` warns analogously.
3. ib client-id mitigation in `load_aio_clients()` (`ib/api.py:~1316`): role-based offset when `client_id` is the 6116 default (e.g. `+16` when `'datad' in tractor.current_actor().name`), optionally configurable via `brokers.toml` keys.
4. Docs/comment sweep: resolve `brokers/_daemon.py:62` TODO, `piker/cli/__init__.py:253` TODO, daemon list in `piker/service/__init__.py:21` docstring.
**Gate**: full suite; audit greps clean: `grep -rn maybe_spawn_brokerd piker/` hits only `clearing/_ems.py`, `service/__init__.py`, `brokers/_daemon.py`; no spawn-path `'brokerd'` literals left in `piker/data`, `piker/ui`, `piker/brokers/cli.py`.
---
## Risk register
| Risk | Sev | Mitigation |
|---|---|---|
| ib: `datad.ib` + `brokerd.ib` both connect to TWS/gw; `client_id=6116` collision burns `connect_timeout` retries | High (live ib only) | Stage 4 role-based id offset; both daemons inherit `infect_asyncio` via `_spawn_kwargs` copy in both init fns |
| `piker ledger` ad-hoc actor path silently broken by signature change | Med | `portal:` override kept on `open_brokerd_dialog` (Stage 2); explicit smoke test |
| datad-only backends (kucoin/deribit) → useless brokerd spawn | Low | already covered: `open_brokerd_dialog` forces `exec_mode='paper'` when no trades ep (`_ems.py:413-417`) BEFORE the lazy spawn; Stage 4 fail-fast |
| brokerd in-process symbology/ledger needs (ib `broker.py` imports `.symbols`; kraken uses `stream_messages`) | None | verified pure in-process imports; `enable_modules` gates RPC only |
| paper-mode test asserts brokerd spawns (`test_services.py:237`) | Low | Stage 3 deliberately inverts it |
| doubled per-broker clients (HTTP/WS, symcache loads) | Low | each actor already opens its own WS today; symcache is disk-read-mostly |
## Verification (per stage gates above, plus end-to-end)
- `pytest tests/test_services.py tests/test_feeds.py tests/test_ems.py` at every stage (kraken/binance public endpoints, no creds needed).
- Manual smoke matrix post-Stage-3: `pikerd -l info` + `piker chart btcusdt.spot.binance` → `piker services` shows `datad.binance`, no brokerd; submit paper order → `paperboi.binance` appears, still no brokerd; symbol search; `piker ledger <broker>.paper`.
- If ib creds/gateway available: live ib chart + small live order to exercise dual-actor client-id path (Stage 4).
## Critical files
- **new** `piker/data/_daemon.py` — all datad machinery
- `piker/brokers/_daemon.py` — slimmed brokerd fixture/init/spawn
- `piker/data/feed.py` — spawn cutover + actor-name assert
- `piker/clearing/_ems.py` — emsd lazy brokerd spawn (`open_brokerd_dialog`, `Router`)
- `piker/service/_actor_runtime.py`, `piker/service/__init__.py` — root mods + re-exports
- `piker/data/validate.py` — `get_eps()` helper
- backend `__init__.py`s (kraken/binance/deribit/ib) — `_datad_mods`/`_brokerd_mods`
- `piker/accounting/cli.py` — keyword-form dialog call
- `tests/test_services.py` — inverted + new assertions

View File

@ -1,55 +0,0 @@
# OpenCode Integration
[OpenCode](https://opencode.ai/) discovers provider-neutral skills
directly from `.agents/skills/` and pre-migration piker skills from
`.claude/skills/`. There is no second copy of each skill to keep in
sync.
## Available Skills
| Skill | Activation | Specialization |
|-------|------------|----------------|
| `commit-msg` | `/commit-msg` or explicit request | Piker commit-message style and artifacts |
| `piker-clearing-expert` | automatic | Clearing, order-control, and accounting invariants |
| `piker-conc-expert` | automatic | `tractor` actor topology, RPC, and cancellation |
| `piker-profiling` | automatic | Cross-actor `Profiler` instrumentation |
| `piker-slang` | automatic | Project communication style |
| `py-codestyle` | automatic | Python source conventions |
| `pyqtgraph-optimization` | automatic | Batched Qt graphics rendering |
| `timeseries-optimization` | automatic | NumPy and Polars timeseries performance |
OpenCode's project command lives at
`.opencode/commands/commit-msg.md`. It delegates to the
shared `commit-msg` skill and only supplies command
arguments; workflow logic remains in the skill.
A user-local skill with the same name may override a repo
skill. Treat `opencode debug skill` as authoritative when
diagnosing which source is active.
## Verify Discovery
From the repository root:
```console
opencode debug skill
opencode debug config
```
`opencode debug skill` should list the piker skills from
the project checkout. Restart OpenCode after changing a
skill or command because configuration-time files are not
hot-reloaded into an active session.
## Portability Rules
- Use only portable Agent Skills frontmatter in shared
`SKILL.md` files.
- Keep harness-specific command syntax under
`.opencode/commands/`.
- Detect the active harness and model at runtime; do not
hardcode Claude Code attribution in shared workflows.
- Keep supporting references beside each shared skill so
relative links resolve in every harness.
- Put new provider-neutral bundles under `.agents/skills/`; use
relative provider links only when a harness requires one.

View File

@ -1,34 +0,0 @@
---
created_at: 2026-10-03T00:18:37.208688+00:00
generated_by:
harness: codex
provider: openai
model: gpt-6
git_ref: 9115d24
scope: data
substantive: true
raw_file: 20261003T001837Z_9115d24_project_stores.raw.md
---
## Prompt
Split the LNS working corpus into per-repository federated stores on
open-wkt branches and connect them to one global storespace. Preserve
human task states. Add a local agent workflow, update taken-export,
and design rollover, supervised concurrency, activity and ranked views.
## Response summary
Create the repository's migration branch and preserve its imported
scope, with revision-aware local source configuration and a shared
local taken skill. Keep original checkout stores and indexes intact.
Existing live branch stores remain independently registered. The LNS
manifest and migration ledger describe the authoritative split paths.
## Human edits
The human chose the per-repo split and worktree delivery, authorized
local auto-mode, and required supervisor-based locking: the supervisor
owns write authority and can revoke delegated human/subagent edit
grants through cancellation. The agent applied these directions.
No task/checkbox acceptance changes or Git commits were authorized.

View File

@ -1,36 +0,0 @@
---
created_at: 2026-10-03T00:18:37.208688+00:00
generated_by:
harness: codex
provider: openai
model: gpt-6
git_ref: 9115d24
scope: data
substantive: true
raw_file: 20261003T001837Z_9115d24_project_stores.raw.md
---
## Prompt excerpts
“break it up into appropriate per repo federated store files”
“intro the sub-store updates each on /open-wkt branches”
“a concise entrypoint to view all sub-project repo's federated stores”
“supervisor based locking”
“an edit capability can only be acquired from the supervisor”
“a human editor can be cancelled from their write access”
## Generated output (diff reference)
> `git diff HEAD~1..HEAD -- .taken/current.org`
Create the repository's migration branch and preserve its imported
scope, with revision-aware local source configuration and a shared
local taken skill. Keep original checkout stores and indexes intact.
Existing live branch stores remain independently registered. The LNS
manifest and migration ledger describe the authoritative split paths.
## Explanation
The global launch now works: one Neovim window shows all 13 sources,
with normal highlighting and the new help menu. The full AI export
reports complete coverage with no diagnostics.

View File

@ -1,59 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:08:59Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T170859Z_75cefe10_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T170859Z_75cefe10_prompt_io.raw.md
---
## Prompt
Session-initiating instruction (driving all 7 commits in
this series):
> ok i want you to become the distributed runtime and
> concurrency expert for this project - namely acquire
> a deep understanding of tractor and how it's used.
> then i want you to attempt to factor our current
> brokerd service daemon into 2 daemons: a brokerd
> which only hosts live/paper trading endpoint tasks
> [..] a new `datad` subdaemon which in a separate
> subactor serves all the data feed service tasks [..]
> give me a mega detailed plan on how to approach this,
> and a staged approach for the implementation.
Proximate driver for THIS commit: during the approved
plan's stage-0 test gate the agent discovered test
subactors were writing into the user's REAL
`~/.config/piker/accounting/` files (a bogus paper fill
landed in `account.kraken.paper.toml`) because the old
test-dir override in `config.get_app_dir()` was
commented out and could never work in spawned
subactors anyway. Fix applied autonomously under the
approved plan; no explicit per-fix user prompt.
## Response summary
Restore `pytest` config-dir isolation by resolving the
per-test tmp dir lazily (at conf-path access time) from
`tractor` runtime-vars, which propagate down the actor
tree; route all conf-path derivation through
`config.get_conf_dir()` so the override is effective in
every (sub)actor.
## Files changed
- `piker/config.py` — add `_maybe_use_test_dir()`;
hook in `get_conf_dir()`; route `get_conf_path()` +
`load()` mkdir through it
- `piker/accounting/_ledger.py` — derive ledger dir
via `config.get_conf_dir()` (not the global)
- `piker/accounting/_pos.py` — same for account files
## Human edits
None — committed as generated.

View File

@ -1,46 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:08:59Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T170859Z_75cefe10_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/config.py`
Generated: `config._maybe_use_test_dir()` — lazily
reads `piker_test_dir` from
`tractor.runtime._state._runtime_vars['piker_vars']`
(pre-loaded by `open_piker_runtime()` from the
`tests.conftest._open_test_pikerd()` overrides) and
calls `_override_config_dir()` when set. Hooked at the
top of `get_conf_dir()`; `get_conf_path()` and
`load()`'s dir-creation rerouted through
`get_conf_dir()`.
> `git log -1 -p --follow -- piker/accounting/_ledger.py`
> `git log -1 -p --follow -- piker/accounting/_pos.py`
Generated: ledger/account dir derivation switched from
the `config._config_dir` module global to
`config.get_conf_dir()` + `mkdir(parents=True,
exist_ok=True)` for nested tmp-dir creation.
Key diagnostic reasoning (verbatim from session):
The old (commented-out) `get_app_dir()` override gated
on `'pytest' in sys.modules` which can NEVER work in
spawned subactors (fresh procs, no pytest import); as
a result test `paperboi`/daemon actors were writing
into the user's REAL `~/.config/piker/accounting/`
files. Evidence: `account.kraken.paper.toml` gained a
single 0.001 xbtusdt clear stamped 2026-06-09T18:47Z
(a test fill), and `trades_kraken_paper.toml` (252B)
contained only that fill. The resolution must be
checked lazily at config-path access time (NOT import
time) since sub-actors only receive runtime-vars once
their `tractor` runtime has fully booted.

View File

@ -1,53 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:10:22Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T171022Z_4485f2b9_prompt_io.raw.md
---
## Prompt
Same session-initiating `brokerd`-split instruction (see
`20260610T170859Z_75cefe10_prompt_io.md`). Proximate
driver: the approved plan's per-stage test gates could
not run AT ALL — the branch base was broken vs.
`tractor` git `main` (`AttributeError: 'tuple' object
has no attribute 'unwrap'` at `pikerd` boot, stale
`arbiter_sockaddr`/`.type`/`.size` API refs). The agent
fixed forward autonomously to (re)establish the gate
baseline, continuing the `repair_tests` branch lineage
(verified already merged in ancestry via `git cherry`
during a user-requested branch-overlap survey).
## Response summary
Port the service layer + test suites to current
`tractor` APIs: addr-type normalization in
`open_pikerd()`, `query_actor()`/`wait_for_actor()`
kwarg renames, modern self-cancel absorption semantics
in the cancel-method test harness, exc/position attr
renames, a paper-EMS startup-budget bump and a syntax
fix in `.deribit.api`.
## Files changed
- `piker/service/_actor_runtime.py` — `wrap_address()`
normalize before `.unwrap()` in `open_pikerd()`
- `piker/service/_registry.py` — `check_for_service()`
-> `query_actor(regaddr=)` + 2-tuple yield +
`open_registry(addrs=)`
- `piker/brokers/deribit/api.py` — missing comma in
`tractor.trionics` import tuple
- `tests/test_services.py` — `registry_addr=` kwarg,
raddr unwraps, cancel-semantics harness rewrite,
`fail_after` 9 -> 19s
- `tests/test_ems.py` — `.boxed_type`, `pp.cumsize`
## Human edits
None — committed as generated.

View File

@ -1,56 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:10:22Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/service/_actor_runtime.py`
Generated: normalize each registry addr via
`tractor.discovery._addr.wrap_address()` before
`.unwrap()`-ing for the `accept_addrs` bind check —
entries may be raw `tuple`s when passed in from (test)
client code. Import-path precedent taken from
`piker/cli/__init__.py:336`.
> `git log -1 -p --follow -- piker/service/_registry.py`
Generated: `check_for_service()` ported to
`tractor.query_actor(name, regaddr=...)` (kwarg was
`arbiter_sockaddr=`), unpacking the new
`(sockaddr, portal)` yield, and passing the
now-required `open_registry(addrs=Registry.addrs)`.
> `git log -1 -p --follow -- tests/test_services.py`
> `git log -1 -p --follow -- tests/test_ems.py`
> `git log -1 -p --follow -- piker/brokers/deribit/api.py`
Key diagnostic reasoning (verbatim from session):
- the "DID NOT RAISE ContextCancelled" failure: in this
test the client actor IS pikerd (in-proc), and
current `tractor` main absorbs a `ContextCancelled`
whose canceller is your own actor — self-requested
cancels now exit cleanly instead of raising; the
'sigint' variant propagates a bare collapsed
`KeyboardInterrupt` rather than a
`BaseExceptionGroup`.
- the hard-coded `trio.fail_after(9)` startup budget is
marginal — full stack boot (pikerd -> emsd ->
brokerd.kraken -> paperboi + live kraken symbology
fetch) occasionally exceeds 9s -> bumped to 19s.
- `RemoteActorError.type` -> `.boxed_type`;
`Position.size` -> `.cumsize` (the paper engine
populates `BrokerdPosition.size` from `pp.cumsize`).
- overlap survey (user-requested): all of the
`repair_tests` branch commits are already in this
stack's ancestry; this commit finishes that branch's
port mission (its f4c4f1e2 fixed `conftest.py`'s
`arbiter_sockaddr` usage; this fixes the remaining
`test_services.py` + `check_for_service()` sites).

View File

@ -1,54 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:11:05Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171105Z_bc6e18d7_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T171105Z_bc6e18d7_prompt_io.raw.md
---
## Prompt
Same session-initiating `brokerd`-split instruction (see
`20260610T170859Z_75cefe10_prompt_io.md`); this is the
approved plan's "stage 0" prep. Plan-shaping user
decisions captured via in-session Q&A:
- `datad.<broker>` topology: sibling of
`brokerd.<broker>` under `pikerd` (vs. child
subactor).
- migration: hard cutover, staged by layer (no
dual-mode runtime flag).
- post-split `brokerd` scope: trading-only +
EMS-lazy-spawned (charts/CLI never touch it).
## Response summary
Declare per-daemon-kind backend submod groups
(`_datad_mods`/`_brokerd_mods`) in the split-style
backends, keyed to the pre-existing
`piker.data.validate._eps` contract; add a
`validate.get_eps()` introspection helper; ws-import
hygiene in `.kraken.broker`. Zero behavior change
(`__enable_modules__` unions unchanged).
## Files changed
- `piker/data/validate.py` — add `get_eps()`
- `piker/brokers/kraken/__init__.py` — mod groups
- `piker/brokers/binance/__init__.py` — mod groups
(note: no `symbols.py`; search eps live in `.feed`)
- `piker/brokers/deribit/__init__.py` — datad-only
groups (no `broker.py` yet)
- `piker/brokers/ib/__init__.py` — add `'api'` to the
pre-existing `_datad_mods`
- `piker/brokers/kraken/broker.py` — import
`NoBsWs`/`open_autorecon_ws` from
`piker.data._web_bs` directly
## Human edits
None — committed as generated.

View File

@ -1,46 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:11:05Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171105Z_bc6e18d7_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/data/validate.py`
Generated: `get_eps(mod, kind) -> dict[str, Callable]`
returning the daemon-kind's ep funcs defined by a
backend mod, keyed by ep name, missing eps excluded;
sourced from the existing `_eps` grouping table
(`'middleware' | 'datad' | 'brokerd'`).
> `git log -1 -p --follow -- piker/brokers/kraken/__init__.py`
> `git log -1 -p --follow -- piker/brokers/binance/__init__.py`
> `git log -1 -p --follow -- piker/brokers/deribit/__init__.py`
> `git log -1 -p --follow -- piker/brokers/ib/__init__.py`
> `git log -1 -p --follow -- piker/brokers/kraken/broker.py`
Key exploration findings driving the design (from the
planning phase, 3 parallel explore agents + 1 architect
agent):
- the codebase already anticipated this split:
`validate._eps` groups eps into 'datad' vs 'brokerd'
kinds and `ib/__init__.py` already declared
`_brokerd_mods`/`_datad_mods`; `brokers/_daemon.py`
carried the literal TODO "rename the daemon to datad
prolly once we split up broker vs. data tasks into
separate actors?".
- the feared kraken feed<->broker "shared ws state"
hazard is mild: `NoBsWs`/`open_autorecon_ws`
originate in `piker.data._web_bs` (re-exported via
`.kraken.feed`); only `stream_messages` is feed-local
and it's a pure parser — in-process imports only,
each actor opens its own ws conn.
- `enable_modules` gates RPC entry, NOT python imports,
so backend trading mods may keep importing feed-side
helpers in-process post-split.

View File

@ -1,47 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:11:42Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171142Z_119d2c04_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T171142Z_119d2c04_prompt_io.raw.md
---
## Prompt
Same session-initiating `brokerd`-split instruction (see
`20260610T170859Z_75cefe10_prompt_io.md`); this is the
approved plan's "stage 1": introduce the `datad` daemon
machinery additively (nothing routes through it yet).
User-decided constraint applied: `datad.<broker>` is a
SIBLING of `brokerd.<broker>` under `pikerd`, spawned
via the existing `Services` + `maybe_spawn_daemon()`
machinery.
## Response summary
New `piker/data/_daemon.py` hosting the
`datad.<broker>` feed-only daemon-actor: lifetime
fixture owning the actor-global `_FeedsBus`, init/spawn
fns mirroring `.brokers._daemon` conventions and the
`samplerd` sub-daemon precedent, plus root-mod
registration, `piker.service` re-exports and a spawn
test.
## Files changed
- `piker/data/_daemon.py` — NEW:
`_setup_persistent_datad()`, `datad_init()`,
`spawn_datad()`, `maybe_spawn_datad()`,
`_datad_service_mods`
- `piker/service/_actor_runtime.py` — add
`piker.data._daemon` to `_root_modules`
- `piker/service/__init__.py` — re-export spawn eps
- `tests/test_services.py` — add `test_datad_spawn`
## Human edits
None — committed as generated.

View File

@ -1,60 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:11:42Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171142Z_119d2c04_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/data/_daemon.py`
Generated symbols + key design decisions:
- `_datad_service_mods: list[str]` — datad-always
enabled mods, the data-side successor to the old
`piker.brokers._daemon._data_mods` set; kept minimal
per the caps-sec model.
- `_setup_persistent_datad()` — `@tractor.context`
lifetime fixture: console-log setup then allocates
the actor-global feed bus via
`feed.get_feed_bus(brokername, service_nursery)`
exactly as the old brokerd fixture did, pinned open
with `ctx.started()` + `sleep_forever()`.
- `datad_init()` — actor name `f'datad.{brokername}'`;
copies backend `_spawn_kwargs` (CRITICAL for `ib`'s
`infect_asyncio=True`); builds `enable_modules` from
`getattr(brokermod, '_datad_mods',
getattr(brokermod, '__enable_modules__', []))` as
the flat-backend fallback.
- `spawn_datad()` — `Services.actor_n.start_actor()` +
`Services.start_service_task()` exactly mirroring
`spawn_brokerd()`; dedup-composes enable mods via
`list(dict.fromkeys(...))`.
- `maybe_spawn_datad()` — wraps `maybe_spawn_daemon(
service_name=f'datad.{brokername}', ...)`.
> `git log -1 -p --follow -- piker/service/_actor_runtime.py`
> `git log -1 -p --follow -- piker/service/__init__.py`
> `git log -1 -p --follow -- tests/test_services.py`
Design rationale (verbatim from session):
- `_root_modules` must gain `piker.data._daemon` so
`pikerd_portal.run(spawn_datad, ...)` resolves in
the root.
- the `Services`-based impl style deliberately mirrors
`spawn_brokerd()` so the eventual `tractor.hilevel`
`ServiceMngr` port (see the `service_mng_to_tractor`
branch's d8c21d44 prep, surfaced by the
user-requested branch-overlap survey) lands
symmetrically on both spawn fns.
- mod placement (`piker/data/_daemon.py` vs.
generalizing `piker.brokers._daemon`) follows the
per-subsystem daemon-mod convention
(`.clearing._ems`, `.data._sampling`) and resolves
the existing TODO at `brokers/_daemon.py:49` ("move
this def to the `.data` subpkg").

View File

@ -1,47 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:12:26Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171226Z_64181219_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T171226Z_64181219_prompt_io.raw.md
---
## Prompt
Same session-initiating `brokerd`-split instruction (see
`20260610T170859Z_75cefe10_prompt_io.md`); this is the
approved plan's "stage 2": decouple the clearing layer
from `feed.portals` BEFORE the feed cutover so live
trading works at every stage boundary. User-decided
constraint applied: post-split `brokerd` is
trading-only and spawned LAZILY only by `emsd`'s
`open_brokerd_dialog()` path.
## Response summary
Kill the single coupling forcing feed + trading eps
into one actor (`Router.open_trade_relays()` pulling
its trades portal from `feed.portals[brokermod]`):
`open_brokerd_dialog()` now (maybe) spawns/finds
`brokerd.<broker>` itself and ONLY when a live
trades-ep will actually open; paper mode never touches
it. Pre-cutover this is a pure refactor (registry
lookup finds the same feed-spawned daemon).
## Files changed
- `piker/clearing/_ems.py` — `open_brokerd_dialog()`
re-sig + inner `acquire_live_portal()`;
`Router.maybe_open_brokerd_dialog()` drops `portal`
param; `open_trade_relays()` drops the
`feed.portals` lookup
- `piker/accounting/cli.py` — keyword-form `portal=`
override kept for the `piker ledger` ad-hoc actor
## Human edits
None — committed as generated.

View File

@ -1,43 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:12:26Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171226Z_64181219_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/clearing/_ems.py`
Generated: new `open_brokerd_dialog()` signature
`(brokermod, exec_mode, fqme=None, portal=None,
loglevel=None)` with an inner `@acm
acquire_live_portal()` that yields the caller-provided
`portal` override (the `piker ledger` path) else
`maybe_spawn_brokerd(brokermod.name)` — designated THE
one place a live, credentialed `brokerd.<broker>` gets
booted post-split. The eager
`portal.open_context(trades_endpoint, ...)`
construction moved inside that block so the paper
short-circuit never acquires a live portal.
> `git log -1 -p --follow -- piker/accounting/cli.py`
Key analysis (verbatim from session):
- `feed.portals` had exactly ONE trading consumer:
`piker/clearing/_ems.py:671` (`portal =
feed.portals[brokermod]`) — the single coupling
forcing feed + trading into one actor.
- `piker ledger` (`accounting/cli.py:100-157`) is a
hidden consumer: it calls `broker_init()` directly,
spawns its own ad-hoc actor and passes the portal
positionally — the new signature must keep an
explicit `portal:` override param for this path.
- stage sequencing: clearing decouple lands BEFORE the
feed cutover, otherwise `feed.portals` would hand
emsd a `datad` portal and live `open_trade_dialog`
RPC would fail.

View File

@ -1,48 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:12:59Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171259Z_59d5d9a6_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T171259Z_59d5d9a6_prompt_io.raw.md
---
## Prompt
Same session-initiating `brokerd`-split instruction (see
`20260610T170859Z_75cefe10_prompt_io.md`); this is the
approved plan's "stage 3": the feed-layer hard cutover
(user-decided: no dual-mode runtime flag, each stage
lands fully working).
## Response summary
The topology flip: all data-feed consumers route to
`datad.<broker>`; the `brokerd` lifetime fixture slims
to trading-only; UI/CLI data-flavoured spawn sites
repointed; test expectations inverted incl. an explicit
negative assert that paper sessions spawn NO
`brokerd.<broker>`.
## Files changed
- `piker/data/feed.py` — `open_feed()` ->
`maybe_spawn_datad()`; `open_feed_bus()` actor-name
assert -> `'datad'`; `install_brokerd_search` ->
`install_datad_search`; comment sweep
- `piker/brokers/_daemon.py` —
`_setup_persistent_brokerd()` slimmed (feed-bus
alloc moved to the datad fixture)
- `piker/ui/_app.py`, `piker/ui/cli.py`,
`piker/brokers/core.py`, `piker/brokers/cli.py`,
`piker/ui/kivy/option_chain.py` — spawn-site
repoints
- `tests/test_services.py` — datad assertions + the
no-`brokerd.kraken` negative check
## Human edits
None — committed as generated.

View File

@ -1,54 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:12:59Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171259Z_59d5d9a6_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/data/feed.py`
Generated: `open_feed()` spawn cutover with the
`maybe_spawn_datad` import done "relative-direct" from
`._daemon` — NOT via `piker.service` — to dodge a
partial-init cycle: when `piker.data.feed` loads as
part of `piker.service.__init__` executing its own
`piker.data._daemon` import, the service pkg is
mid-init and its `maybe_spawn_datad` binding does not
exist yet. The `open_feed_bus()` local-state sanity
assert flips `'brokerd' in servicename` ->
`'datad' in servicename` (the only actor-name assert
in the tree, verified by grep).
> `git log -1 -p --follow -- piker/brokers/_daemon.py`
Generated: `_setup_persistent_brokerd()` slimmed to
console-log setup + pinned-open ctx; drops the bus
alloc, the `assert not feed._bus`, the service nursery
(backend `open_trade_dialog()` ctxs own their task
trees) and the `eg.ExceptionGroup` handler. The
`piker ledger` ad-hoc actor enters this same slimmed
fixture — exactly what it needs.
> `git log -1 -p --follow -- piker/ui/_app.py`
> `git log -1 -p --follow -- piker/ui/cli.py`
> `git log -1 -p --follow -- piker/brokers/core.py`
> `git log -1 -p --follow -- piker/brokers/cli.py`
> `git log -1 -p --follow -- piker/ui/kivy/option_chain.py`
> `git log -1 -p --follow -- tests/test_services.py`
Verification (from session): per-suite gates green at
this commit (services 5-passed incl. the new negative
assert, feeds 3-passed); a headless live smoke
(`maybe_open_pikerd` + `open_feed(['xbtusdt.kraken'])`
on an alt registry port) confirmed quotes flowing via
`datad.kraken` + `samplerd` with `check_for_service(
'brokerd.kraken') is None`. Known pre-existing flake
documented: `test_multi_fill_positions`' second
in-proc runtime boot wedges ~50% (zombie subactor w/
unread parent-IPC bytes); reproduced with the split
fully reverted so NOT a regression of this work.

View File

@ -1,43 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:13:44Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171344Z_eee19de0_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T171344Z_eee19de0_prompt_io.raw.md
---
## Prompt
Same session-initiating `brokerd`-split instruction (see
`20260610T170859Z_75cefe10_prompt_io.md`); this is the
approved plan's final "stage 4": caps-sec slimming of
the (live, credentialed) trading actor + the `ib`
dual-daemon `client_id` collision mitigation flagged in
the plan's risk register.
## Response summary
`brokerd` loses ALL `piker.data.*` (feed) RPC mods;
spawn fails fast for datad-only backends with a "use
paper-mode" error; `ib`'s default api-gw `client_id`
gets a per-daemon-kind offset so `datad.ib` +
`brokerd.ib` don't collide on connect.
## Files changed
- `piker/brokers/_daemon.py` — `_data_mods` -> minimal
`_brokerd_service_mods`; `broker_init()` reads
`_brokerd_mods` (fallback `__enable_modules__`);
`spawn_brokerd()` fail-fast via `validate.get_eps()`
- `piker/brokers/ib/api.py` — role-based `client_id`
offset in `load_aio_clients()`
- `piker/cli/__init__.py` — resolved "expose datad"
TODO
## Human edits
None — committed as generated.

View File

@ -1,41 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:13:44Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171344Z_eee19de0_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); backfilled from the live dev
session transcript per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/brokers/_daemon.py`
Generated: the fail-fast originally landed in
`broker_init()` but was relocated to `spawn_brokerd()`
mid-implementation after realizing `piker ledger`
calls `broker_init()` directly even for paper accounts
on datad-only backends (would have crashed the cli);
the service-spawn path is the correct enforcement
seam. Error text:
Backend 'kucoin' offers NO `brokerd` (live
order-control) eps!? It is likely a datad-only
provider, use paper-mode for clearing instead.
(verified live via a `trio.run()` unit check.)
> `git log -1 -p --follow -- piker/brokers/ib/api.py`
Generated: in `load_aio_clients()`, when `client_id`
is the 6116 default: `datad`-named actors offset +16
(disjoint from `brokerd`'s linear `client_id + i`
retry range), other non-`brokerd` (ad-hoc test/cli)
actors +32. Rationale from the plan's risk register:
post-split BOTH per-broker daemons connect to the same
TWS/gw endpoint; a shared default id collides and
burns up to `connect_timeout * retries` (90s) in
retry cycles.
> `git log -1 -p --follow -- piker/cli/__init__.py`

View File

@ -1,66 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T17:33:09Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T173309Z_f15f8178_prompt_io.md
scope: docs
substantive: true
raw_file: 20260610T173309Z_f15f8178_prompt_io.raw.md
---
## Prompt
The session-initiating instruction, verbatim (this doc
IS its "mega detailed plan" deliverable):
> ok i want you to become the distributed runtime and
> concurrency expert for this project - namely acquire
> a deep understanding of tractor and how it's used.
> then i want you to atttempt to factor our current
> brokerd service daemon into 2 daemons:
>
> - a brokerd which only hosts live/paper trading
> endoint tasks as defined namely within all
> piker/brokers/<backend>/broker.py mods
> - a new `datad` subdaemon which in a separate
> subactor serves all the data feed service tasks
> namely delivered by endpoints in
> piker/brokers/<backend>/feed.py (or similar for
> less mature backends) and as more rigorously
> defined by the validation machinery in
> piker.data.validate.
>
> give me a mega detailed plan on how to approach
> this, and a staged approach for the implementation.
Plan-shaping user decisions (in-session Q&A): sibling
topology under `pikerd`; hard cutover staged by layer;
trading-only EMS-lazy-spawned `brokerd`. The human
staged the doc copy into `ai/claude-code/plans/` and
requested this commit after the 7 implementation
commits landed.
## Response summary
The staged design doc for the `brokerd` -> (`datad` +
`brokerd`) split: context, target supervision topology,
load-bearing verified facts, per-stage file-level
changes with gates, risk register and an end-to-end
verification matrix. Produced via 3 parallel explore
agents + 1 architect agent + human Q&A before any code
was written; all 7 implementation commits in this
branch reference its stages in their provenance
entries.
## Files changed
- `ai/claude-code/plans/datad_service.md` — the design
plan doc (human-staged copy of the AI-authored plan)
## Human edits
None to the doc content — committed as generated. NB:
the implementation deviated from the plan-as-written in
4 places, see the raw file's deviation log.

View File

@ -1,51 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T17:33:09Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T173309Z_f15f8178_prompt_io.md
---
NOTE: diff-ref mode entry; the AI output here is the
committed doc itself (a design plan, not code) so no
verbatim copy is duplicated:
> `git log -1 -p --follow -- ai/claude-code/plans/datad_service.md`
## Implementation deviation log
Where the landed 7-commit series differs from the plan
as written (recorded for reviewer transparency; the
plan doc is committed unmodified):
1. Commit ordering: the `pytest` config-dir isolation
fix lands BEFORE the `tractor`-API drift port. The
plan's stage gates assumed a runnable+isolated test
baseline; per-commit gating exposed that without
isolation the paper-EMS test reads the user's real
(polluted) `account.kraken.paper.toml` and reddens.
2. The plan's "stage 0: full pytest green" gate
required first repairing pre-existing branch
breakage vs `tractor` git `main` (boot
`AttributeError`, stale discovery/exc/position
APIs) — that repair became its own commit
("Port service+tests to latest `tractor` APIs")
rather than plan-stage work.
3. Stage-4 fail-fast placement: the plan said
`broker_init()` raises on brokerd-ep-less backends;
implementation moved the raise to `spawn_brokerd()`
since `piker ledger` calls `broker_init()` directly
even for paper accounts on datad-only backends.
4. `brokers/_daemon.py` change grouping: the
import-cleanup hunks (`exceptiongroup`, `_FeedsBus`
type-only import) landed with the caps-sec slim
commit instead of the fixture-slim commit, keeping
each intermediate tree import-clean without
sub-hunk surgery.
Also of record: the plan's "Verification" matrix was
executed as written (per-suite gates each stage, the
headless datad-feed smoke, the kucoin fail-fast unit
check); the known pre-existing ~50% second-runtime-boot
test wedge was characterized and excluded as a
regression via revert-testing.

View File

@ -1,60 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
timestamp: 2026-06-10T21:35:49Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T213549Z_f084e899_prompt_io.md
scope: code
substantive: true
raw_file: 20260610T213549Z_f084e899_prompt_io.raw.md
---
## Prompt
User bug report from live `ib` testing of the
(datad|brokerd)-split branch:
> ok doing some testing and noticing live orders do not
> work otb, pikerd show this on live submission,
> [pdb traceback: `RuntimeError("Can not order
> {symbol}, no live feed?")` at `ib/api.py:1152`
> `submit_limit()` with `self._contracts == {}` in the
> `brokerd.ib` actor + a `TrioTaskExited` teardown
> cascade]
Follow-up user direction fixing the design intent:
> i think the main thing here is that [brokerd] should
> be able to always submit orders without a live feed
> being up and registered in the same subactor right?
## Response summary
Root cause: pre-split the feed code populated the
actor-local `Client._contracts` cache (via
`get_mkt_info()` writing `mkt.bs_fqme` keys) in the
SAME process as order submission; post-split the
trading actor's client is never warmed. Fix: lazily
qualify + cache the contract per order request in
`handle_order_requests()` by running the same
`get_mkt_info(fqme, proxy=...)` ep the feed side uses,
plus per-order error relay (`BrokerdError`) so one bad
submission can't crash the whole trades dialog (the
`TrioTaskExited` storm was teardown cascade from the
original raise).
## Files changed
- `piker/brokers/ib/broker.py` — thread `proxies` into
`handle_order_requests()`; lazy contract qualify on
cache-miss; guard `submit_limit()` w/ `BrokerdError`
relay; uncomment the (anticipatory) `get_mkt_info`
import
- `piker/brokers/ib/api.py` — fix the non-f-string
raise msg + document the new qualification contract
## Human edits
None — committed as generated. Live `ib` order retest
performed by the human post-commit.

View File

@ -1,57 +0,0 @@
---
model: claude-fable-5[1m]
service: claude
timestamp: 2026-06-10T21:35:49Z
git_ref: datad_service
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T213549Z_f084e899_prompt_io.md
---
NOTE: diff-ref mode entry (code committed in the same
commit as this log); recorded from the live debug
session per the `/prompt-io` skill rules.
> `git log -1 -p --follow -- piker/brokers/ib/broker.py`
> `git log -1 -p --follow -- piker/brokers/ib/api.py`
Key diagnostic chain (from session):
- pdb showed `Client._contracts == {}` inside
`brokerd.ib`'s `submit_limit()`; the cache has
exactly TWO write sites: `Client.find_contracts()`
(api.py, keys `f'{sym}.{exch}.ib'`) and
`symbols.get_mkt_info()` (key `mkt.bs_fqme`, eg.
'nvda.nasdaq' — NO `.ib` suffix).
- `BrokerdOrder.symbol` arrives as the bs_fqme form
('nvda.nasdaq') so ONLY the `get_mkt_info()` write
site produces the key `submit_limit()` reads —
ie. pre-split it was the feed's in-proc
`get_mkt_info(sym, proxy=proxy)` call keeping orders
working, NOT `find_contracts()`.
- the existing TODO at `symbols.py:642-644` literally
predicted this: "this is going to be problematic
if/when we split out the datad vs. brokerd actors
since the mktmap lookup table will now be
inaccessible.."
- instance identity verified: `proxy._aio_ns` IS the
same `Client` obj as `_accounts2clients[account]`
(both sourced from the `load_aio_clients()` cache via
`open_client_proxies()`), so a brokerd-side
`get_mkt_info(fqme, proxy=proxies[account])` warms
exactly the dict `submit_limit()` reads. It also
populates `client._cons2mkts` which the
position-audit path (`broker.py` backup-table code)
needs in this actor anyway.
- the `TrioTaskExited` storm in the user's log
(`recv_trade_updates`, `open_aio_client_method_relay`
aio tasks) is teardown cascade: the raise crashed
`handle_order_requests` -> nursery teardown ripped
the trio sides of still-running aio relay tasks.
Hence the added per-order try/except ->
`BrokerdError` relay hardening so a single bad
submission degrades to an EMS error msg instead of
killing the backend's entire order-ctl dialog.
Verification: `tests/test_services.py` (5 passed) +
`tests/test_ems.py` (6 passed) regression-green; live
`ib` submission retest delegated to the human (needs a
running TWS/gw).

View File

@ -1,34 +0,0 @@
# AI Prompt I/O Log — claude
This directory tracks prompt inputs and model
outputs for AI-assisted development using
`claude` (claude-code CLI).
## Policy
Prompt logging follows the
[NLNet generative AI policy][nlnet-ai].
All substantive AI contributions are logged
with:
- Model name and version
- Timestamps
- The prompts that produced the output
- Unedited model output (`.raw.md` files)
[nlnet-ai]: https://nlnet.nl/foundation/policies/generativeAI/
## Usage
Entries are created by the `/prompt-io` skill
or automatically via `/commit-msg` integration.
Each commit carrying AI-generated changes links
to its provenance entry via a `Prompt-IO:`
commit-msg trailer; entries use "diff-ref mode"
(pointers into `git log -p` instead of verbatim
code copies) to avoid duplicating committed
code.
Human contributors remain accountable for all
code decisions. AI-generated content is never
presented as human-authored work.

View File

@ -1,58 +0,0 @@
---
created_at: 2026-10-05T23:00:13.353081+00:00
generated_by:
harness: codex
provider: OpenAI
git_ref: 9555e20c
scope: data
substantive: true
raw_file: 20261005T230013Z_9555e20c_trend_followups_d48a77_prompt_io.raw.md
---
## Prompt
The human asked to capture all ongoing Trend Calculus/Jev follow-ups
in Taken, supplied the federated_project_stores worktree, and then
requested a complete commit plan for that branch. They confirmed
that workflow configuration already exists on moar_ai_skillz and
asked why the earlier trend package duplicated it.
## Response summary
Resolved the registered Piker corpus and unique structural parent.
Used Taken's guarded whole-document save to append six identified
TODO tasks and 24 unchecked items. Preserved every prior byte,
existing state, property and order. Linked the existing FSP review
instead of duplicating it and kept annotation IPC follow-ups with
the existing task. Recorded known harness/worktree/branch provenance.
Corrected only the new prototype-review task's prose to require the
existing f148fbcc/moar_ai_skillz workflow dependency and regenerate
six Trend Calculus behavior boundaries. No task marker was changed.
Added a whitespace attribute limited to .taken Org documents so the
required final empty subtree separator passes standard Git checks.
No other workflow configuration is included in this commit package.
## Verification
Taken lint previously passed on the saved corpus and standard Git
whitespace checks pass with the path-scoped Org attribute. Saved
bytes were checked against the guarded candidate; all original
corpus content and state markers are intact. The commit package
selects a read-only lint against its exact boundary store, with
application tests excluded for this data-only change. That check
remains pending until package execution; no earlier whole-worktree
result is claimed as an exact-boundary reusable pass.
## Human edits
The human authorized loading the registered store and requested
planning, not execution. Their workflow-history correction directly
changed the new review task. Existing human tasks remain unaccepted;
no commits, pushes, rebases, mainlining or existing-state changes
were performed. The main checkout's staged content was preserved.
## Files changed
- `.taken/current.org`
- `.gitattributes`

View File

@ -1,52 +0,0 @@
---
created_at: 2026-10-05T23:00:13.353081+00:00
generated_by:
harness: codex
provider: OpenAI
git_ref: 9555e20c
scope: data
substantive: true
---
## Human instruction (verbatim)
after this pass i want us to start loading our taken store with all the ongoing / todos/ follow ups anyway - we can hash it all out there.
it's on another unmerged wkt we have to mainline, not sure what the
best stopgap for that is rn but the existing taken is here,
wkt/federated_project_stores
can we do a $commit-plan for that wkt branch with this stuff then as
well? i'm going to try and get it landed to main asap so we can start
always updating it directly from our working branch/wkt.
uhh isn't this already in f148fbcc and the moar_ai_skillz branch??
## Captured assistant output (verbatim)
The style pass and seven-commit package are finished. I added
six follow-up tasks with 24 unchecked items to the registered
Taken corpus and verified that all prior content is unchanged.
Taken lint passes.
You’re right: the three `.ai` files are byte-for-byte identical
to `f148fbcc` on `moar_ai_skillz`. That commit isn’t in this
checkout or local `main` yet, but I should have treated it as
an existing branch dependency, not proposed a duplicate commit.
I’m withdrawing that workflow step from the Trend Calculus plan.
Those files are now staged here; I’ll leave your index untouched.
## Data/configuration pointers
> `git diff HEAD~1..HEAD -- .taken/current.org`
> `git diff HEAD~1..HEAD -- .gitattributes`
These pointers name the completed one-boundary commit after human
review/execution. The prepared package captures the pending delta.
Six identified tasks retain all existing states and record prototype
review, live Jev qualification, service wiring, Pine parity, chart
qualification and native subsecond source work. A narrow Org
attribute permits Taken's required blank separator at EOF while
retaining other whitespace diagnostics. No Git commit ran.

View File

@ -1,64 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-21T20:52:28Z
git_ref: 58ffe487
scope: config
substantive: true
raw_file: 20260721T205228Z_58ffe487_prompt_io.raw.md
---
## Prompt
The user asked to scan Claude's repo-local skills and
documentation, summarize their specializations, and then
rework repo-specific skills for use across coding
harnesses, particularly OpenCode. The user intends to
choose one of Claude's unfinished tasks afterward.
## Response summary
Standardized the tracked piker skills on portable Agent
Skills frontmatter, made `commit-msg` harness-aware,
documented OpenCode discovery and command delegation, and
fixed an unsafe `np.searchsorted()` example found during
the audit. Preserved the existing `.claude` artifact path
as a shared legacy location to avoid breaking established
commit workflows.
## Files changed
- `.claude/skills/commit-msg/SKILL.md` - portable,
harness-aware commit-message workflow
- `.claude/skills/commit-msg/style-guide-reference.md` -
generic coding-harness attribution
- `.claude/skills/piker-conc-expert/SKILL.md` - portable
frontmatter
- `.claude/skills/piker-profiling/SKILL.md` - portable
frontmatter
- `.claude/skills/piker-slang/SKILL.md` - portable
frontmatter
- `.claude/skills/pyqtgraph-optimization/SKILL.md` -
portable frontmatter
- `.claude/skills/timeseries-optimization/SKILL.md` -
portable frontmatter and safe search bounds handling
- `ai/README.md` - shared-skill integration model
- `ai/claude-code/README.md` - cross-harness Claude Code
documentation
- `ai/opencode/README.md` - OpenCode usage and discovery
documentation
- `.opencode/commands/commit-msg.md` - thin OpenCode
command delegating to the shared skill
- `ai/prompt-io/opencode/README.md` - OpenCode provenance
policy
- `ai/prompt-io/opencode/20260721T205228Z_58ffe487_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260721T205228Z_58ffe487_prompt_io.md`
- provenance metadata and summary
## Human edits
None - generated changes have not yet been reviewed or
edited by the human.

View File

@ -1,33 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-21T20:52:28Z
git_ref: 58ffe487
diff_cmd: git diff HEAD~1..HEAD
---
The repo-local skill inventory contains seven domains:
commit-message generation, actor-runtime concurrency,
distributed profiling, project communication style,
Python source style, PyQtGraph rendering, and NumPy/Polars
timeseries optimization.
I converted the six tracked repo-specific skills to the
portable Agent Skills frontmatter subset so Claude Code
and OpenCode can load the same source files. The
commit-message workflow now gathers live git context at
execution time, uses runtime harness/model attribution,
preserves human-owned task state, and keeps the existing
message artifact paths for compatibility.
I added OpenCode integration documentation and updated
the shared and Claude Code docs to describe a single
cross-harness skill source with thin harness commands.
During validation I also corrected an out-of-bounds
`np.searchsorted()` example in the timeseries skill.
The unfinished artifacts found during the scan are a
shared-memory migration plan and a gap-annotation
performance handoff. The earlier datad split plan appears
implemented and is now captured by the concurrency skill.

View File

@ -1,41 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-21T21:50:55Z
git_ref: c6ec3d41
scope: docs
substantive: true
raw_file: 20260721T215055Z_c6ec3d41_prompt_io.raw.md
---
## Prompt
The user asked to boot a plan to continue work on the
time-series gap checker and bug fixing of the history
backfiller. The user authorized prompt-I/O capture for the
plan documentation after the repository audit.
## Response summary
Produced a bounded repair plan based on current source,
historical issue caches, existing profiling notes, and a
test-coverage audit. The plan prioritizes reproducible
correctness failures and storage durability before venue
classification, annotation performance, or manual repair
UX.
## Files changed
- `plans/opencode/gap-checker-backfiller-repair.md` -
phased implementation and verification plan
- `ai/prompt-io/opencode/20260721T215055Z_c6ec3d41_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260721T215055Z_c6ec3d41_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated plan has not yet been edited by the
human.

View File

@ -1,26 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-21T21:50:55Z
git_ref: c6ec3d41
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff -- plans/opencode/gap-checker-backfiller-repair.md`
Generated a phased implementation plan for continuing
piker's gap checker and history backfiller repairs. The
plan separates data correctness from annotation
performance and orders work by dependency: deterministic
tests, canonical frame/gap normalization, structured
backfill completion, non-destructive atomic NativeDB
writes, exact null repair, provider/venue classification,
annotation vectorization, and crash qualification.
The plan is grounded in current code paths, local issue
caches `#62`, `#71`, and `#75`, and the existing 1,285-gap
profiling handoff. It records confirmed present defects,
design invariants, per-phase acceptance gates, test
commands, commit boundaries, and explicitly deferred UX
and provider work.

View File

@ -1,46 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-22T00:13:57Z
git_ref: 16f3cd6f
scope: code
substantive: true
raw_file: 20260722T001357Z_16f3cd6f_prompt_io.raw.md
---
## Prompt
Continue the gap-checker and history-backfiller repair plan. Start
with deterministic analysis characterization, then fix canonical
sorting, dedupe-derived columns, positive gap detection, and null
grouping.
During review, the user challenged the replacement null-grouping
algorithm because its initial tests did not assert exact endpoints.
The user explicitly required retaining detailed, human-oriented
algorithm documentation such as the existing ASCII segment map.
## Response summary
Added deterministic analysis regressions and corrected normalization
so sorting and duplicate resolution precede derived-column
calculation. Unified null grouping for NumPy and Polars inputs,
documented its exact inclusive-boundary contract with an adapted
visual map, and verified all small null layouts against an independent
state-machine oracle. Retained sorted smart-dedupe output.
## Files changed
- `piker/tsp/_anal.py` - canonical gap and documented null grouping
- `piker/tsp/_dedupe_smart.py` - sorted duplicate resolution
- `tests/test_tsp_analysis.py` - exact and exhaustive regressions
- `ai/prompt-io/opencode/20260722T001357Z_16f3cd6f_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260722T001357Z_16f3cd6f_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not yet been edited by the human.

View File

@ -1,40 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-22T00:13:57Z
git_ref: 16f3cd6f
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/tsp/_anal.py`
Generated canonical gap and null-segment normalization. Derived
datetime and delta columns are recomputed after final sorting and
duplicate resolution, and negative deltas no longer become ordinary
gaps.
NumPy and Polars null grouping share one implementation while
retaining the human-oriented visual map of contiguous zero runs. The
documented contract defines absolute inclusive endpoints, margin
expansion, frame boundary clamping, contiguous-index validation, and
requested-column selection.
> `git diff HEAD~1..HEAD -- piker/tsp/_dedupe_smart.py`
Adjusted smart dedupe to honor sorted output and resolve duplicate
timestamps without retaining stale order.
> `git diff HEAD~1..HEAD -- tests/test_tsp_analysis.py`
Added deterministic synthetic OHLCV coverage for sorted dedupe, fresh
derived columns, and positive gap detection. Null grouping is checked
against readable endpoint examples and an independent state-machine
oracle over every layout through six rows, three margin widths, and
both NumPy and Polars inputs.
Verification generated with the patch:
`timeout -k 5 30 python -m pytest -q tests/test_tsp_analysis.py`
Result: 11 passed.

View File

@ -1,36 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-22T00:13:58Z
git_ref: 16f3cd6f
scope: code
substantive: true
raw_file: 20260722T001358Z_16f3cd6f_prompt_io.raw.md
---
## Prompt
Continue the structured backfill phase after the analysis regressions.
Characterize provider exhaustion and genuinely empty frames, then remove
completion paths that can hang after child-task exit.
## Response summary
Removed orphan-prone completion events from the structured nursery flow
and checked empty provider frames before indexing timestamp endpoints.
Added deterministic timeout-bounded regressions for both exit paths.
## Files changed
- `piker/tsp/_history.py` - structured completion and empty-frame fixes
- `tests/test_history_backfill.py` - deterministic exit regressions
- `ai/prompt-io/opencode/20260722T001358Z_16f3cd6f_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260722T001358Z_16f3cd6f_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not yet been edited by the human.

View File

@ -1,25 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-22T00:13:58Z
git_ref: 16f3cd6f
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/tsp/_history.py`
Removed redundant completion events whose consumers waited only after
their owning nurseries had joined. Added empty provider-frame handling
before timestamp endpoint indexing so provider exhaustion exits cleanly.
> `git diff HEAD~1..HEAD -- tests/test_history_backfill.py`
Added bounded, actor-free regressions for `DataUnavailable` and empty
provider-frame completion.
Verification generated with the patch:
`timeout -k 5 60 python -m pytest -q tests/test_history_backfill.py`
Result: 2 passed.

View File

@ -1,39 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-22T02:41:33Z
git_ref: 3a4f6737
scope: code
substantive: true
raw_file: 20260722T024133Z_3a4f6737_prompt_io.raw.md
---
## Prompt
The user challenged the analysis commit message's claim that only
positive sample-step gaps are detected and asked whether out-of-order
timestamps were simply ignored. After confirming the missing separate
reporting path, the user instructed the agent to implement the fix.
## Response summary
Separated missing-history gaps from timestamp-ordering errors without
changing the existing `dedupe()` return shape. Added a structured
detector and made normalization warn before sorting removes evidence of
duplicates or reversed timestamps.
## Files changed
- `piker/tsp/_anal.py` - ordering detector and dedupe reporting
- `piker/tsp/__init__.py` - public detector export
- `tests/test_tsp_analysis.py` - exact ordering-error regression
- `ai/prompt-io/opencode/20260722T024133Z_3a4f6737_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260722T024133Z_3a4f6737_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not yet been edited by the human.

View File

@ -1,30 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-22T02:41:33Z
git_ref: 3a4f6737
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/tsp/_anal.py`
Added `detect_time_ordering_errors()` to return non-positive timestamp
steps as structured rows. `dedupe()` now warns with those rows before
sorting and duplicate removal erase the original ordering evidence.
> `git diff HEAD~1..HEAD -- piker/tsp/__init__.py`
Exported the ordering detector through the public TSP package.
> `git diff HEAD~1..HEAD -- tests/test_tsp_analysis.py`
Changed the negative-delta regression to verify exact predecessor,
timestamp, and delta values, confirm exclusion from missing-history
gaps, and require explicit normalization reporting.
Verification generated with the patch:
- `tests/test_tsp_analysis.py`: 11 passed
- Ruff: passed
- `git diff --check`: passed

View File

@ -1,43 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-22T02:41:34Z
git_ref: 3a4f6737
scope: code
substantive: true
raw_file: 20260722T024134Z_3a4f6737_prompt_io.raw.md
---
## Prompt
The user asked why the in-progress `piker/storage` changes were omitted
from the earlier commit plan. After receiving an inventory of unfinished
Phase 3 requirements, the user instructed the agent to complete the work.
## Response summary
Finished non-destructive, atomic NativeDB updates and integrated them
with history startup and reverse backfill. Expanded tests through two
adversarial review rounds that caught and corrected cross-client lock
blocking, stale temp indexing, discontinuous persisted indexes, startup
snapshot races, missing latest-frame persistence, notification wedges,
and mutable/truncated SHM persistence.
## Files changed
- `piker/storage/__init__.py` - incremental storage contract
- `piker/storage/nativedb.py` - validated atomic merge persistence
- `piker/storage/marketstore/__init__.py` - non-duplicate update mode
- `piker/tsp/_history.py` - provider-delta and startup persistence
- `tests/test_storage_nativedb.py` - NativeDB durability regressions
- `tests/test_history_backfill.py` - persistence lifecycle regressions
- `ai/prompt-io/opencode/20260722T024134Z_3a4f6737_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260722T024134Z_3a4f6737_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not yet been edited by the human.

View File

@ -1,43 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-22T02:41:34Z
git_ref: 3a4f6737
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/storage/__init__.py piker/storage/nativedb.py piker/storage/marketstore/__init__.py`
Added an incremental storage update contract. NativeDB now validates
canonical numeric OHLCV data, serializes writers both actor-locally and
through cancellable filesystem locks, merges with incoming-wins seam
resolution, regenerates contiguous indexes, reopens and validates a
same-directory temporary parquet, fsyncs it, atomically replaces the
target, fsyncs the directory, and publishes cache only after replacement.
NativeDB indexing ignores lock and crash-left temporary files.
MarketStore uses its non-duplicate write mode for incremental updates.
> `git diff HEAD~1..HEAD -- piker/tsp/_history.py`
Separated full provider deltas from capacity-truncated SHM pushes.
Backfill persists before SHM mutation, publishes bounded notifications,
and delays latest-frame publication until the concurrent pre-update
storage snapshot completes.
> `git diff HEAD~1..HEAD -- tests/test_storage_nativedb.py tests/test_history_backfill.py`
Added deterministic coverage for merge preservation, conflict policy,
atomic failures, reopened-candidate validation, cache consistency,
schema and timestamp invariants, contiguous index regeneration,
separate series, stale temp indexing, cancellable file-lock contention,
full provider-delta persistence, latest-frame ordering, and bounded
notification teardown.
Verification generated with the patch:
- deterministic analysis/backfill/storage set: 31 passed
- Ruff: passed
- `git diff --check`: passed
- final adversarial review: no findings

View File

@ -1,32 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: ses_092a25886ffeT0nrIrdkMEcgJK
timestamp: 2026-07-24T22:01:56Z
git_ref: flake_update
scope: config
substantive: true
raw_file: 20260724T220156Z_43d7a3ed_prompt_io.raw.md
---
## Prompt
After committing Piker's provider-neutral deployment, the user asked to
extract Piker-specialized `/run-tests` content from the historical
`wkt/run_tests_skill` implementation into the new deployment.
## Response summary
Create a repository-owned `test-harness-reference.md` for the canonical Run
base. Revalidate historical commands and assumptions against current pytest,
uv/Nix environments, tests, fixtures, and Tractor runtime behavior, retaining
only current Piker-specific guidance.
## Files changed
- `.claude/skills/run-tests/test-harness-reference.md` - define Piker's safe
commands, opt-in boundaries, mappings, known outcomes, and runtime notes.
## Human edits
None at generation time; pending human review.

View File

@ -1,32 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-07-24T22:01:56Z
git_ref: flake_update
diff_cmd: git diff HEAD~1..HEAD
---
The user asked to extract useful Piker-specific `/run-tests` behavior from
`wkt/run_tests_skill` after committing the provider-neutral deployment.
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
Generate a repository-owned harness reference rather than restoring the old
standalone `SKILL.md`. Preserve verified Piker-specific environment, command,
scope, fixture, test-layout, change-mapping, known-outcome, and Tractor-runtime
details while leaving shared execution and cleanup policy in the canonical
`ai.skillz` base.
Repository inspection found that the historical skill needs correction:
- the comments-only `pytest.ini` shadows `pyproject.toml` pytest options, so
`-p no:xonsh` must be explicit;
- no marker-based offline suite exists, and several live/GUI/container tests
are unsafe defaults;
- skipped Docker and Questrade modules can fail during import before marks;
- actor timeout retry remains relevant only for the exact timed-out command;
- `py313` and frozen no-sync `uv run` are the current local environment paths.
Validate with checkout import resolution, safe collection, and deterministic
watchlist/accounting tests. Do not run live broker, GUI, container,
credentialed, or user-config-dependent cases during harness verification.

View File

@ -1,40 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: unavailable
timestamp: 2026-07-27T20:47:11Z
git_ref: 84a6d47b
scope: code
substantive: true
raw_file: 20260727T204711Z_84a6d47b_prompt_io.raw.md
---
## Prompt
The user identified that `backfiller_deep_fixes` introduced persistent
`.parquet.lock` files, questioned whether Parquet or Arrow already handled
writer coordination, and clarified that piker's `tractor` structured
concurrency design already provides single-writer ownership through the
persistent `datad` feed task. The user then asked to open the backfiller
worktree and resolve the redundant locking.
## Response summary
Removed redundant actor-local and filesystem locking while preserving
atomic crash-safe Parquet replacement. Replaced the synthetic contention
test with regressions for the actual cross-branch failure: writes create
no lock sidecars, and legacy lock artifacts are ignored during indexing.
## Files changed
- `piker/storage/nativedb.py` - rely on `datad` writer ownership
- `tests/test_storage_nativedb.py` - lock-sidecar regressions
- `ai/prompt-io/opencode/20260727T204711Z_84a6d47b_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260727T204711Z_84a6d47b_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,30 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-27T20:47:11Z
git_ref: 84a6d47b
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/storage/nativedb.py`
Removed actor-local and filesystem writer locks from NativeDB. The
persistent `datad` feed task already owns writes for each series, while
its timeframe children write distinct files. NativeDB retains validated
temporary writes, file and directory synchronization, and atomic target
replacement for crash durability. The exact `.parquet` suffix filter is
retained so legacy lock sidecars are harmless.
> `git diff HEAD~1..HEAD -- tests/test_storage_nativedb.py`
Removed the synthetic cross-client lock-contention test. Added regression
coverage proving replacement and incremental writes create no lock
sidecars. Extended indexing coverage with the legacy
`.parquet.lock` artifact that caused upstream `flake_update` to crash.
Verification generated with the patch:
- NativeDB and history regression set: 20 passed
- Ruff: passed
- `git diff --check`: passed

View File

@ -1,42 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-27T21:24:54Z
git_ref: 689df816
scope: code
substantive: true
raw_file: 20260727T212454Z_689df816_prompt_io.raw.md
---
## Prompt
The user reran the known IB FQME on `backfiller_deep_fixes` and reported
that `publish_latest_frame()` still failed because NativeDB required an
`index` absent from IB's provider frame. The user called out the missed
tabular schema boundary and requested an actual end-to-end test suite
rather than storage fakes.
## Response summary
Repaired the IB-provider-to-NativeDB boundary by canonicalizing durable
fields and mapping reloads into provider-specific SHM buffers. Added a
local actor/SHM/Parquet integration regression covering first startup and
restart, plus focused conversion and timestamp-coercion tests. Two review
rounds found and resolved restart hydration and fractional-time hazards.
## Files changed
- `piker/storage/nativedb.py` - canonical storage and SHM field mapping
- `piker/tsp/_anal.py` - name-based Polars-to-NumPy conversion
- `tests/test_history_backfill.py` - actor/SHM/Parquet integration test
- `tests/test_storage_nativedb.py` - schema conversion regressions
- `ai/prompt-io/opencode/20260727T212454Z_689df816_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260727T212454Z_689df816_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,34 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-27T21:24:54Z
git_ref: 689df816
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/storage/nativedb.py piker/tsp/_anal.py`
Normalized index-less provider frames to NativeDB's canonical names,
order, and dtypes before merge and publication. Provider-only columns
are excluded from durable files, derived indexes are regenerated, and
fractional timestamps are rejected before integer conversion. Added a
canonical field map for hydrating provider-specific SHM buffers while
leaving provider-only fields at their defaults. Changed Polars-to-NumPy
conversion to select columns by field name rather than position.
> `git diff HEAD~1..HEAD -- tests/test_history_backfill.py tests/test_storage_nativedb.py`
Added deterministic coverage using IB's actual provider dtype and a real
local `tractor` root actor, IB-typed shared-memory buffers, NativeDB,
Parquet persistence, first-start publication, and restart hydration.
Added focused regressions for reordered/extra Polars columns and
fractional timestamp rejection.
Verification generated with the patch:
- NativeDB and history integration set: 23 passed
- Ruff: passed
- `git diff --check`: passed
- second adversarial review: no findings
- no live gateway or network tests run

View File

@ -1,41 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-27T21:59:06Z
git_ref: 689df816
scope: code
substantive: true
raw_file: 20260727T215906Z_689df816_prompt_io.raw.md
---
## Prompt
After the actor/SHM/Parquet integration test exposed a stale SHM triplet,
the user requested leak-cleaner machinery in the pytest harness using
Tractor's existing ownership and lifetime patterns.
## Response summary
Added creator-scoped SHM leak tracking to pytest without scanning
`/dev/shm` or treating attachments as owned. The fixture cooperates with
normal Tractor teardown, verifies POSIX object identity before fallback
cleanup, restores process-local token state, and fails after cleaning a
leak. Regressions cover the exact pre-actor-registration allocation window,
positional creators, and external attachment safety.
## Files changed
- `tests/conftest.py` - creator-scoped SHM leak tracking fixture
- `tests/test_shm_cleanup.py` - ownership and failure-window regressions
- `.claude/skills/run-tests/test-harness-reference.md`
- document current-process SHM cleanup behavior
- `ai/prompt-io/opencode/20260727T215906Z_689df816_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260727T215906Z_689df816_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,25 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-27T21:59:06Z
git_ref: 689df816
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- tests/conftest.py tests/test_shm_cleanup.py .claude/skills/run-tests/test-harness-reference.md`
Added function-scoped SHM ownership tracking around Tractor's test-process
factory. The fixture records only successful creators, removes ownership
records during normal Tractor teardown, verifies POSIX object identity
before fallback unlink, restores the token-cache baseline, and fails after
cleaning any leak. Regressions reproduce allocation failure before actor
lifetime registration and prove external attachments remain untouched.
Verification generated with the patch:
- SHM cleanup regressions: 2 passed
- combined SHM, NativeDB, and history set: 25 passed
- Ruff: passed
- `git diff --check`: passed
- final adversarial review: no findings

View File

@ -1,42 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: 24fb9765-a550-4570-8350-f0fc9b7e17db
timestamp: 2026-07-28T00:32:47Z
git_ref: ed85721c
scope: code
substantive: true
raw_file: 20260728T003247Z_ed85721c_prompt_io.raw.md
---
## Prompt
Build a safe xonsh workflow for qualifying NativeDB and reverse-backfill
correctness against a known gappy IB chart, beginning with
`mnq.cme.20260918`. Cover baseline, fresh, restart, append, and expansion
testing through implementation, adversarial review, and verification.
## Response summary
Implemented a private disposable xonsh qualification workflow. Evidence is
tied to a fixed case, report checksum, snapshot checksum, worktree import,
and phase metadata. Added explicit path and symlink safety, source
replacement handling, xonsh child environments, and lifecycle preservation
comparisons.
## Files changed
- `snippets/nativedb_backfill_audit.xsh` - disposable qualification helpers
- `docs/manual_backfill_qualification.rst` - operator lifecycle runbook
- `tests/test_backfill_audit_snippet.py` - xonsh and comparison regressions
- `.claude/skills/run-tests/test-harness-reference.md`
- qualification test-harness guidance
- `ai/prompt-io/opencode/20260728T003247Z_ed85721c_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260728T003247Z_ed85721c_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,32 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-28T00:32:47Z
git_ref: ed85721c
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- snippets/nativedb_backfill_audit.xsh docs/manual_backfill_qualification.rst tests/test_backfill_audit_snippet.py .claude/skills/run-tests/test-harness-reference.md`
Added sourceable xonsh helpers that create a private disposable root, bind
child processes to the reviewed worktree, capture checksum-bound phase
evidence, safely seed and clear test history, and compare lifecycle
preservation.
The workflow rejects path traversal, pre-existing symlinks, output
collisions, mismatched case/report/snapshot evidence, and same-phase
comparison. The accompanying runbook covers known-bad replay, fresh
backfill, restart, append, gap triage, and expansion cases.
Verification generated with the patch:
- xonsh qualification helper regressions: passed
- xonsh sourceability: passed
- Ruff: passed
- `git diff --check`: passed
Adversarial review drove additional evidence binding, worktree executable,
environment propagation, source replacement, and descriptor-level safety
fixes. Residual concurrent mutation risk is stated explicitly in the private
disposable-root runbook.

View File

@ -1,40 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: 24fb9765-a550-4570-8350-f0fc9b7e17db
timestamp: 2026-07-28T00:50:34Z
git_ref: ed85721c
scope: code
substantive: true
raw_file: 20260728T005034Z_ed85721c_prompt_io.raw.md
---
## Prompt
Add reusable read-only tooling to qualify raw NativeDB Parquet against a
known gappy IB chart, beginning with `mnq.cme.20260918`. Preserve malformed
evidence and distinguish structural validity from unclassified positive
gaps without opening or mutating the storage runtime.
## Response summary
Implemented raw Parquet audit reporting with human and JSON output, bounded
cadence details, exact integer arithmetic, strict status, collision-safe
snapshot capture, and source path protections. Regressions cover malformed
schema and values, timestamp precision, gap arithmetic, corrupt bytes,
copy failures, symlinks, traversal, and read-only CLI behavior.
## Files changed
- `piker/storage/_audit.py` - raw Parquet audit and snapshot implementation
- `piker/storage/cli.py` - `piker store audit` command
- `tests/test_storage_audit.py` - audit and CLI regressions
- `ai/prompt-io/opencode/20260728T005034Z_ed85721c_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260728T005034Z_ed85721c_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,27 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-28T00:50:34Z
git_ref: ed85721c
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/storage/_audit.py piker/storage/cli.py tests/test_storage_audit.py`
Added a raw, read-only NativeDB Parquet audit with human and JSON output,
bounded cadence evidence, exact integer arithmetic, pre-parse snapshot
capture, and strict qualification status.
The command rejects unsafe FQME paths, symlinked sources and outputs,
destination collisions, non-regular source nodes, malformed canonical
schema, non-finite values, invalid timestamps, noncanonical indexes, and
sub-period cadence. Copy-failure cleanup preserves source bytes while
completed corrupt snapshots remain available for diagnosis.
Verification generated with the patch:
- storage audit and CLI regressions: passed
- Ruff: passed
- `git diff --check`: passed
- final adversarial review: no findings

View File

@ -1,39 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: 24fb9765-a550-4570-8350-f0fc9b7e17db
timestamp: 2026-07-28T23:27:18Z
git_ref: ed85721c
scope: code
substantive: true
raw_file: 20260728T232718Z_ed85721c_prompt_io.raw.md
---
## Prompt
Diagnose the live `pikerd` failure where backfill publication raised
`ValueError: OHLCV timestamps must be finite and positive` while merging the
known gappy MNQ NativeDB baseline with fresh IB history. Determine whether to
commit the pending audit stack or iterate first.
## Response summary
Traced the primary failure through `publish_latest_frame()` to
`NativeStorageClient.update_ohlcv()`. The incoming frame was valid, but the
canonicalized persisted baseline retained its epoch-zero row and caused the
merged frame to fail validation. Added persisted-row repair before merge and
a regression using the observed legacy schema characteristics.
## Files changed
- `piker/storage/nativedb.py` - drop non-positive persisted rows during merge
- `tests/test_storage_nativedb.py` - live MNQ failure-shape regression
- `ai/prompt-io/opencode/20260728T232718Z_ed85721c_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260728T232718Z_ed85721c_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,27 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-28T23:27:18Z
git_ref: ed85721c
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/storage/nativedb.py tests/test_storage_nativedb.py`
Fixed incremental NativeDB updates against legacy persisted history with
non-positive timestamps. Incoming provider frames remain strictly validated,
while merge repair discards invalid persisted rows before concat, dedupe,
ordering, canonical-index rewrite, and atomic publication.
The regression reproduces the observed MNQ baseline shape: one epoch-zero
row, noncanonical absolute indexes, extra derived columns, and a valid fresh
IB frame. It proves the invalid row is removed while all valid old and new
bars survive with canonical indexes.
Verification generated with the patch:
- NativeDB regressions: 18 passed
- history backfill regressions: 6 passed
- focused Ruff: passed
- `git diff --check`: passed

View File

@ -1,40 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: 24fb9765-a550-4570-8350-f0fc9b7e17db
timestamp: 2026-07-29T03:41:06Z
git_ref: 922a5df8
scope: code
substantive: true
raw_file: 20260729T034106Z_922a5df8_prompt_io.raw.md
---
## Prompt
Diagnose the live IB reverse-fill failure where
`reqHistoricalDataAsync()` raised API error 10314 because its end date,
time, or timezone was invalid.
## Response summary
Traced the failure to `Client.bars()`, where an unfinished EST conversion
left the original datetime for `ib_async` to serialize as
`YYYYMMDD HH:MM:SS UTC`. Converted aware boundaries explicitly to UTC and
passed IB's accepted `YYYYMMDD-HH:MM:SS` string while retaining a blank
latest-request boundary. Added exact request-argument regressions.
## Files changed
- `piker/brokers/ib/api.py` - explicit UTC-dash history boundary format
- `tests/test_ib_history.py` - IB request-format regressions
- `.claude/skills/run-tests/test-harness-reference.md`
- deterministic IB history test mapping
- `ai/prompt-io/opencode/20260729T034106Z_922a5df8_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260729T034106Z_922a5df8_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,25 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-29T03:41:06Z
git_ref: 922a5df8
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/brokers/ib/api.py tests/test_ib_history.py .claude/skills/run-tests/test-harness-reference.md`
Fixed IB reverse-history requests to serialize aware end boundaries with
IB's explicit UTC-dash syntax, `YYYYMMDD-HH:MM:SS`. This bypasses
`ib_async`'s trailing-`UTC` representation, which the live Gateway rejected
with API error 10314, and removes the unfinished EST comparison breakpoint.
The regression captures the exact `reqHistoricalDataAsync()` argument for
latest, stdlib-aware, Pendulum UTC, and America/New_York inputs.
Verification generated with the patch:
- IB history request regressions: 4 passed
- focused Ruff: passed
- `git diff --check`: passed
- adversarial review: no findings

View File

@ -1,40 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
session: 24fb9765-a550-4570-8350-f0fc9b7e17db
timestamp: 2026-07-29T04:17:23Z
git_ref: ce33deb6
scope: code
substantive: true
raw_file: 20260729T041723Z_ce33deb6_prompt_io.raw.md
---
## Prompt
Diagnose why the chart still showed a zero first OHLCV row after the
epoch-zero timestamp repair, causing auto-y-ranging to include zero.
## Response summary
Audited live 60s and 1s NativeDB files and found one exact 60s first-slot
sentinel at epoch 60 with a completely zero OHLCV payload. Added narrowly
scoped read and merge repair, matching incoming validation, sentinel-only
startup handling, canonical reindexing, and explicit audit classification.
Preserved modern all-zero bars as unclassified evidence rather than assuming
all zero-priced instruments are corrupt.
## Files changed
- `piker/storage/nativedb.py` - first-slot sentinel repair and validation
- `piker/storage/_audit.py` - sentinel classification and zero-row evidence
- `tests/test_storage_nativedb.py` - hydration, merge, and boundary regressions
- `tests/test_storage_audit.py` - sentinel and modern-zero audit regressions
- `ai/prompt-io/opencode/20260729T041723Z_ce33deb6_prompt_io.raw.md`
- unedited response record
- `ai/prompt-io/opencode/20260729T041723Z_ce33deb6_prompt_io.md`
- provenance metadata and response summary
## Human edits
None - generated changes have not been edited by the human.

View File

@ -1,31 +0,0 @@
---
model: gpt-5.6-sol
provider: openai
service: opencode
timestamp: 2026-07-29T04:17:23Z
git_ref: ce33deb6
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- piker/storage/nativedb.py piker/storage/_audit.py tests/test_storage_nativedb.py tests/test_storage_audit.py`
Fixed the remaining legacy first-slot sentinel observed in live MNQ 60s
history: `time=60` with zero open, high, low, close, and volume. NativeDB now
repairs the exact sentinel before read hydration and merge, reindexes the
filtered view, and persists the repaired frame on the next valid update.
The repair remains narrowly scoped. Modern all-zero OHLC bars stay valid for
spreads or synthetic instruments, null-containing malformed rows still fail
validation, new writes can not recreate the first-slot sentinel, and a file
containing only sentinels loads as no history so fresh backfill can proceed.
The raw audit reports total all-zero price rows, classifies first-slot
sentinels as structural violations, and leaves later all-zero rows visible as
unclassified warnings.
Verification generated with the patch:
- NativeDB, audit, history, xonsh, and IB regressions: 61 passed
- focused Ruff: passed
- `git diff --check`: passed
- final adversarial review: no findings

View File

@ -1,34 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: 6409e3bb-1a9a-4ada-b6c4-c554115143e9
timestamp: 2026-07-29T18:54:06Z
git_ref: d359b1cb
scope: code
substantive: true
raw_file: 20260729T185406Z_d359b1cb_prompt_io.raw.md
---
## Prompt
The user reported that QQQ 60-second zeros appeared as a flat line after
reload, clarified that the outstanding concern was the prior `ldshm`
failure, and instructed the agent to implement the more focused fix.
## Response summary
Changed `ldshm` to classify invalid SHM snapshots before downstream
analysis. Cadence is inferred only from observed finite positive steps;
buffers containing non-finite or non-positive timestamps, or lacking a
positive cadence, are skipped rather than partially replacement-written
or reloaded. Added deterministic helper and command-level regressions.
## Files changed
- `piker/storage/cli.py` - inspect cadence and reject invalid SHM snapshots before mutation.
- `tests/test_ldshm.py` - cover QQQ-like zeros, corrupt timestamps, cadence selection, degenerate buffers, and mutation prevention.
- `.claude/skills/run-tests/test-harness-reference.md` - register the deterministic regression target.
## Human edits
None - generated output remains uncommitted.

View File

@ -1,58 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-07-29T18:54:06Z
git_ref: d359b1cb
diff_cmd: git diff HEAD~1..HEAD
---
The user clarified that the QQQ 60-second chart now displayed a flat
forward-filled segment, then asked whether the previously reported
`piker store ldshm` failure had been fixed. After being told it had not,
the user instructed: "ok but i read above you have a more focussed fix
todo now? so have at it!"
The implementation focused on the exact failure boundary. It does not
filter invalid rows into a partial replacement and does not mutate live
SHM. Instead, `ldshm` inspects one captured Polars snapshot, infers its
cadence from observed finite positive timestamp steps, and skips the
entire buffer before analysis, persistence, or reload when any timestamp
is non-finite or non-positive.
> `git diff HEAD~1..HEAD -- piker/storage/cli.py`
Generated `_shm_period_and_invalid_count()` and integrated its result in
`ldshm`. The helper selects the most frequent observed positive step,
using the smallest observed step as the deterministic tie-break. Short
or cadence-degenerate buffers are skipped. Invalid snapshots are logged
and cannot reach deduplication, NativeDB replacement, or SHM reload.
> `git diff HEAD~1..HEAD -- tests/test_ldshm.py`
Generated deterministic regressions for the QQQ-shaped interior zero
run, observed-step cadence selection, all invalid timestamp classes,
short and degenerate buffers, and command-level prevention of dedupe,
storage writes, and reload. The command-level test uses an immutable
Polars snapshot and failing spies, without live SHM mutation or timing.
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
Added the deterministic `ldshm` regression target and its change-to-test
mapping to the repository test harness reference.
Verification output:
```text
.......................................................... [100%]
58 passed in 0.70s
```
`git diff --check` passed. Ruff was unavailable in the worktree's
existing environment. Three adversarial review passes found and drove
fixes for partial-replacement data loss, invented median timeframes,
mixed SHM observations, and pre-guard null-analysis failures. The final
review reported no remaining findings.
The patch intentionally does not claim that `ldshm` is safe to run as a
general concurrent repair writer. It handles invalid live snapshots by
refusing mutation rather than weakening NativeDB validation.

View File

@ -1,37 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: 253ade33-07ba-45b5-8839-be35d17ec164
timestamp: 2026-07-29T20:40:46Z
git_ref: ad6c560f
scope: code
substantive: true
raw_file: 20260729T204046Z_ad6c560f_prompt_io.raw.md
---
## Prompt
The user reported that the QQQ 1-second chart still contained a gap after
the `ldshm` fix, asked the agent to inspect it, and authorized continued
implementation after a short pause and shutdown of the live workspace.
## Response summary
Diagnosed a 653-row active RT SHM null reservation caused by inclusive IB
reverse-query overlaps and startup repair orchestration. Prevented extra
physical SHM overlap rows, serialized and bounded IB history recovery,
made blank/error responses terminate, and constrained synthetic repair to
valid interior timestamp boundaries. Added deterministic concurrency and
data-layout regressions.
## Files changed
- `piker/brokers/ib/feed.py` - bound and serialize IB history reset/retry behavior.
- `piker/tsp/_history.py` - prevent SHM overlap skew and safely finalize null repair.
- `tests/test_ib_history.py` - cover blank, cancellation, reset, and pacing interleavings.
- `tests/test_history_backfill.py` - cover overlap and null-repair invariants.
- `.claude/skills/run-tests/test-harness-reference.md` - register deterministic coverage.
## Human edits
None - generated output remains uncommitted.

View File

@ -1,72 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-07-29T20:40:46Z
git_ref: ad6c560f
diff_cmd: git diff HEAD~1..HEAD
---
The user reported that QQQ still displayed a gap on the 1-second chart
after the focused `ldshm` fix and asked the agent to inspect it. The user
then paused and resumed implementation while shutting down the live piker
trading workspace.
Read-only live inspection found the active datad generation held 653
contiguous zero-time rows in QQQ's 1-second RT SHM, while durable Parquet
contained no zero rows. The run occupied absolute indexes 168148 through
168800 between timestamps 1785348398 and 1785349051. The stale actor
generation and active 60-second history were separately identified.
> `git diff HEAD~1..HEAD -- piker/tsp/_history.py`
Generated history changes that exclude each inclusive reverse-query
endpoint already present in SHM while retaining the full provider frame
for NativeDB merge. Startup null repair now runs after reverse backfill,
uses bounded UI notifications, handles provider no-data without an
interactive pause, fills only exact interior zero groups, and refuses
synthetic timestamps unless both valid boundaries establish the expected
cadence.
> `git diff HEAD~1..HEAD -- piker/brokers/ib/feed.py`
Generated IB history reset changes that make blank responses complete,
bound repeated cancellation and reset failures per request, serialize
timeout and pacing farm resets with one actor-global Trio lock, carry
explicit reset results, and coordinate pacing handoff with queued timeout
waiters.
> `git diff HEAD~1..HEAD -- tests/test_history_backfill.py`
Generated regressions for inclusive endpoint exclusion, full NativeDB
provider deltas, strict synthetic gap boundaries, empty-provider local
fallback, bounded notifications, and preservation of valid margin rows.
> `git diff HEAD~1..HEAD -- tests/test_ib_history.py`
Generated deterministic regressions for blank IB responses, cancellation
limits, stalled reset cancellation, pacing reset failure limits,
cross-request reset serialization, timeout-to-pacing handoff, and
successful handoff timeout restart.
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
Registered the deterministic history-backfill target and expanded the IB
history mapping to include `feed.py`.
Verification output:
```text
........................................................................ [ 93%]
..... [100%]
77 passed in 2.12s
```
`git diff --check` passed. Multiple adversarial review rounds identified
and drove fixes for unbounded IB empty/cancellation/reset paths, stale
reset ownership, actor-global failure poisoning, concurrent farm resets,
double-counted pacing handoffs, physical endpoint overlap, and unsafe
synthetic timestamp boundaries. Final review reported no findings.
Live validation was intentionally deferred because the user shut down the
trading workspace. A fresh datad/chart startup is required to regenerate
SHM and verify that QQQ no longer contains the 653-row null run.

View File

@ -1,41 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-07-31T16:52:15Z
git_ref: 0846cbd4
scope: code
substantive: true
raw_file: 20260731T165215Z_0846cbd4_prompt_io.raw.md
---
## Prompt
Evaluate and update `piker store` so bare groups and endpoints immediately
show help; prepare for eventual optional fuzzy selection in `anal` and
`ldshm`; aggregate recent time-series diagnostics into CLI endpoints. The
user selected the safe-foundation scope.
## Response summary
Added immediate help UX, exact NativeDB and SHM identities, read-only
`series` and `shm` diagnostics, selector-ready exact SHM names, and robust
discovery/attachment. Fixed related `ldshm` option and no-match failures.
Deferred optional `fzf` and mutation-default changes.
## Files changed
- `piker/storage/cli.py` - help UX and read-only series/SHM diagnostics.
- `piker/storage/nativedb.py` - canonical compound series identities.
- `piker/tsp/_history.py` - exact SHM discovery and dtype resolution.
- `piker/data/_sharedmem.py` - attach-only existing-segment helper.
- `piker/tsp/__init__.py` - SHM identity helper exports.
- `tests/test_store_cli.py` - command UX and endpoint regressions.
- `tests/test_ldshm.py` - SHM diagnostics and operational regressions.
- `tests/test_storage_nativedb.py` - series parsing/index regressions.
- `docs/manual_backfill_qualification.rst` - triage command documentation.
- `.claude/skills/run-tests/test-harness-reference.md` - test mapping.
## Human edits
None - generated output remains uncommitted.

View File

@ -1,93 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-07-31T16:52:15Z
git_ref: 0846cbd4
diff_cmd: git diff HEAD~1..HEAD
---
The user requested an evaluation and possible update of `piker store`,
including immediate help output when a group or endpoint is invoked with
no arguments. The user also proposed eventual optional `fzf` selection for
`anal` and `ldshm`, and authorized aggregating the recent time-series and
SHM debugging work into CLI endpoints. After reviewing three scopes, the
user selected the recommended safe foundation rather than implementing
interactive fuzzy selection or changing mutation defaults immediately.
> `git diff HEAD~1..HEAD -- piker/storage/cli.py`
Generated no-argument help behavior for the `store` group and every
endpoint. Added read-only `series` and `shm` commands, JSON and Rich output,
exact `--shm-name` plumbing, SHM cadence/invalid/order/gap summaries, and
safe corrupt-epoch formatting. Fixed existing `ldshm` no-write/no-reload
control flow and no-match debugger behavior.
> `git diff HEAD~1..HEAD -- piker/storage/nativedb.py`
Generated canonical `NativeSeriesRef` parsing and deterministic listing.
Changed the internal index to preserve `(fqme, period)` identities while
keeping unique-FQME compatibility listing and cardinality. Hardened
malformed, sidecar, Unicode-period, symlink, and traversal handling.
> `git diff HEAD~1..HEAD -- piker/tsp/_history.py`
Generated exact `ShmBufferRef` parsing and stable discovery, replacing
unsafe substring globbing. Added dtype resolution that mirrors history
allocation, exact-ref attachment, disappearance handling, and optional
exact-name iteration.
> `git diff HEAD~1..HEAD -- piker/data/_sharedmem.py`
Generated attach-only SHM access which never creates a segment when a
discovered object disappears.
> `git diff HEAD~1..HEAD -- piker/tsp/__init__.py`
Exported selector-ready SHM identity, parsing, listing, and dtype helpers.
> `git diff HEAD~1..HEAD -- tests/test_store_cli.py`
Generated command-level help, exact durable-series JSON, read-only SHM JSON,
and unknown exact-name regressions.
> `git diff HEAD~1..HEAD -- tests/test_ldshm.py`
Generated SHM identity, summary, ordering, dtype, forged-name, disabled
mutation-flag, and gap-markup regressions.
> `git diff HEAD~1..HEAD -- tests/test_storage_nativedb.py`
Generated compound index, canonical parser, malformed filename, and dotted
FQME regressions.
> `git diff HEAD~1..HEAD -- docs/manual_backfill_qualification.rst`
Documented `store series` and `store shm` as separate read-only durable and
live-memory triage layers.
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
Registered the deterministic storage CLI UX target and mapping.
Verification output:
```text
........................................................................ [ 71%]
............................. [100%]
101 passed in 1.72s
```
Real `piker store` and `piker store audit` invocations printed complete
help without `--help`, exiting with Click's normal no-args help status 2.
`git diff --check` passed. Ruff was unavailable in the existing worktree
environment.
Adversarial review drove fixes for provider dtype reconstruction, observed
versus expected cadence, exact SHM grammar, discovery races, Typer direct
defaults, malformed NativeDB periods, compound cardinality compatibility,
undefined `ldshm` reload payloads, no-match debugger hangs, ordering
corruption reporting, and dtype precedence. Final review found no issues.
Optional external `fzf` or built-in numbered selection remains deferred.
The exact series and SHM identities added here are the intended foundation
for that later patch.

View File

@ -1,39 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
session: ses_0799212ebffe42arY96czXn89F
timestamp: 2026-08-01T01:53:21Z
git_ref: 74ea2152
scope: code
substantive: true
raw_file: 20260801T015321Z_74ea2152_prompt_io.raw.md
---
## Prompt
Make `piker store ls` default to all NativeDB series as a compact counterpart
to detailed `series`, with sensible no-flag output and a visible help
description. Consolidate SHM inspection and repair under canonical `shm`,
because attachment to volatile segments is implied, and make inspection the
safe default while retaining explicit persistence and reload controls.
## Response summary
Replaced backend-oriented `ls` with compact NativeDB discovery and made both
listing commands default to all series. Consolidated SHM behavior under a
read-only-by-default `shm` command, guarded explicit repair options, updated
executable references and docs, and added command regressions.
## Files changed
- `piker/storage/cli.py` - listing defaults and unified SHM command modes.
- `tests/test_store_cli.py` - listing, help, and SHM mode regressions.
- `tests/test_ldshm.py` - explicit persistence-path regressions.
- `docs/manual_backfill_qualification.rst` - revised safe CLI workflow.
- `snippets/claude_debug_helper.py` - explicit SHM persistence commands.
- `.claude/skills/run-tests/test-harness-reference.md` - safety and test map.
- `.claude/skills/piker-slang/examples.md` - canonical command example.
## Human edits
None - generated output incorporates the user's design refinements.

View File

@ -1,78 +0,0 @@
---
model: openai/gpt-5.6-sol
service: opencode
timestamp: 2026-08-01T01:53:21Z
git_ref: 74ea2152
diff_cmd: git diff HEAD~1..HEAD
---
The user requested command-surface refinements after reviewing the new
storage CLI. Bare `ls` should default to all series and act as a compact
form of detailed `series`; commands should produce sensible default output
without requiring trigger flags; and `ls` needed a parent-help description.
The user first proposed folding read-only SHM inspection into `ldshm -r`,
then clarified that `shm` is the better canonical command because attaching
to volatile segments is implied by the resource name.
The resulting design uses `piker store ls` as a compact NativeDB FQME and
period view, while `piker store series` reports each exact sub-series with
size and path details. Both default to all records and accept an optional
FQME substring.
`piker store shm FQME` is read-only by default. Persistence and reload enter
the prior repair workflow only through explicit `--write-parquet` and
`--reload-parquet-to-shm` flags. Reload requires persistence, and read-only
formatting flags are rejected in repair mode instead of being ignored.
> `git diff HEAD~1..HEAD -- piker/storage/cli.py`
Generated shared NativeDB payload collection, compact and detailed output,
numeric period ordering, default-all semantics, the canonical `shm` command,
safe mode dispatch, explicit repair validation, and debugger propagation in
read-only mode.
> `git diff HEAD~1..HEAD -- tests/test_store_cli.py`
Generated regressions for no-flag listing, parent-help descriptions, numeric
period display, default read-only SHM JSON, reload dependencies, and repair
versus read-only option conflicts.
> `git diff HEAD~1..HEAD -- tests/test_ldshm.py`
Adjusted persistence regressions for the renamed command and explicit repair
entry while preserving the historical failure rationale.
> `git diff HEAD~1..HEAD -- docs/manual_backfill_qualification.rst`
Documented compact versus detailed NativeDB discovery, default read-only SHM
inspection, and the explicitly mutating repair invocation.
> `git diff HEAD~1..HEAD -- snippets/claude_debug_helper.py`
Updated executable debug helper commands to select explicit SHM persistence.
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
Updated operational safety guidance and SHM regression mappings.
> `git diff HEAD~1..HEAD -- .claude/skills/piker-slang/examples.md`
Updated the command example to the canonical `shm` spelling.
Verification output:
```text
........................................................................ [ 69%]
................................ [100%]
104 passed in 5.77s
```
Real command-help rendering was checked for the parent group, `ls`, `series`,
and `shm`. Real read-only `ls` and `series --json` output was also exercised
against the configured NativeDB. `git diff --check` passed.
Adversarial review identified and drove fixes for lexicographic period
ordering, stale runbook safety wording, ignored mode-specific options, and an
explicit-default `--max-gaps 10` validation bypass. Final review found no
remaining issues. Real OS-backed SHM attachment and successful repair/reload
remain integration-level validation concerns.

Some files were not shown because too many files have changed in this diff Show More