| @@ -1,4 +1,8 @@ | ||
| node_modules/ | ||
| - | .treetrace/ | |
| *.log | ||
| .DS_Store | ||
| + | ||
| + | # Local redaction-decision cache (hashes + actions only, never secrets). | |
| + | # Kept out of git because it's per-machine resolution state, not shareable | |
| + | # lineage. The shareable companion - .treetrace/tree.json - IS committed. | |
| + | .treetrace/redactions.json |
| @@ -48,7 +48,7 @@ A privacy-positioned tool gets exactly one chance with your secrets, so this is | ||
| - Curated provider rules (AWS, GitHub, GitLab, Anthropic, OpenAI, Slack, Stripe, npm, Tailscale, Google, SendGrid, Twilio, Telegram, Discord webhooks, JWTs, private key blocks, WireGuard, basic-auth URLs, bearer tokens, secret assignments) plus a high-entropy fallback. | ||
| - Interactive review of every unique hit before anything is written. | ||
| - A **shadow scan** re-checks the final rendered artifact; an unresolved hit aborts the write. | ||
| - | - Your decisions persist in `.treetrace/redactions.json` as salted-free **hashes only** - the file never contains a secret and re-runs never re-ask. | |
| + | - Your decisions persist in `.treetrace/redactions.json` keyed by **content hash only** - the file stores the hash and your chosen action, never the secret itself, so re-runs skip resolved hits without ever recording sensitive data. | |
| ## Usage | ||
| @@ -69,7 +69,7 @@ npx treetrace --since 2026-06-01 | ||
| |--------|--------| | ||
| | Claude Code (`~/.claude/projects` JSONL) | ✅ built-in, zero-config | | ||
| | Pasted / plain-text transcripts (`User:` / `Assistant:` markers) | ✅ built-in | | ||
| - | | Codex CLI, Cursor, SpecStory, ChatGPT export | 🚧 importers welcome - [open an issue](https://github.com/zionboggan/treetrace/issues) | | |
| + | | Codex CLI, Cursor, SpecStory, ChatGPT export | 🚧 importers welcome - [open an issue](https://github.com/REPLACE-ME-ORG/treetrace/issues) | | |
| ## The format | ||
| @@ -0,0 +1,17 @@ | ||
| + | # Examples | |
| + | ||
| + | Real `treetrace` output, so you can see the artifact before you run it. | |
| + | ||
| + | ## [weather-dashboard/](weather-dashboard/) | |
| + | ||
| + | A short session that exercises every feature: a **root** goal, a **direction**, a **correction** ("scrap the radar map"), and a **scope change** ("also add a settings panel") - plus the redaction gate masking a planted Anthropic key and a basic-auth URL, and a **reusable prompt pack** that folds the correction in as a learned constraint. | |
| + | ||
| + | Generated with: | |
| + | ||
| + | ```bash | |
| + | treetrace --file session.jsonl --redact-auto | |
| + | ``` | |
| + | ||
| + | ## Dogfooding | |
| + | ||
| + | treetrace ships its own [`PROMPT_TREE.md`](../PROMPT_TREE.md) at the repo root - the prompt tree of the tool that makes prompt trees, regenerated from its own build sessions. That's the standing invitation: if you build something with an agent, commit the tree next to the code. |
| @@ -0,0 +1,51 @@ | ||
| + | # 🌳 Prompt Tree - weather-dashboard | |
| + | ||
| + | > **4 prompts** · **1 session** · **1 day** · 1 correction · 1 scope change · 2 tool calls · 1 file touched | |
| + | > | |
| + | > The prompt lineage that built this project - extracted from real sessions, curated and redacted by the author, generated by [treetrace](https://github.com/REPLACE-ME-ORG/treetrace). | |
| + | ||
| + | ## Goal | |
| + | ||
| + | > Build a weather dashboard web app that shows the forecast for Memphis using the NWS API. Keep it a single static page. | |
| + | ||
| + | ## The Path | |
| + | ||
| + | `⬢` root · `→` direction · `↩` correction · `⚑` scope change · `◆` checkpoint · `?` question · `✗` abandoned | |
| + | ||
| + | - `⬢` **Build a weather dashboard web app that shows the forecast for Memphis using the NWS API.** <sub>(new session, 2026-06-01)</sub> | |
| + | <details><summary>full prompt</summary> | |
| + | ||
| + | > Build a weather dashboard web app that shows the forecast for Memphis using the NWS API. Keep it a single static page. | |
| + | </details> | |
| + | - `→` Try using leaflet for an interactive radar map layer on top of the forecast. | |
| + | - `↩` No, scrap the radar map, it is too heavy. | |
| + | <details><summary>full prompt</summary> | |
| + | ||
| + | > No, scrap the radar map, it is too heavy. Keep the page lightweight, just the forecast cards. | |
| + | </details> | |
| + | - `⚑` Actually wait - also add a settings panel so the user can switch cities. | |
| + | <details><summary>full prompt</summary> | |
| + | ||
| + | > Actually wait - also add a settings panel so the user can switch cities. My test key is [REDACTED:anthropic-key] and the server is at [REDACTED:url-basic-auth] | |
| + | </details> | |
| + | ||
| + | ## Course corrections & dead ends | |
| + | ||
| + | **1 correction along the way:** | |
| + | ||
| + | - ↩ No, scrap the radar map, it is too heavy. | |
| + | ||
| + | ## Reusable Prompt Pack | |
| + | ||
| + | A distilled, replayable version of the accepted path - paste into a fresh agent to rebuild something like this: | |
| + | ||
| + | ```text | |
| + | 1. Build a weather dashboard web app that shows the forecast for Memphis using the NWS API. Keep it a single static page. | |
| + | 2. Try using leaflet for an interactive radar map layer on top of the forecast. | |
| + | (constraint learned along the way: No, scrap the radar map, it is too heavy. Keep the page lightweight, just the forecast cards.) | |
| + | 3. Actually wait - also add a settings panel so the user can switch cities. My test key is [REDACTED:anthropic-key] and the server is at [REDACTED:url-basic-auth] | |
| + | ``` | |
| + | ||
| + | --- | |
| + | ||
| + | *Generated by [treetrace](https://github.com/REPLACE-ME-ORG/treetrace) · 4 prompts across 1 session · assistant-model · machine-readable lineage in `.treetrace/tree.json` ([schema](https://github.com/REPLACE-ME-ORG/treetrace/blob/main/SCHEMA.md))* |
| @@ -0,0 +1,122 @@ | ||
| + | { | |
| + | "schemaVersion": "0.1", | |
| + | "generator": { | |
| + | "name": "treetrace", | |
| + | "version": "0.1.0", | |
| + | "url": "https://github.com/REPLACE-ME-ORG/treetrace" | |
| + | }, | |
| + | "project": { | |
| + | "name": "weather-dashboard", | |
| + | "generatedAt": "2026-06-12T00:01:29.681Z", | |
| + | "sourceType": "claude-code-jsonl" | |
| + | }, | |
| + | "stats": { | |
| + | "prompts": 4, | |
| + | "sessions": 1, | |
| + | "days": 1, | |
| + | "corrections": 1, | |
| + | "scopeChanges": 1, | |
| + | "checkpoints": 0, | |
| + | "abandonedBranches": 0, | |
| + | "toolUses": 2, | |
| + | "filesTouched": 1, | |
| + | "models": [ | |
| + | "assistant-model" | |
| + | ], | |
| + | "firstTs": "2026-06-01T10:00:00.000Z", | |
| + | "lastTs": "2026-06-01T10:12:00.000Z" | |
| + | }, | |
| + | "sessions": [ | |
| + | { | |
| + | "id": "synthetic-session", | |
| + | "title": "Build a weather dashboard", | |
| + | "firstTs": "2026-06-01T10:00:00.000Z", | |
| + | "lastTs": "2026-06-01T10:12:00.000Z", | |
| + | "promptCount": 5, | |
| + | "isContinuation": false | |
| + | } | |
| + | ], | |
| + | "nodes": [ | |
| + | { | |
| + | "id": "node_001", | |
| + | "parentId": null, | |
| + | "role": "user", | |
| + | "kind": "root", | |
| + | "title": "Build a weather dashboard web app that shows the forecast for Memphis using the NWS API.", | |
| + | "text": "Build a weather dashboard web app that shows the forecast for Memphis using the NWS API. Keep it a single static page.", | |
| + | "status": "accepted", | |
| + | "nudges": 1, | |
| + | "reruns": 0, | |
| + | "session": "synthetic-session", | |
| + | "timestamp": "2026-06-01T10:00:00.000Z", | |
| + | "sourceEventIds": [ | |
| + | "u1" | |
| + | ] | |
| + | }, | |
| + | { | |
| + | "id": "node_002", | |
| + | "parentId": "node_001", | |
| + | "role": "user", | |
| + | "kind": "direction", | |
| + | "title": "Try using leaflet for an interactive radar map layer on top of the forecast.", | |
| + | "text": "Try using leaflet for an interactive radar map layer on top of the forecast.", | |
| + | "status": "accepted", | |
| + | "nudges": 0, | |
| + | "reruns": 0, | |
| + | "session": "synthetic-session", | |
| + | "timestamp": "2026-06-01T10:04:00.000Z", | |
| + | "sourceEventIds": [ | |
| + | "u5" | |
| + | ] | |
| + | }, | |
| + | { | |
| + | "id": "node_003", | |
| + | "parentId": "node_002", | |
| + | "role": "user", | |
| + | "kind": "correction", | |
| + | "title": "No, scrap the radar map, it is too heavy.", | |
| + | "text": "No, scrap the radar map, it is too heavy. Keep the page lightweight, just the forecast cards.", | |
| + | "status": "accepted", | |
| + | "nudges": 0, | |
| + | "reruns": 0, | |
| + | "session": "synthetic-session", | |
| + | "timestamp": "2026-06-01T10:09:00.000Z", | |
| + | "sourceEventIds": [ | |
| + | "u7" | |
| + | ] | |
| + | }, | |
| + | { | |
| + | "id": "node_004", | |
| + | "parentId": "node_003", | |
| + | "role": "user", | |
| + | "kind": "scope-change", | |
| + | "title": "Actually wait - also add a settings panel so the user can switch cities.", | |
| + | "text": "Actually wait - also add a settings panel so the user can switch cities. My test key is [REDACTED:anthropic-key] and the server is at [REDACTED:url-basic-auth]", | |
| + | "status": "accepted", | |
| + | "nudges": 0, | |
| + | "reruns": 0, | |
| + | "session": "synthetic-session", | |
| + | "timestamp": "2026-06-01T10:12:00.000Z", | |
| + | "sourceEventIds": [ | |
| + | "u9" | |
| + | ] | |
| + | } | |
| + | ], | |
| + | "edges": [ | |
| + | { | |
| + | "from": "node_001", | |
| + | "to": "node_002", | |
| + | "relationship": "refines" | |
| + | }, | |
| + | { | |
| + | "from": "node_002", | |
| + | "to": "node_003", | |
| + | "relationship": "corrects" | |
| + | }, | |
| + | { | |
| + | "from": "node_003", | |
| + | "to": "node_004", | |
| + | "relationship": "expands" | |
| + | } | |
| + | ] | |
| + | } |
| @@ -0,0 +1,8 @@ | ||
| + | // Single source of truth for the public repo URL. | |
| + | // | |
| + | // NOTE (2026-06-12): the launch home is not yet decided - the personal GitHub | |
| + | // account is suspended, so treetrace will be published under a NEW GitHub | |
| + | // organization. Until that org exists, this is a placeholder. Change it here | |
| + | // (or set TREETRACE_REPO_URL) and every export/doc reference updates. | |
| + | export const REPO_URL = | |
| + | process.env.TREETRACE_REPO_URL || 'https://github.com/REPLACE-ME-ORG/treetrace'; |
| @@ -1,3 +1,5 @@ | ||
| + | import { REPO_URL } from './config.js'; | |
| + | ||
| /** | ||
| * Machine-readable export: treetrace lineage schema v0.1. | ||
| * Documented in SCHEMA.md with a mapping to the Agent Trace RFC. | ||
| @@ -18,7 +20,7 @@ export function renderJson(tree, opts = {}) { | ||
| return { | ||
| schemaVersion: '0.1', | ||
| - | generator: { name: generatedBy, version, url: 'https://github.com/zionboggan/treetrace' }, | |
| + | generator: { name: generatedBy, version, url: REPO_URL }, | |
| project: { | ||
| name: projectName, | ||
| generatedAt: opts.generatedAt || null, |
| @@ -1,4 +1,5 @@ | ||
| import { truncate, plural, formatDay, mdEscapePipe } from './util.js'; | ||
| + | import { REPO_URL } from './config.js'; | |
| const ICONS = { | ||
| root: '⬢', | ||
| @@ -9,7 +10,6 @@ const ICONS = { | ||
| question: '?', | ||
| }; | ||
| - | const REPO_URL = 'https://github.com/zionboggan/treetrace'; | |
| const MAX_NODE_TEXT = 1500; | ||
| export function renderMarkdown(tree, opts = {}) { |