cli-consumption 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. cli_consumption-0.0.1/.agents/skills/add-cli-adapter/SKILL.md +21 -0
  2. cli_consumption-0.0.1/.agents/skills/add-cli-adapter/agents/openai.yaml +4 -0
  3. cli_consumption-0.0.1/.agents/skills/audit-usage-privacy/SKILL.md +22 -0
  4. cli_consumption-0.0.1/.agents/skills/audit-usage-privacy/agents/openai.yaml +4 -0
  5. cli_consumption-0.0.1/.agents/skills/evolve-storage-schema/SKILL.md +21 -0
  6. cli_consumption-0.0.1/.agents/skills/evolve-storage-schema/agents/openai.yaml +4 -0
  7. cli_consumption-0.0.1/.agents/skills/yeet-github/SKILL.md +66 -0
  8. cli_consumption-0.0.1/.agents/skills/yeet-github/agents/openai.yaml +4 -0
  9. cli_consumption-0.0.1/.agents/skills/yolo/SKILL.md +48 -0
  10. cli_consumption-0.0.1/.agents/skills/yolo/agents/openai.yaml +4 -0
  11. cli_consumption-0.0.1/.github/workflows/ci.yml +26 -0
  12. cli_consumption-0.0.1/.github/workflows/release.yaml +122 -0
  13. cli_consumption-0.0.1/.gitignore +18 -0
  14. cli_consumption-0.0.1/.pre-commit-config.yaml +35 -0
  15. cli_consumption-0.0.1/.python-version +1 -0
  16. cli_consumption-0.0.1/AGENTS.md +67 -0
  17. cli_consumption-0.0.1/CONTRIBUTING.md +38 -0
  18. cli_consumption-0.0.1/LICENSE +201 -0
  19. cli_consumption-0.0.1/NOTICE +4 -0
  20. cli_consumption-0.0.1/PKG-INFO +192 -0
  21. cli_consumption-0.0.1/README.md +164 -0
  22. cli_consumption-0.0.1/docs/architecture.md +74 -0
  23. cli_consumption-0.0.1/docs/privacy.md +69 -0
  24. cli_consumption-0.0.1/docs/provider-support.md +24 -0
  25. cli_consumption-0.0.1/docs/roadmap.md +26 -0
  26. cli_consumption-0.0.1/pyproject.toml +72 -0
  27. cli_consumption-0.0.1/src/cli_consumption/__init__.py +10 -0
  28. cli_consumption-0.0.1/src/cli_consumption/__main__.py +4 -0
  29. cli_consumption-0.0.1/src/cli_consumption/adapters/__init__.py +3 -0
  30. cli_consumption-0.0.1/src/cli_consumption/adapters/base.py +18 -0
  31. cli_consumption-0.0.1/src/cli_consumption/adapters/codex.py +591 -0
  32. cli_consumption-0.0.1/src/cli_consumption/api.py +66 -0
  33. cli_consumption-0.0.1/src/cli_consumption/cli.py +245 -0
  34. cli_consumption-0.0.1/src/cli_consumption/dashboard.py +431 -0
  35. cli_consumption-0.0.1/src/cli_consumption/exporting.py +31 -0
  36. cli_consumption-0.0.1/src/cli_consumption/models.py +60 -0
  37. cli_consumption-0.0.1/src/cli_consumption/py.typed +0 -0
  38. cli_consumption-0.0.1/src/cli_consumption/storage.py +525 -0
  39. cli_consumption-0.0.1/src/cli_consumption/sync.py +25 -0
  40. cli_consumption-0.0.1/tests/conftest.py +133 -0
  41. cli_consumption-0.0.1/tests/test_api.py +61 -0
  42. cli_consumption-0.0.1/tests/test_cli.py +101 -0
  43. cli_consumption-0.0.1/tests/test_codex_adapter.py +174 -0
  44. cli_consumption-0.0.1/tests/test_storage_and_exports.py +276 -0
  45. cli_consumption-0.0.1/tests/test_sync.py +33 -0
  46. cli_consumption-0.0.1/uv.lock +742 -0
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: add-cli-adapter
3
+ description: Add or update an AI coding CLI provider adapter for CLI Consumption. Use for provider discovery, local file or endpoint parsing, normalized conversation/turn/model/tool mapping, provider capability status, compatibility fixtures, and adapter documentation.
4
+ ---
5
+
6
+ # Add a CLI adapter
7
+
8
+ 1. Verify the provider's current data sources and terms from primary documentation.
9
+ 2. Record which fields are stable, optional, inferred, or unavailable. Never invent a
10
+ cross-provider equivalence.
11
+ 3. Add synthetic fixtures covering the smallest supported format, malformed input, and
12
+ a realistic multi-turn conversation. Do not copy personal provider data.
13
+ 4. Implement the adapter contract under `src/cli_consumption/adapters/`. Keep all
14
+ provider-specific logic there and emit only the normalized snapshot fields.
15
+ 5. Apply `$audit-usage-privacy` to the input fields, transient parsing, errors, logs,
16
+ snapshot payload, SQL rows, CSV, and dashboard.
17
+ 6. Test stable IDs, duplicate copies, model attribution, token semantics, tool names,
18
+ partial records, and format changes.
19
+ 7. Register the adapter in the CLI only after its tests pass. Update
20
+ `docs/provider-support.md` with precise limitations.
21
+ 8. Run every quality gate in `AGENTS.md`.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Add CLI Adapter"
3
+ short_description: "Add a privacy-safe AI CLI ingestion adapter"
4
+ default_prompt: "Use $add-cli-adapter to implement the next AI CLI provider."
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: audit-usage-privacy
3
+ description: Audit CLI Consumption changes for metadata minimization and sensitive-content leakage. Use for adapters, API payloads, storage, errors, logging, exports, dashboards, fixtures, documentation, or any change that handles provider files or conversation-derived data.
4
+ ---
5
+
6
+ # Audit usage privacy
7
+
8
+ 1. Enumerate every input field read and every output surface changed: memory snapshot,
9
+ SQL, API, CSV, HTML, logs, errors, fixtures, and documentation examples.
10
+ 2. Require an explicit analytical purpose for each persisted field. Prefer derived
11
+ labels and counts over raw values.
12
+ 3. Reject prompts, responses, instructions, raw events, tool arguments or results,
13
+ commands, patches, environment values, credentials, original paths, and arbitrary
14
+ metadata blobs.
15
+ 4. Allow transient inspection only when required to derive an approved value, then
16
+ discard the source content immediately.
17
+ 5. Check malformed-input errors and debug paths for accidental raw-record output.
18
+ 6. Add a synthetic canary secret to fixtures and assert that it is absent from
19
+ snapshots, databases, API bodies, CSV files, dashboards, and logs.
20
+ 7. Re-read `docs/privacy.md` and update it if the approved boundary changes.
21
+ 8. Report each reviewed surface and any residual operational disclosure such as project
22
+ names or activity timestamps.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Audit Usage Privacy"
3
+ short_description: "Keep sensitive conversation content out of exports"
4
+ default_prompt: "Use $audit-usage-privacy to review this ingestion or export change."
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: evolve-storage-schema
3
+ description: Evolve CLI Consumption persistence safely across SQLite and PostgreSQL. Use for tables, columns, indexes, constraints, migrations, retention, deduplication, stable identifiers, ingestion transactions, or storage compatibility changes.
4
+ ---
5
+
6
+ # Evolve the storage schema
7
+
8
+ 1. Define the provider-neutral meaning, nullability, cardinality, and lifecycle of each
9
+ proposed field before editing the schema.
10
+ 2. Apply `$audit-usage-privacy`; reject fields that expose content or machine-private
11
+ paths without an explicit accepted design change.
12
+ 3. Specify upgrade, downgrade, and mixed-version behavior. Introduce a migration tool
13
+ before the first incompatible released schema change.
14
+ 4. Preserve provider-qualified stable IDs and atomic replacement of a conversation with
15
+ its child records.
16
+ 5. Test SQLite directly. Test PostgreSQL for SQL, types, constraints, indexes, and
17
+ transaction behavior whenever the change can differ by dialect.
18
+ 6. Cover repeated ingestion, less-complete duplicates, more-complete replacements,
19
+ partial failure, empty datasets, and concurrent writers as applicable.
20
+ 7. Update architecture, privacy, export, and API documentation together with the code.
21
+ 8. Run every quality gate in `AGENTS.md`.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Evolve Storage Schema"
3
+ short_description: "Change SQLite and PostgreSQL schemas safely"
4
+ default_prompt: "Use $evolve-storage-schema to plan and implement this data model change."
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: yeet-github
3
+ description: Publish the current repository work in a draft GitHub pull request with gh.
4
+ ---
5
+
6
+ # Yeet GitHub
7
+
8
+ Run from the repository root. Publish the current work without merging the pull request. Use `$yolo` when the user explicitly requests publication, squash merge, and cleanup as one workflow.
9
+
10
+ ## 1. Verify context
11
+
12
+ 1. Read all repository instructions, including `AGENTS.md` and `CONTRIBUTING.md` when present.
13
+ 2. Read `docs/product-specification.md` when present and map the objective to relevant tickets and acceptance criteria without expanding scope.
14
+ 3. Summarize the objective and identify only the changes that belong to it.
15
+ 4. Inspect `git status --short --branch`, `git diff --check`, `git diff`, `git diff --stat`, and relevant untracked files.
16
+ 5. Verify `gh --version`, `gh auth status`, `git remote -v`, and the default branch with `gh repo view --json defaultBranchRef,nameWithOwner`.
17
+ 6. Require an authenticated `gh` session and an `origin` remote matching the expected GitHub repository. Stop before mutation if a prerequisite is missing.
18
+ 7. Preserve unrelated changes. Stop before staging if inclusion is ambiguous.
19
+
20
+ Read the installed command help before relying on version-sensitive options:
21
+
22
+ ```bash
23
+ gh pr create --help
24
+ gh pr view --help
25
+ gh pr merge --help
26
+ ```
27
+
28
+ ## 2. Select branches
29
+
30
+ 1. Capture the target branch from `defaultBranchRef`.
31
+ 2. If the current branch is the target, create a short `<type>/<issue>-<subject>` branch using the repository's allowed Conventional Commit types. Never include `codex`, an agent name, or an automation-tool name in the branch name.
32
+ 3. Keep an existing work branch only when it clearly matches the request.
33
+ 4. Capture exact source and target names. Reject an empty, identical, protected, or unexpected source branch.
34
+ 5. Check that proposed local and remote branches do not already exist in an ambiguous state.
35
+
36
+ ## 3. Validate and commit
37
+
38
+ 1. Run the canonical checks in `AGENTS.md` that apply to the changed domain. Never invent substitute commands.
39
+ 2. Review the final diff and run `git diff --check`.
40
+ 3. Present the branch, changed files, concise diff summary, checks, and known limitations; obtain explicit approval before any push or pull-request publication.
41
+ 4. After approval, stage only in-scope files. Run `git diff --cached --check` and inspect `git diff --cached --stat`.
42
+ 5. Commit using the repository convention, defaulting to an English Conventional Commit. Include a ticket reference only when one exists.
43
+ 6. Never bypass hooks. Capture the full SHA with `git rev-parse HEAD` and require a clean worktree apart from explicitly ignored local files.
44
+
45
+ Never use `git clean`, `git reset --hard`, `git checkout --`, or hook bypasses.
46
+
47
+ ## 4. Push
48
+
49
+ 1. Push the captured source branch explicitly with `git push -u origin <source-branch>`.
50
+ 2. Stop on non-fast-forward. Never rebase, resolve conflicts, or force-push without explicit authorization.
51
+ 3. Verify that the remote source SHA equals the captured local SHA.
52
+
53
+ ## 5. Open the pull request
54
+
55
+ 1. Use `gh pr list --head <source-branch> --state all` to ensure no pull request already exists.
56
+ 2. Write an English title and body covering objective, tickets and acceptance criteria, changes, technical decisions, impacts, tests, documentation, limitations, both storage profiles, and references.
57
+ 3. Create a draft pull request with `gh pr create --draft --head <source-branch> --base <target-branch> --title '<title>' --body-file <temporary-file-outside-repository>`.
58
+ 4. Remove the temporary file after the command and never track it.
59
+ 5. Verify number, URL, draft state, branches, SHA, and state with `gh pr view`.
60
+ 6. If creation has an ambiguous result, look for an existing pull request immediately and do not retry until side effects are known.
61
+
62
+ ## Result
63
+
64
+ Report the pull-request URL, number, and state; source and target branches; pushed SHA; checks and results; remaining limitations; and final `git status --short --branch`.
65
+
66
+ Never merge the pull request, delete a branch, or modify GitHub protections in this skill.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Yeet GitHub"
3
+ short_description: "Publish current work in a draft GitHub PR"
4
+ default_prompt: "Use $yeet-github to validate and publish the current work in a draft GitHub pull request."
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: yolo
3
+ description: Publish the current Codex work in a GitHub pull request, squash-merge it, then clean up its local and remote branches. Use only when the user explicitly invokes `$yolo` or requests the full publish, merge, and cleanup sequence.
4
+ ---
5
+
6
+ # Publish, merge, and clean up
7
+
8
+ Run each phase in order from the repository root. The implicit pull request is the one for the current Codex work and current branch.
9
+
10
+ ## 1. Publish
11
+
12
+ 1. Read all repository instructions and the product specification referenced by `AGENTS.md`.
13
+ 2. Load and follow `$yeet-github` in full to inspect, validate, commit, push, and open a draft pull request.
14
+ 3. Retain the exact source and target branches, pushed SHA, pull-request number, and URL.
15
+ 4. Stop after any failure or ambiguous external result. Never merge or clean up after a partial failure.
16
+
17
+ ## 2. Merge
18
+
19
+ 1. Explicit `$yolo` invocation authorizes merging only the pull request for the current work. It never authorizes bypassing protections or merging another pull request.
20
+ 2. Verify with `gh pr view` that the pull request exactly matches the captured source branch and SHA. Reject ambiguity or a changed head.
21
+ 3. Inspect required checks, reviews, conversations, and protections with `gh pr checks` and `gh pr view --json mergeStateStatus,reviewDecision,statusCheckRollup`.
22
+ 4. Mark a ready draft with `gh pr ready <number>`.
23
+ 5. Watch pending checks with `gh pr checks <number> --watch --interval 10`; stop and report any failing check.
24
+ 6. Present the final state and obtain explicit approval immediately before merging and deleting branches.
25
+ 7. After approval, use `gh pr merge <number> --squash --delete-branch --match-head-commit <source-sha>`.
26
+ 8. If GitHub queues the merge, keep monitoring. Clean up only after `gh pr view <number> --json state,mergedAt,mergeCommit` reports `MERGED`.
27
+
28
+ ## 3. Clean up
29
+
30
+ 1. Reconfirm the merged state and capture the merge commit SHA.
31
+ 2. Refuse cleanup if new tracked, staged, or untracked work appeared after the source commit.
32
+ 3. Run `git fetch --prune origin`.
33
+ 4. Switch to the target branch and update it only by fast-forward with `git switch <target-branch>` and `git pull --ff-only origin <target-branch>`.
34
+ 5. Delete the exact local source branch if it remains. `git branch -D <source-branch>` is allowed only after verified squash merge.
35
+ 6. If the unprotected remote branch remains, obtain fresh explicit approval before `git push origin --delete <source-branch>`.
36
+ 7. Run `git status --short --branch` and report the final state.
37
+
38
+ ## Guardrails
39
+
40
+ - Never use `git clean`, `git reset --hard`, or recursive deletion.
41
+ - Never delete the target branch, a protected branch, or a branch whose exact name was not captured before merge.
42
+ - Never clean another worktree.
43
+ - Never confuse green checks, approval, or mergeability with an actual merge.
44
+ - Never extend this authorization to a pull request unrelated to the current work.
45
+
46
+ ## Result
47
+
48
+ Report the pull-request URL and state, merged SHA, deleted branches, current branch, and final `git status`.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Yolo GitHub"
3
+ short_description: "Publish, squash-merge, and clean up a PR"
4
+ default_prompt: "Use $yolo to publish, squash-merge, and clean up the current GitHub work."
@@ -0,0 +1,26 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ quality:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v6
17
+ with:
18
+ enable-cache: true
19
+ python-version: "3.14"
20
+ - run: uv sync --locked --all-groups
21
+ - run: uv run pre-commit run --all-files --show-diff-on-failure
22
+ - run: uv run ruff format --check .
23
+ - run: uv run ruff check .
24
+ - run: uv run ty check --output-format github
25
+ - run: uv run pytest --cov --cov-report=term-missing
26
+ - run: uv build
@@ -0,0 +1,122 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths: [pyproject.toml]
7
+
8
+ concurrency:
9
+ group: release
10
+ cancel-in-progress: false
11
+
12
+ jobs:
13
+ detect-version:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ contents: read
17
+ outputs:
18
+ changed: ${{ steps.version.outputs.changed }}
19
+ version: ${{ steps.version.outputs.version }}
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+ - uses: astral-sh/setup-uv@v6
25
+ with:
26
+ python-version: "3.14"
27
+ - name: Detect project version change
28
+ id: version
29
+ env:
30
+ BEFORE_SHA: ${{ github.event.before }}
31
+ run: |
32
+ set -euo pipefail
33
+
34
+ current_version="$(uv version --short)"
35
+ previous_version=""
36
+ if git cat-file -e "${BEFORE_SHA}:pyproject.toml" 2>/dev/null; then
37
+ previous_version="$(
38
+ git show "${BEFORE_SHA}:pyproject.toml" |
39
+ python -c 'import sys, tomllib; print(tomllib.load(sys.stdin.buffer)["project"]["version"])'
40
+ )"
41
+ fi
42
+
43
+ echo "version=${current_version}" >> "${GITHUB_OUTPUT}"
44
+ if [[ "${current_version}" == "${previous_version}" ]]; then
45
+ echo "changed=false" >> "${GITHUB_OUTPUT}"
46
+ else
47
+ echo "changed=true" >> "${GITHUB_OUTPUT}"
48
+ fi
49
+
50
+ build:
51
+ needs: detect-version
52
+ if: needs.detect-version.outputs.changed == 'true'
53
+ runs-on: ubuntu-latest
54
+ permissions:
55
+ contents: read
56
+ steps:
57
+ - uses: actions/checkout@v4
58
+ - uses: astral-sh/setup-uv@v6
59
+ with:
60
+ enable-cache: true
61
+ python-version: "3.14"
62
+ - run: uv sync --locked --all-groups
63
+ - run: uv run pre-commit run --all-files --show-diff-on-failure
64
+ - run: uv run ruff format --check .
65
+ - run: uv run ruff check .
66
+ - run: uv run ty check --output-format github
67
+ - run: uv run pytest --cov --cov-report=term-missing
68
+ - run: uv build
69
+ - name: Upload distributions
70
+ uses: actions/upload-artifact@v4
71
+ with:
72
+ name: python-package-distributions
73
+ path: dist/
74
+ if-no-files-found: error
75
+ overwrite: true
76
+
77
+ tag:
78
+ needs: [detect-version, build]
79
+ runs-on: ubuntu-latest
80
+ permissions:
81
+ contents: write
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ with:
85
+ fetch-depth: 0
86
+ - name: Tag version commit
87
+ env:
88
+ RELEASE_VERSION: ${{ needs.detect-version.outputs.version }}
89
+ run: |
90
+ set -euo pipefail
91
+
92
+ tag="v${RELEASE_VERSION}"
93
+ git fetch --tags origin
94
+ if git rev-parse --verify --quiet "refs/tags/${tag}" >/dev/null; then
95
+ tagged_commit="$(git rev-list -n 1 "${tag}")"
96
+ if [[ "${tagged_commit}" != "${GITHUB_SHA}" ]]; then
97
+ echo "Tag ${tag} already points to ${tagged_commit}, not ${GITHUB_SHA}." >&2
98
+ exit 1
99
+ fi
100
+ else
101
+ git config user.name "github-actions[bot]"
102
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
103
+ git tag --annotate "${tag}" --message "Release ${RELEASE_VERSION}" "${GITHUB_SHA}"
104
+ git push origin "refs/tags/${tag}"
105
+ fi
106
+
107
+ publish:
108
+ needs: [detect-version, tag]
109
+ runs-on: ubuntu-latest
110
+ environment:
111
+ name: pypi
112
+ url: https://pypi.org/p/cli-consumption
113
+ permissions:
114
+ id-token: write
115
+ steps:
116
+ - name: Download distributions
117
+ uses: actions/download-artifact@v4
118
+ with:
119
+ name: python-package-distributions
120
+ path: dist/
121
+ - name: Publish distributions to PyPI
122
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,18 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ .coverage
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ reports/
12
+ *.sqlite
13
+ *.sqlite3
14
+ .env
15
+
16
+ # Machine-specific orchestration context. These files must never be committed.
17
+ .agents/orchestrator.md
18
+ .agents/local-environment.md
@@ -0,0 +1,35 @@
1
+ minimum_pre_commit_version: "4.6.2"
2
+ default_install_hook_types: [pre-commit, pre-push]
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v6.0.0
7
+ hooks:
8
+ - id: trailing-whitespace
9
+ - id: end-of-file-fixer
10
+ - id: check-added-large-files
11
+ - id: check-merge-conflict
12
+ - id: check-toml
13
+ - id: check-yaml
14
+
15
+ - repo: https://github.com/astral-sh/ruff-pre-commit
16
+ rev: v0.16.4
17
+ hooks:
18
+ - id: ruff-check
19
+ - id: ruff-format
20
+
21
+ - repo: local
22
+ hooks:
23
+ - id: ty
24
+ name: ty
25
+ entry: uv run ty check
26
+ language: system
27
+ pass_filenames: false
28
+ require_serial: true
29
+ - id: pytest
30
+ name: pytest
31
+ entry: uv run pytest -W error::ResourceWarning --cov --cov-report=term-missing
32
+ language: system
33
+ pass_filenames: false
34
+ require_serial: true
35
+ stages: [pre-push]
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,67 @@
1
+ # Repository instructions
2
+
3
+ ## Authority and scope
4
+
5
+ Read this file, `README.md`, `CONTRIBUTING.md`, and the relevant documents under
6
+ `docs/` before changing the repository. Keep changes scoped to one short-lived branch
7
+ and one coherent pull request.
8
+
9
+ The project is a Python 3.14+ package managed exclusively with `uv`. Do not introduce
10
+ another package manager, task runner, ORM, web framework, or migration tool without an
11
+ accepted architecture decision.
12
+
13
+ ## Product invariants
14
+
15
+ - Never collect or persist prompts, responses, tool arguments, environment values,
16
+ credentials, or raw rollout events.
17
+ - Treat every provider file and API payload as untrusted input.
18
+ - Keep the normalized model provider-neutral; provider-specific parsing belongs in
19
+ `src/cli_consumption/adapters/`.
20
+ - Support SQLite and PostgreSQL for every persisted schema change.
21
+ - Make ingestion idempotent and safe to repeat after partial failures.
22
+ - Preserve stable conversation IDs and prefer the most complete duplicate copy.
23
+ - Keep generated dashboards self-contained and free of network requests.
24
+ - Do not claim that local token events represent billing data.
25
+
26
+ ## Required skills
27
+
28
+ - Use `.agents/skills/add-cli-adapter` for a new provider or provider format change.
29
+ - Use `.agents/skills/evolve-storage-schema` for tables, columns, indexes, migrations,
30
+ retention, or compatibility changes.
31
+ - Use `.agents/skills/audit-usage-privacy` for collectors, API payloads, exports,
32
+ dashboards, logging, or changes that can cross the privacy boundary.
33
+ - Use `.agents/skills/yeet-github` only when explicitly asked to publish a draft pull
34
+ request. Use `.agents/skills/yolo` only when explicitly invoked for the full publish,
35
+ squash-merge, and cleanup workflow.
36
+
37
+ ## Quality gates
38
+
39
+ Run all of the following before requesting review:
40
+
41
+ ```bash
42
+ uv run pre-commit run --all-files
43
+ uv run ruff format --check .
44
+ uv run ruff check .
45
+ uv run ty check
46
+ uv run pytest --cov --cov-report=term-missing
47
+ uv build
48
+ ```
49
+
50
+ Add tests for every behavioral change. Include malformed and adversarial provider data
51
+ for parsers, idempotency cases for ingestion, authentication cases for the API, and
52
+ privacy assertions for every new exported field.
53
+
54
+ ## Trunk-based workflow
55
+
56
+ - Branch from current `main` using a short-lived `feat/`, `fix/`, `docs/`, or `chore/`
57
+ branch.
58
+ - Never push directly to `main`, force-push shared history, or bypass required checks.
59
+ - Prefer one focused commit before review and squash-merge the pull request.
60
+ - Rebase or merge current `main` before final validation when the branch is stale.
61
+ - Delete the source branch only after the pull request is verified as merged.
62
+
63
+ ## Local orchestration files
64
+
65
+ `.agents/orchestrator.md` and `.agents/local-environment.md` are machine-specific and
66
+ ignored deliberately. Keep durable, portable decisions in tracked documentation or
67
+ architecture decision records instead.
@@ -0,0 +1,38 @@
1
+ # Contributing
2
+
3
+ ## Set up the project
4
+
5
+ ```bash
6
+ git switch main
7
+ git pull --ff-only
8
+ git switch -c feat/short-description
9
+ uv sync --all-groups
10
+ uv run pre-commit install
11
+ ```
12
+
13
+ Use `uv add`, `uv remove`, and `uv lock` for dependency changes. Do not edit the lock
14
+ file manually.
15
+
16
+ ## Make a change
17
+
18
+ Keep provider parsing behind the adapter interface and normalized persistence behind
19
+ the storage module. A new field must have a documented meaning across providers or be
20
+ explicitly namespaced as provider-specific.
21
+
22
+ Do not add telemetry. Test fixtures must be synthetic and must not contain copied user
23
+ conversations or credentials.
24
+
25
+ ## Validate and review
26
+
27
+ Run the quality gates documented in `AGENTS.md`, inspect the complete diff, then open a
28
+ pull request. The pull request must explain the behavior, privacy impact, storage
29
+ compatibility, tests, and any remaining limitation. Merge by squash after required
30
+ checks pass and review is complete.
31
+
32
+ ## Release
33
+
34
+ Update the project version with `uv version <version>` and include the resulting
35
+ `pyproject.toml` and `uv.lock` changes in a pull request. When that version change is
36
+ squash-merged into `main`, the release workflow reruns the quality gates, builds the
37
+ distributions, tags the merge commit as `v<version>`, and publishes to PyPI through
38
+ Trusted Publishing. Do not create the release tag manually.