vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
숫자가 실제라면 각 리드에 조사자를 배정하고 증거로 판단한다, 비즈니스 지표에 다중 에이전트 귀속을 제공한다
Is the number real? If yes, every lead gets its own investigator, and the evidence decides. Multi-agent attribution for business metrics.
데이터Python · HTMLGitHub @PujaSridhar온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Is the number real? If yes, every lead gets its own investigator — and the evidence decides.
When a business metric moves ("revenue dropped 14% in two weeks — why?"), two very
different things can be true:README 전문 보기 ↗Is the number real? If yes, every lead gets its own investigator — and the evidence decides.
When a business metric moves ("revenue dropped 14% in two weeks — why?"), two very different things can be true:
Causal Crew checks the number first and stops if it can't be trusted. If it can, every lead gets an independent investigator with its own isolated database, and a deterministic judge compares the evidence on equal footing. Verified findings become memory for the next question.
It does attribution, not causal proof: which segments account for the change, by how much, and what context lines up with it.
flowchart TD
Q[Question + windows] --> H{1. Health check<br/>deterministic}
H -- FAIL --> S[Stop: don't trust this number yet<br/>names the check and the day]
H -- PASS --> P[2-3. Planner<br/>data-driven leads from SQL<br/>+ context leads from Gemini via RocketRide]
P --> I1[4. Investigator<br/>own workspace]
P --> I2[4. Investigator<br/>own workspace]
P --> I3[4. Investigator<br/>own workspace]
I1 & I2 & I3 --> J[5. Judge<br/>noise, seasonality, consistency, timing<br/>overlap merge, verdicts]
J --> R[6. Report<br/>SQL behind every number]
J --> M[7. Memory<br/>verified findings for next time]
| Stage | Module | What it does |
|---|---|---|
| 0. Question | causal_crew/question.py | Relative periods ("last two weeks") are computed in code. Other phrasings are read by Gemini via RocketRide and validated against the data. Users can also set the dates. |
| 1. Health check | causal_crew/health.py | Freshness, row counts (robust z + relative floor), duplicate order ids, days copied under new ids, null spikes, unit/scale breaks. Any failure stops the run. |
| 2-3. Planner | causal_crew/planner.py | The largest single-dimension deltas always become leads (SQL). Changelog notes whose title names a segment always become leads too. Gemini, run as a RocketRide pipeline, fills the remaining slots using nearby notes and prior findings. |
| 4. Investigators | causal_crew/investigator.py, workspace.py | One per lead, in parallel, each in its own database: size the lead, drill down two levels, find the change point, split volume from order value, match context. At each level the investigator's own RocketRide pipeline task chooses the path among sub-segments that pass a statistical threshold. Every query is logged. |
| 5. Judge | causal_crew/judge.py | Deterministic evidence checks, overlap merge, ranking, verdicts. The LLM never writes a verdict. |
| 6. Report | causal_crew/run.py | Markdown + JSON, with the SQL behind every number. |
| 7. Memory | causal_crew/memory.py | Supported findings are appended to memory/findings.jsonl and fed to the planner next run; optionally pushed to Cognee (--remember). |
| Web app | causal_crew/web/ | FastAPI and a single-page dashboard: ask a question, watch the pipeline and the investigator crew, read a plain-English answer built only from the judge's output, then drill into findings, data health, leads, memory, and SQL. Past runs are kept in history. |
| LLM layer | causal_crew/llm.py, rocketride_llm.py | RocketRide first, Gemini direct as backup, per agent. Each call is its own RocketRide task with a unique project id. |
Every threshold lives in causal_crew/config.py.
The data is synthetic, with a planted cause — see PLANTED_CAUSE.md. The West region's flat shipping fee rises from $4.99 to $8.99 on 2026-08-27; West orders fall ~34%, concentrated in new customers. A decoy (the annual summer email campaign ending two days earlier) dips email orders in every region — and did the same last year.
make setup # venv + dependencies
make data # generate 637k orders (+ a broken copy) and verify the planted story
make test # unit tests + lint, no network
make app # the dashboard at http://localhost:8000
make demo-a # Run A: broken data
make demo-b # Run B: clean data
Run A — a day loaded twice. The health check fails on row counts (+73%, |z| = 28.7) and duplicate order ids, both naming 2026-09-03, and the run stops.
Run B — clean data (revenue −14.4%):
| # | Lead | Final segment | Share of change | Verdict |
|---|---|---|---|---|
| 1 | West | West, new customers | 58.9% | SUPPORTED + CONTEXT_LINKED — change point 2026-08-27, same day as the fee note; volume explains ~100% |
| 2 | 16.4% | REJECTED (seasonality) — the same windows last year dropped 87% as much | ||
| 3 | New customers | West, new customers | — | MERGED into West — the same lost orders |
| 4 | Web in West | West, web | — | MERGED into West |
The first answer to "why did revenue drop?" is expensive: the planner and the investigator agents reason through RocketRide, and on the demo data that took 65 seconds and 8 LLM path decisions to land on West → new customers. The next time the same question comes up, nothing needs to be re-reasoned. Causal Crew saves the drill-down path of every SUPPORTED finding as a recipe, and two Rote Plays turn that into deterministic, shareable code.
| Play | What it does | Steps |
|---|---|---|
data-health-check | Is this number real? Six deterministic checks on any orders CSV or parquet file. Says OK or DON'T TRUST THIS NUMBER YET, with the evidence. | check_health |
metric-drop-replay | Replays the learned drill-down with 0 LLM calls, re-measures every number in SQL, re-runs the judge, and says whether today's data still supports the saved path. | check_health → replay_drilldown (a failed health check blocks the replay) |
make plays # build and install into ~/.rote/flows
rote play run ~/.rote/flows/data-health-check/main.ts orders=demo-broken
rote play run ~/.rote/flows/metric-drop-replay/main.ts orders=demo
rote play run ~/.rote/flows/data-health-check/main.ts orders=/abs/path/orders.csv days=7
orders=demo generates the seeded demo data inside the run; demo-broken is the same
data with one day loaded twice. Results on the demo data:
| Run | Result |
|---|---|
Learn (python -m causal_crew.plays learn) | LLM crew via RocketRide: 65 s, 8 path decisions → recipe region-west.json |
metric-drop-replay orders=demo | 0 LLM calls, replay step 1.3 s: West new customers, 58.9% of the change, change point 2026-08-27, SUPPORTED + CONTEXT_LINKED |
metric-drop-replay orders=demo-broken | check_health fails on 2026-09-03 (+73% rows, 1,433 duplicate order ids); replay_drilldown is blocked |
data-health-check orders=demo-broken | FAIL: row_counts and duplicates, both naming 2026-09-03 |
How they were made: each Play was recorded with rote proc run in a clean Rote
workspace, exported with rote workspace export, then generalized: recorded literals
became $orders/$days parameters, host paths became packaged @resource{…} files,
dependencies are pinned through uv, and a presentation renders the JSON the steps
print. The packaged Python is the same deterministic code as the app
(causal_crew/plays.py, entry point plays/crew.py), rebuilt into each package's
resources/ by scripts/build_play_resources.py. A replayed recipe that the data no
longer supports is flagged, not silently trusted.
Workspace class is the seam:
today it's a local DuckDB file per lead; Hotdata instant databases with one
fork per investigator are the drop-in upgrade (signup required a credit card at
the event).pipelines/planner.pipe holds a ${ROCKETRIDE_GEMINI_KEY}
placeholder that RocketRide fills at run time; keys live only in .judge.verdict)| Condition | Verdict |
|---|---|
| Noise, seasonality, or consistency fails | REJECTED (<failed checks>) |
| All pass and share of change ≥ 30% | SUPPORTED, plus CONTEXT_LINKED if a note lands within ±3 days of the change point |
| All pass, share < 30% | INSUFFICIENT_EVIDENCE |
| > 50% of its lost orders sit inside a stronger finding | MERGED into <lead> |
| Tool / Layer | Role here |
|---|---|
| RocketRide | Runs every agent's LLM step on the staging server, each as its own task with a unique project id: the planner (pipelines/planner.pipe) and each investigator's drill-down decisions (pipelines/investigator.pipe). The fan-out itself runs in Python threads. |
| DuckDB workspaces | One isolated database per investigator (workspaces/{lead_id}.duckdb), each with its own copy of the data and its own scratch tables, so agents never share state. |
| Hotdata | Designed in behind the Workspace interface (one forked instant database per investigator); not live because signup needed a credit card at the event. |
| Cognee | Changelog notes loaded into a knowledge graph (scripts/ingest_context.py); verified findings can be pushed back with --remember. |
| Snyk | Dependency scanning (make scan): the 34 core dependencies have no known vulnerabilities. Static analysis (snyk code test): 8 medium DOM-XSS warnings, all on the dashboard's innerHTML rendering, where every value is escaped first. See Security. |
make scan tests the 34 core dependencies: no known
vulnerabilities (2026-09-11).requirements-cognee.txt,
make setup-cognee). Snyk reports 5 issues in cognee 1.5.4 and its dependencies,
none with a fixed version yet: arbitrary code injection in cognee (critical),
deserialization of untrusted data in diskcache (high), and session and
authentication issues in litellm's proxy server (high, medium). The demo and the
dashboard never import cognee. It loads only in scripts/ingest_context.py and
run --remember, both opt-in and run on our own changelog notes, and the litellm
proxy server is never started..env. Pipeline files hold ${ROCKETRIDE_GEMINI_KEY}
placeholders, and commits were scanned for key material before every push.ast.literal_eval), never executed. Planner leads are validated against real
dimension values, investigator path choices against the statistical threshold,
rationales that cite a number not in the evidence are withheld, and the dashboard
HTML-escapes all LLM text.ruff runs in CI. snyk code test reports 8 medium DOM-XSS
warnings, all where the dashboard builds HTML with innerHTML. Each is a value that
passes through the page's escaping helper first, which Snyk's taint analysis can't
follow; the two error paths that carried a message were rewritten to use textContent
so nothing from the network reaches innerHTML there. They are tracked, not ignored.causal_crew/ pipeline modules; config.py holds every threshold
data/ demo data generator + verify_orders.py (checks the planted story holds)
context/ ten dated changelog / incident notes
pipelines/ RocketRide pipeline definitions
scripts/ environment smoke test, Cognee ingest
tests/ unit tests on deterministic fixtures (CI: .github/workflows/tests.yml)
Copy .env.example to .env and fill in ROCKETRIDE_APIKEY and LLM_API_KEY (Gemini).
make check smoke-tests every service. make setup-cognee adds the optional Cognee
memory integration; make app serves the dashboard at http://localhost:8000.
.env