{"id":51783222,"url":"https://github.com/alsi-lawr/chatgpt-analysis","last_synced_at":"2026-07-20T14:02:39.177Z","repository":{"id":371208630,"uuid":"1299122366","full_name":"alsi-lawr/chatgpt-analysis","owner":"alsi-lawr","description":"Local-first, reproducible, evidence-linked analysis of user-supplied ChatGPT exports.","archived":false,"fork":false,"pushed_at":"2026-07-14T00:10:37.000Z","size":58,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-14T02:09:43.500Z","etag":null,"topics":["chatgpt","chatgpt-export","cli","data-analysis","digital-humanities","local-first","privacy","python","reproducible-research","research-software","sqlite"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alsi-lawr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-13T09:48:53.000Z","updated_at":"2026-07-14T00:10:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alsi-lawr/chatgpt-analysis","commit_stats":null,"previous_names":["alsi-lawr/chatgpt-analysis"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/alsi-lawr/chatgpt-analysis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alsi-lawr%2Fchatgpt-analysis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alsi-lawr%2Fchatgpt-analysis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alsi-lawr%2Fchatgpt-analysis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alsi-lawr%2Fchatgpt-analysis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alsi-lawr","download_url":"https://codeload.github.com/alsi-lawr/chatgpt-analysis/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alsi-lawr%2Fchatgpt-analysis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35688504,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"ssl_error","status_checked_at":"2026-07-20T02:08:09.736Z","response_time":111,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatgpt","chatgpt-export","cli","data-analysis","digital-humanities","local-first","privacy","python","reproducible-research","research-software","sqlite"],"created_at":"2026-07-20T14:02:37.546Z","updated_at":"2026-07-20T14:02:39.161Z","avatar_url":"https://github.com/alsi-lawr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003ch1\u003eChatGPT Export Analysis\u003c/h1\u003e\n\n\u003cp\u003e\u003cstrong\u003eTurn your ChatGPT export into a reproducible, queryable, evidence-linked corpus.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003e\n  Normalize the selected conversation branch, measure the corpus, apply your own taxonomy,\n  and trace every coded finding back to the source turn—without sending transcript text anywhere by default.\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003ca href=\"https://github.com/alsi-lawr/chatgpt-analysis/actions/workflows/ci.yml\"\u003e\u003cimg alt=\"CI status\" src=\"https://github.com/alsi-lawr/chatgpt-analysis/actions/workflows/ci.yml/badge.svg?branch=master\"\u003e\u003c/a\u003e\n  \u003ca href=\"pyproject.toml\"\u003e\u003cimg alt=\"Python 3.11+\" src=\"https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python\u0026logoColor=white\"\u003e\u003c/a\u003e\n  \u003ca href=\"pyproject.toml\"\u003e\u003cimg alt=\"Zero runtime dependencies\" src=\"https://img.shields.io/badge/runtime_dependencies-0-2ea44f\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"MIT license\" src=\"https://img.shields.io/badge/license-MIT-blue\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003ca href=\"#quick-start\"\u003eQuick start\u003c/a\u003e ·\n  \u003ca href=\"#how-the-pipeline-works\"\u003ePipeline\u003c/a\u003e ·\n  \u003ca href=\"#configuration-controls-the-claims\"\u003eConfiguration\u003c/a\u003e ·\n  \u003ca href=\"#optional-model-or-human-workers\"\u003eWorkers\u003c/a\u003e ·\n  \u003ca href=\"#security-and-interpretation-boundaries\"\u003eBoundaries\u003c/a\u003e\n\u003c/p\u003e\n\n\u003c/div\u003e\n\n\u003e [!IMPORTANT]\n\u003e **Your export stays local unless you deliberately run an external worker.** The deterministic pipeline uses only Python's standard library and contains no hosted-model SDK. Worker task payloads include transcript text, so inspect them before connecting any model provider.\n\n## Your export is data. This makes it an analysis corpus.\n\nA ChatGPT export gives you conversation records, not a trustworthy research workflow. Branches can be traversed inconsistently, long chats exceed useful review windows, keyword counts are easy to overinterpret, and model-generated labels can lose their connection to the text that supposedly supports them.\n\nChatGPT Export Analysis turns that dump into a reviewable workspace:\n\n- **Stable normalization** follows the selected branch and assigns deterministic conversation and turn identities.\n- **Reproducible local analysis** computes inventories, distributions, periods, length buckets, segments, and configured pattern cards.\n- **Evidence-linked coding** requires labels, hypotheses, and observations to cite in-scope turn IDs.\n- **Explicit automation boundaries** keep model providers outside the core pipeline behind JSON task queues.\n- **Deterministic review consolidation** unions additive coding and evidence, retains hypothesis-rating sensitivity ranges, keeps primary-reviewer relevance canonical, and makes every third review audit-only.\n- **Acceptance checks** rehash source files and verify transcript digests, evidence references, report configuration, SQLite row counts, and database integrity.\n\n### At a glance\n\n| | |\n|---|---|\n| **Use it for** | Auditing and exploring patterns in your own ChatGPT export |\n| **Inputs** | Export ZIP, JSON, JSONL, or a directory containing supported conversation files |\n| **Outputs** | Normalized JSONL, deterministic metrics, evidence cards, Markdown/JSON reports, SQLite, and optional FTS5 |\n| **Model use** | Optional and provider-neutral; a model or human-coded executable reads JSON on stdin and writes JSON on stdout |\n| **Runtime** | Python 3.11+ with no third-party runtime dependencies |\n\n## Quick start\n\n### 1. Install from a clone\n\n```bash\ngit clone https://github.com/alsi-lawr/chatgpt-analysis.git\ncd chatgpt-analysis\n\npython -m venv .venv\n. .venv/bin/activate\npython -m pip install .\n\nchatgpt-analysis --version\n```\n\nFor editable development, use `python -m pip install -e .` instead.\n\n### 2. Create an analysis project\n\n```bash\nchatgpt-analysis init my-analysis\ncd my-analysis\n```\n\nThe scaffold contains:\n\n```text\nmy-analysis/\n├── analysis.json\n├── taxonomy.json\n├── prompts/\n│   ├── adjudication.md  # legacy third-review audit contract\n│   ├── reducer.md\n│   ├── review.md\n│   ├── signals.md\n│   └── triage.md\n└── schemas/\n    ├── model-output.schema.json\n    └── task.schema.json\n```\n\nThe prompt and schema files are worker-facing reference copies. Task payloads carry the tool version's current instructions and output schema; editing the copied Markdown prompts does not change generated tasks.\n\nPut the export at `export.zip` inside this directory, or change `source.path` in `analysis.json` to the absolute or project-relative location of your export. The generated configuration is ready for a local-only run; edit `taxonomy.json` when you want project-specific coding.\n\n### 3. Run the local pipeline\n\n```bash\nchatgpt-analysis run --config analysis.json\n```\n\n`run` normalizes the export, calculates metrics, builds segments and deterministic cards, reduces the results, recreates SQLite, writes reports, and performs acceptance checks. It never invokes a model; with routing disabled—the generated default—it also emits no model tasks.\n\n### 4. Inspect the result\n\nStart with these artifacts:\n\n| Artifact | What it answers |\n|---|---|\n| `workspace/reports/summary.md` | What is in the corpus, which configured labels matched, and what limitations apply? |\n| `workspace/reports/summary.json` | What are the same results in machine-readable form? |\n| `workspace/audits/acceptance.json` | Did source, evidence, configuration, and index consistency checks pass? |\n| `workspace/index/analysis.sqlite` | How can I query conversations, turns, segments, cards, and evidence directly? |\n| `workspace/normalized/turns.jsonl` | Which canonical turn does an evidence link refer to? |\n\n```bash\ncat workspace/reports/summary.md\npython -m json.tool workspace/audits/acceptance.json\n```\n\n`accept` exits nonzero for failed checks. Pending worker tasks and quarantined outputs are reported as warnings rather than disguised as completed analysis.\n\n## How the pipeline works\n\n```mermaid\nflowchart LR\n    A[\"Export ZIP / JSON / JSONL\"] --\u003e B[\"Inventory\u003cbr/\u003enormalize + hash\"]\n    B --\u003e C[\"Metrics + bounded segments\"]\n    C --\u003e D[\"Local taxonomy + routing\"]\n    D --\u003e E[\"Deterministic reducer\"]\n    E --\u003e F[\"SQLite + reports + acceptance\"]\n\n    D -. \"routing enabled\" .-\u003e G[\"JSON task queues\"]\n    G --\u003e H[\"Your model or human worker\"]\n    H --\u003e I[\"Validate + independent review\"]\n    I --\u003e E\n```\n\nEvery stage is available independently, which is useful when developing a taxonomy, diagnosing an adapter, or rerunning only downstream outputs.\n\n| Stage | Command | Primary output |\n|---|---|---|\n| Normalize and snapshot | `chatgpt-analysis inventory --config analysis.json` | `normalized/*.jsonl`, source hashes, inventory |\n| Compute corpus metrics | `chatgpt-analysis metrics --config analysis.json` | `metrics/deterministic.json` |\n| Build overlapping windows | `chatgpt-analysis segments --config analysis.json` | `segments/segments.jsonl` |\n| Apply patterns and route tasks | `chatgpt-analysis analyze-local --config analysis.json` | deterministic cards and primary worker queues |\n| Select and merge valid cards | `chatgpt-analysis reduce --config analysis.json` | reduced conversation and hypothesis records |\n| Rebuild the query index | `chatgpt-analysis build-index --config analysis.json` | `index/analysis.sqlite` |\n| Render summaries | `chatgpt-analysis report --config analysis.json` | `reports/summary.{md,json}` |\n| Verify the workspace | `chatgpt-analysis accept --config analysis.json` | `audits/acceptance.json` |\n\n### What “reproducible” means here\n\nGiven the same visible source records, configuration, and accepted worker results (if any), normalization, metrics, segmentation, deterministic coding, reduction, and SQLite reconstruction use stable ordering and identifiers. The provenance ledger records the tool version, configuration digest, output hashes, and execution time for each stage. Acceptance then verifies the boundaries that matter for interpretation instead of treating a successful process exit as proof of a valid corpus.\n\n## Configuration controls the claims\n\nThe tool deliberately avoids baking one interpretation into the executable. The generated [`analysis.json`](config/analysis.example.json) controls corpus construction; [`taxonomy.json`](config/taxonomy.example.json) controls what is coded.\n\n| Setting | Effect |\n|---|---|\n| `source.path` | Export ZIP, JSON/JSONL file, or source directory |\n| `source.visible_roles` | Roles retained in the canonical transcript; defaults to `user` and `assistant` |\n| `timezone` | IANA timezone used to assign conversations to date periods |\n| `periods` | Optional, inclusive date ranges; ranges may overlap intentionally |\n| `length_buckets` | Named conversation-size bands based on visible turn count |\n| `segmentation` | Maximum turns, maximum characters, and overlap for worker scopes |\n| `routing` | Whether and why a conversation is sent to an optional worker queue |\n| `workers` | Retry count and whether independent review is required before model results are selected |\n\n### Periods and missing dates\n\nPeriod membership uses the conversation creation timestamp converted to the configured timezone:\n\n```json\n\"periods\": [\n  {\"id\": \"before-change\", \"start\": \"2023-01-01\", \"end\": \"2024-12-31\"},\n  {\"id\": \"after-change\", \"start\": \"2025-01-01\", \"end\": \"2026-12-31\"}\n]\n```\n\n- With no configured periods, dated conversations belong to `all`.\n- Missing or malformed creation timestamps belong to `unknown_date`.\n- Dated conversations outside every range belong to `outside_defined_periods`.\n- Overlapping periods intentionally count the same conversation in more than one range.\n\n### Taxonomy dimensions\n\nEach taxonomy item has a stable ID plus optional case-insensitive keywords and regular expressions:\n\n```json\n{\n  \"version\": \"example-1\",\n  \"dimensions\": {\n    \"domains\": [\n      {\n        \"id\": \"software\",\n        \"keywords\": [\"code\", \"debug\"],\n        \"regex\": [\"\\\\b(api|cli)\\\\b\"]\n      }\n    ],\n    \"signals\": [\n      {\n        \"id\": \"verification_request\",\n        \"keywords\": [\"verify\", \"cite a source\"],\n        \"regex\": []\n      }\n    ],\n    \"sensitivities\": []\n  },\n  \"hypotheses\": []\n}\n```\n\nDimension names are otherwise project-defined. `signals` also become event cards; `sensitivities` can trigger worker routing. Hypotheses can define separate support and counterevidence patterns and are summarized with evidence links.\n\n\u003e [!CAUTION]\n\u003e A pattern match is candidate coding, not semantic truth. It can be useful for transparent retrieval and routing while still being wrong about context. Reports preserve that distinction, and optional worker review does not remove the need for human interpretation.\n\nSee [`examples/analysis-with-model-routing.json`](examples/analysis-with-model-routing.json) and [`examples/taxonomy-with-hypotheses.json`](examples/taxonomy-with-hypotheses.json) for a complete routed example.\n\n### Segmentation and routing\n\nSegments overlap by a configurable number of turns so that worker scopes retain nearby context. A single turn is never split; if one turn exceeds `maximum_characters`, that one-turn segment can exceed the character target.\n\nWhen routing is enabled, a conversation can be queued because it:\n\n- always requires model or human coding;\n- crosses the visible-turn threshold;\n- has no deterministic label;\n- contains a configured hypothesis candidate; or\n- matches a configured sensitivity.\n\nRouting creates task files. It does **not** call a provider.\n\n## Supported inputs and normalization rules\n\n### Source discovery\n\n| Source | Recognized content |\n|---|---|\n| ZIP archive | Nested `conversations.json` and split `conversations-*.json` members |\n| JSON file | Conversation array, `{ \"conversations\": [...] }`, one mapping conversation, or one message-list conversation |\n| JSONL file | One mapping or message-list conversation object per nonblank line |\n| Directory | `conversations.json`, split `conversations-*.json`, or `conversations*.jsonl` files |\n\n### Conversation adapters\n\n- **OpenAI-style mapping records:** follow `current_node` through parent links. If `current_node` is absent or invalid, the adapter deterministically chooses the latest leaf by message timestamp and node ID.\n- **Message-list records:** read `messages` or `turns` arrays with common role, text/content, timestamp, and model fields.\n- **Text extraction:** reads string parts and common `text`, `caption`, and `transcript` fields from visible roles.\n- **Duplicate IDs:** records that normalize identically within the same source member are collapsed; a repeated conversation ID with different normalized content or a different source member fails visibly.\n- **Unsupported shapes:** fail rather than being silently guessed through.\n\nOnly the selected mapping branch is normalized. Binary attachments, canvas state, reactions, shared-link metadata, deleted branches, and account metadata are not reconstructed or transcribed. See [Architecture and data contracts](docs/architecture.md) for the complete assumptions.\n\n## Workspace anatomy\n\n```text\nworkspace/\n├── provenance/       # source snapshot and per-stage artifact ledger\n├── normalized/       # canonical conversations and visible turns\n├── metrics/          # inventory and deterministic distributions\n├── segments/         # overlapping turn-reference windows\n├── cards/            # deterministic triage and signal cards\n├── tasks/            # task catalog and primary/review queues\n├── results/          # accepted worker cards and quarantined output\n├── reduced/          # selected, evidence-preserving conversation cards\n├── index/            # rebuildable SQLite database and optional FTS5\n├── reports/          # Markdown and machine-readable summaries\n├── viewer/           # generated build-ready static viewer source and private data bundle\n└── audits/           # acceptance result\n```\n\nDeterministic artifacts and the SQLite index are rebuildable from the source and configuration. Preserve external worker results if you need to reproduce model- or human-coded output without running those workers again. Use a fresh or emptied output directory when you need a clean rebuild that excludes old worker artifacts. Configuration validation rejects an output directory that is the source directory or nested beneath it.\n\n## Static viewer\n\nEvery `report` run also creates `workspace/viewer/`: a fresh copy of the packaged React/Tailwind viewer plus `public/data/atlas.json`, the generated Markdown report bundle, and any local assets referenced by those reports. The viewer uses the versioned [`viewer-atlas.schema.json`](schemas/viewer-atlas.schema.json) contract and does not fabricate optional score, rolling, event, claim, thread, title, or transcript data when the generic pipeline did not produce it.\n\nBuild it from the generated workspace, rather than from the packaged source:\n\n```bash\ncd workspace/viewer\nnpm ci\nnpm run build\n```\n\nThis writes a relocatable `workspace/site/` bundle with relative data, report, and asset URLs. Browser history and report-internal links remain in-app query routes. The generated viewer is private data: protect `workspace/` like the rest of the derived analysis artifacts.\n\nThe canonical viewer source is `src/chatgpt_analysis/viewer/`. `scripts/sync_viewer.py` provides the explicit one-way source replacement used by the existing `chatgpt-export` development-atlas mirror; it preserves that mirror's generated `public/` data and local `node_modules/` directory.\n\n## Querying SQLite\n\nThe index stores normalized records alongside canonical record JSON, reduced cards, and evidence rows. If the local SQLite build supports FTS5, the pipeline also creates `turns_fts`.\n\n```bash\n# Corpus counts by visible role\nsqlite3 workspace/index/analysis.sqlite \\\n  'SELECT role, count(*) FROM turns GROUP BY role ORDER BY role;'\n\n# Evidence counts by configured label or hypothesis\nsqlite3 workspace/index/analysis.sqlite \\\n  'SELECT kind, label, count(*) FROM evidence GROUP BY kind, label ORDER BY kind, label;'\n\n# Full-text search with a short context snippet (requires FTS5)\nsqlite3 workspace/index/analysis.sqlite \\\n  \"SELECT turns.chat_id, ordinal, snippet(turns_fts, 3, '[', ']', '…', 12)\n   FROM turns_fts JOIN turns USING (turn_id)\n   WHERE turns_fts MATCH 'verification';\"\n```\n\nCheck FTS availability before relying on the final query:\n\n```bash\nsqlite3 workspace/index/analysis.sqlite \\\n  \"SELECT value FROM metadata WHERE key = 'fts5_enabled';\"\n```\n\nThe `sqlite3` command-line shell is optional; Python's standard-library `sqlite3` module can query the same database.\n\n## Optional model or human workers\n\nThe worker boundary is intentionally small:\n\n1. The local pipeline emits a bounded task as one JSON object.\n2. Your executable receives that object on stdin.\n3. It returns exactly one result object on stdout.\n4. `ingest` binds the result to its task and validates schema version, taxonomy membership, confidence/rating ranges, evidence scope, source hash, parent tasks, and reviewer identity.\n5. Invalid output is retried up to `workers.max_attempts`; exhausted or unbound output is quarantined.\n\nThe executable can call a hosted model, run a local model, or pause for human coding. Provider credentials, dependencies, network behavior, and model selection remain outside this repository.\n\n### Run a primary queue\n\nEnable routing in `analysis.json`, then run `chatgpt-analysis run` or rerun `analyze-local`. For example, to process triage tasks:\n\n```bash\nchatgpt-analysis-worker \\\n  --queue workspace/tasks/queues/triage-primary.jsonl \\\n  --output worker-output/triage-primary.jsonl \\\n  --command './my-model-worker --model MODEL_NAME'\n\nchatgpt-analysis ingest \\\n  --config analysis.json \\\n  --input worker-output/triage-primary.jsonl\n```\n\n`chatgpt-analysis-worker` resumes at the task-attempt level by skipping keys already present in its output JSONL. It launches the configured executable directly without a shell, so the command should be an executable plus arguments—not a shell pipeline. Worker diagnostics belong on stderr; stdout must contain only the result JSON object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndependent review sequence\u003c/strong\u003e\u003c/summary\u003e\n\nPrepare review tasks from accepted primary results:\n\n```bash\nchatgpt-analysis prepare \\\n  --config analysis.json \\\n  --kind triage \\\n  --stage review\n\nchatgpt-analysis-worker \\\n  --queue workspace/tasks/queues/triage-review.jsonl \\\n  --output worker-output/triage-review.jsonl \\\n  --command './my-model-worker --reviewer independent-b'\n\nchatgpt-analysis ingest \\\n  --config analysis.json \\\n  --input worker-output/triage-review.jsonl\n```\n\nRepeat the same lifecycle with `--kind signals` when signal tasks exist, then rebuild the downstream artifacts:\n\n```bash\nchatgpt-analysis reduce --config analysis.json\nchatgpt-analysis build-index --config analysis.json\nchatgpt-analysis report --config analysis.json\nchatgpt-analysis accept --config analysis.json\n```\n\n\u003c/details\u003e\n\nWith `require_independent_review: true`, reducers consolidate each primary/review pair deterministically. Domains, modes, sensitivities, `signals` event labels, and every individually valid evidence anchor are multi-label unions. Hypothesis ratings remain a `minimum`/`maximum` range with the observed values, rather than being averaged or assigned a winner. Reduced summaries contain exactly one `macro_weight: 1` record per chat, so segment count and coding density cannot give one chat extra weight.\n\nRelevance/pruning remains one canonical scalar (`empty`, `frequency_only`, or `retain`). The primary reviewer's value is canonical; the secondary value and any disagreement are retained in `review_audit` as sensitivity metadata. The streamlined pipeline does not prepare third-review tasks. Every existing accepted third-review output is listed as audit-only and cannot change relevance, labels, evidence, observations, or hypothesis ranges, regardless of how many third reviews exist. The validator requires distinct `reviewer_id` values for primary and secondary results; you remain responsible for making the underlying model or human review genuinely independent.\n\nSee the [worker integration guide](docs/worker-example.md), [task schema](schemas/task.schema.json), and [model-output schema](schemas/model-output.schema.json). The schemas document the wire shapes; ingestion also performs task-binding and semantic checks that JSON Schema alone cannot express.\n\n## Security and interpretation boundaries\n\n### Protect the corpus\n\n- Treat the original export, normalized JSONL, worker queues, worker outputs, reports, and SQLite index as sensitive transcript data.\n- Keep them out of source control and apply filesystem permissions and backup policies appropriate to the content.\n- Inspect every queue before giving it to an external worker; task payloads contain the transcript text in that scope.\n- Remember that FTS5 stores searchable plaintext locally—it is an index, not encryption.\n- Taxonomy regular expressions are trusted local configuration. Avoid pathological expressions on large exports.\n\nReport vulnerabilities through the [security policy](SECURITY.md), using only synthetic data.\n\n### Know what the results do not establish\n\n- An export can omit deleted chats, temporary chats, inaccessible attachments, alternate branches, and content absent from the exported files.\n- Pattern coding and model coding can both be wrong. Evidence links support review; they do not make a conclusion true.\n- Counts describe the supplied export, selected roles, selected branch, periods, and taxonomy—not all behavior outside that corpus.\n- Reports are not psychological assessment, causal inference, diagnosis, or proof of stable personal traits.\n\n## Reference\n\n| Resource | Purpose |\n|---|---|\n| [Architecture and data contracts](docs/architecture.md) | Trust boundaries, adapters, local stages, worker protocol, and assumptions |\n| [Worker integration example](docs/worker-example.md) | Provider adapter requirements and queue lifecycle |\n| [Example local configuration](config/analysis.example.json) | Complete default analysis settings |\n| [Example taxonomy](config/taxonomy.example.json) | Generic dimensions and pattern rules |\n| [Routed analysis example](examples/analysis-with-model-routing.json) | Periods, segmentation, and model-routing settings |\n| [Hypothesis taxonomy example](examples/taxonomy-with-hypotheses.json) | Support, counterevidence, signals, and sensitivities |\n| [Task schema](schemas/task.schema.json) | Machine-readable worker task contract |\n| [Model-output schema](schemas/model-output.schema.json) | Machine-readable worker result contract |\n| [Citation metadata](CITATION.cff) | Pseudonymous software citation metadata for research use |\n| [Changelog](CHANGELOG.md) | Versioned record of public changes |\n| [Contributing guide](CONTRIBUTING.md) | Privacy, compatibility, testing, and distribution requirements |\n| [Security policy](SECURITY.md) | Supported versions, private reporting, and operational boundaries |\n\n## Development and verification\n\nAll committed fixtures are synthetic, and the source test suite requires neither a real export nor network access. CI runs it on Python 3.11 through 3.14, then separately builds both distribution formats and exercises the installed wheel end to end.\n\n```bash\n# Run tests, CLI checks, and README validation from an editable install\npython -m unittest discover -s tests -v\npython -m chatgpt_analysis --help\npython -m chatgpt_analysis.worker --help\npython scripts/check_readme.py\n\n# Build source and wheel distributions\npython -m pip install build\npython -m build\n```\n\nThe suite covers selected-branch traversal, multimodal text extraction, ZIP and message-list adapters, bounded overlap, complete local execution, deterministic SQLite rebuilding, retry and quarantine behavior, independent-review reduction, source-mutation detection, worker resume behavior, package metadata, and scaffold-template parity. See [Contributing](CONTRIBUTING.md#distribution-verification) for the clean installed-wheel check.\n\n## Citation\n\nUse GitHub's **Cite this repository** control or the repository's [`CITATION.cff`](CITATION.cff). Citation metadata deliberately identifies the author only by the pseudonym `alsi-lawr`.\n\n## Status\n\nThe package currently reports version **0.1.0** and is classified as alpha research software. ChatGPT export shapes are not a stable public schema; unsupported records fail visibly rather than being guessed through. Review [the adapter assumptions](docs/architecture.md#adapters) before relying on results from a newly encountered export shape.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falsi-lawr%2Fchatgpt-analysis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falsi-lawr%2Fchatgpt-analysis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falsi-lawr%2Fchatgpt-analysis/lists"}