Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ correct. Explain any intentional contract change before changing saved data.
## Useful small contributions

- A synthetic counterexample for a rule that is not yet covered.
- A runnable optional pandas/CSV adapter example, keeping pandas out of the
package's runtime dependencies and preserving timezone-aware values.
- A small counterexample or pandas-version compatibility improvement for the
[existing CSV adapter](examples/pandas_csv.py), with a
[minimal reproduction](#where-to-work). Keep pandas optional and preserve
timezone-aware values.
- A [trial report](https://github.com/dev-belly/PITBridge/issues/new?template=trial_feedback.md)
showing which invoice or CSV instruction worked, or where you got stuck.
- A clearer worked example or a correction to the English/Chinese docs.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The notebook installs **dev-belly/PITBridge** from a full source URL pinned to o
commit; no local checkout is needed. Change a decision or ingestion time to see
which invoice revision remains available.

[Methodology](docs/METHODOLOGY.md) · [Data contract](docs/DATA_CONTRACT.md) · [Interview notes](docs/INTERVIEW.md)
[Choosing a tool / API reuse](docs/CHOOSING.md) · [Methodology](docs/METHODOLOGY.md) · [Data contract](docs/DATA_CONTRACT.md) · [Interview notes](docs/INTERVIEW.md)

[Scale measurements](docs/SCALING.md): three isolated trials each at 100,000 and
1,000,000 observations, with late corrections, tombstones, TTL and an independent
Expand Down
2 changes: 2 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
Notebook 使用 **dev-belly/PITBridge** 的完整源码 URL,固定到一个提交版本,无需克隆。
修改决策或入库时间,即可查看当时应选择哪个发票版本。

[何时选 PITBridge、SQL/pandas 或 Feast,以及如何复用已有 API](docs/CHOOSING.md)

例如,一月份开票金额在二月份公开、三月份才进入银行系统,四月份又被修订。直接按照“一月份”去关联历史申请,会把后来的信息放进早期特征,导致回测过于乐观。

PITBridge 同时处理数据发生时间、公开时间、入库时间和修订版本;以 SQLite SQL 生成特征,用独立 Python 枚举结果核验,并保留每一个特征的来源记录。
Expand Down
65 changes: 65 additions & 0 deletions docs/CHOOSING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Choosing a tool and reusing PITBridge

Choose by the time contract and deployment task. These are documented use cases;
no cross-tool performance or correctness benchmark is implied.

| Your task | A useful starting point | Check before using it |
| :--- | :--- | :--- |
| Inspect local financial observations with publication/ingestion times, revisions, missingness and source-record lineage | **PITBridge** and the [invoice notebook](../examples/decision_time.ipynb) | Upstream timestamps/version IDs must be trustworthy; use the [input contract](DATA_CONTRACT.md). For capacity, consult the [measured workloads](SCALING.md). |
| Keep historical selection in an existing database and own its business rules | **SQL** with explicit filters and ranking; see [SQLite window functions](https://www.sqlite.org/windowfunctions.html) and [this implementation](../src/pitbridge/core.py) | Define availability, revision ordering, deletion, freshness and ties, then test those rules against small expected cases. |
| Match sorted tables by the nearest prior value of a chosen key | **pandas `merge_asof`**, with `direction="backward"`; see the [official API](https://pandas.pydata.org/docs/reference/api/pandas.merge_asof.html) | Sort by the merge key; choose grouping, tolerance and exact-match policy. Define how your publication, ingestion and revision rules map to the tables before joining. |
| Manage feature definitions, historical training retrieval and online serving across infrastructure | **Feast**; start with its [local quickstart](https://docs.feast.dev/getting-started/quickstart) | Choose the source/store and its time semantics. Its [PIT guide](https://docs.feast.dev/getting-started/concepts/point-in-time-joins) also documents `filter_by_created_timestamp=True`; check the behavior for your version/store and the meaning of the created timestamp. |

PITBridge's scope is scalar financial observations and explicit rolling aggregates.
Streaming ingestion, access control and label generation belong to the surrounding
system. The table makes no claim about features absent from other tools.

## Reuse the existing public API

These signatures describe pre-1.0 source `6d6524b`, checked on 2026-10-19.
Pin the tag or source commit used by your example and retain its inputs and report
bundle. The documented input rules and verifiers describe that snapshot; they do
not establish cross-version API or bundle compatibility. Before adopting another
snapshot, review its contract changes and rerun the existing invoice and replay
checks. Public imports are listed in [the package](../src/pitbridge/__init__.py)
and implemented in [core.py](../src/pitbridge/core.py).

```text
Observation(record_id: str, entity_id: str, source: str, feature: str,
event_at: str, published_at: str, ingested_at: str,
revision: int, value: float | None, deleted: bool = False)
Decision(decision_id: str, entity_id: str, decision_at: str)
FeatureSpec(source: str, feature: str, max_age_days: float | None = None)
build_snapshot(observations, decisions, specs) -> list[Snapshot]
reference_snapshot(observations, decisions, specs) -> list[Snapshot]
```

Pass iterables of `Observation`, `Decision` and `FeatureSpec` respectively.
A generator is exhausted after one call; use lists when comparing SQL selection
with the independent Python reference. The [runnable invoice example](../examples/decision_time.py)
constructs those lists and checks both the full rows and three expected selections.

The return is a list of `Snapshot` dataclasses, one per decision/spec pair,
ordered by `decision_id`, `source`, `feature`. Each row contains the decision,
value/status and selected source record's ID, revision and timestamps.
Missing selections keep `value=None` and a reason: `no_history`, `not_available`,
`deleted` or `stale`; they are not filled with zero. Use `dataclasses.asdict(row)`
for a dictionary. Feature values follow the finite binary64 contract; integer
conversion can round above `2^53`.

Invalid timestamps, revisions, freshness limits, duplicate identities or missing
specs raise `ValueError` through the constructors/validation. Wrong Python call
shapes can still raise `TypeError`. Python calls raise exceptions; the CLI reports
handled contract errors on stderr with exit code 2. Full field/error rules remain
in the [input contract](DATA_CONTRACT.md); [the method](METHODOLOGY.md) explains
selection, and [rolling features](ROLLING.md) have their own contract and entry points.

## Continue with your input

Use the [optional CSV example](../examples/README.md#optional-pandascsv-input)
for three table inputs, or the `build --inputs` JSON route in the input contract.
Pandas is optional. For a mismatch, keep a minimal synthetic input, the expected
record and the actual status, then [share trial feedback](https://github.com/dev-belly/PITBridge/issues/new?template=trial_feedback.md).

External references above were checked on 2026-10-19. They describe those tools'
contracts, not an implemented adapter or compatibility promise from PITBridge.
Loading