ai-profile-cli 0.3.0__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.
- ai_profile_cli-0.3.0/.gitattributes +3 -0
- ai_profile_cli-0.3.0/.github/workflows/ci.yml +29 -0
- ai_profile_cli-0.3.0/.github/workflows/publish.yml +40 -0
- ai_profile_cli-0.3.0/.gitignore +17 -0
- ai_profile_cli-0.3.0/.hypothesis/.gitignore +9 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/015c2e410aaf7eb9 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/0ba88f907dc84408 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/181e26901f2aa440 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/1d91045722da8d58 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/300729828f9fc1d2 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/3dd03d239e44486d +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/46484eb265dbc142 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/469682b22d658606 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/4787e114548c11ed +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/4b3dc9d999dfb5d7 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/5b73d75526838a3e +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/606cf4e2a9f0bcd3 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/66104b2322415e55 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/6939069d327ecd0c +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/6a7bfa945445f617 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/6d23c053eeec8d84 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/6e9774fcaa01b7a7 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/9487c4f418fac494 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/a762b1fa0f7c34ce +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/a7a1f2134e21af76 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/ae8276b72ed1f0ea +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/c827650f32894259 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/ce0d3408eab3b4ef +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/e409c1c2a387079e +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/f191e6a3a01e3bf3 +4 -0
- ai_profile_cli-0.3.0/.hypothesis/constants/f579a39123bc3edb +4 -0
- ai_profile_cli-0.3.0/.hypothesis/unicode_data/15.0.0/charmap.json.gz +0 -0
- ai_profile_cli-0.3.0/AGENTS.md +129 -0
- ai_profile_cli-0.3.0/CHANGELOG.md +132 -0
- ai_profile_cli-0.3.0/CONTRIBUTING.md +44 -0
- ai_profile_cli-0.3.0/LICENSE +21 -0
- ai_profile_cli-0.3.0/PKG-INFO +215 -0
- ai_profile_cli-0.3.0/README.md +191 -0
- ai_profile_cli-0.3.0/README.zh-TW.md +178 -0
- ai_profile_cli-0.3.0/THIRD_PARTY_NOTICES.md +48 -0
- ai_profile_cli-0.3.0/docs/PRIVACY.md +69 -0
- ai_profile_cli-0.3.0/docs/ROADMAP.md +155 -0
- ai_profile_cli-0.3.0/docs/architecture.md +347 -0
- ai_profile_cli-0.3.0/docs/assets/badge-sample-dark.svg +12 -0
- ai_profile_cli-0.3.0/docs/assets/badge-sample-light.svg +12 -0
- ai_profile_cli-0.3.0/docs/assets/banner-dark.svg +59 -0
- ai_profile_cli-0.3.0/docs/assets/banner-light.svg +59 -0
- ai_profile_cli-0.3.0/docs/assets/heatmap-sample-dark.svg +414 -0
- ai_profile_cli-0.3.0/docs/assets/heatmap-sample-light.svg +414 -0
- ai_profile_cli-0.3.0/docs/assets/social-preview.png +0 -0
- ai_profile_cli-0.3.0/docs/assets/social-preview.svg +60 -0
- ai_profile_cli-0.3.0/docs/assets/summary-sample-dark.svg +194 -0
- ai_profile_cli-0.3.0/docs/assets/summary-sample-light.svg +194 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-001-language-and-packaging.md +30 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-002-cli-framework.md +21 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-003-data-validation.md +30 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-004-sqlite-access-and-migrations.md +27 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-005-git-metadata-format.md +75 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-006-git-notes-namespace.md +30 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-007-deterministic-event-ids.md +41 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-008-evidence-precedence.md +51 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-009-private-data-handling.md +76 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-010-svg-rendering.md +50 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-011-github-authentication.md +31 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-012-schema-versioning.md +40 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-013-provider-normalization.md +41 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-014-rewritten-history.md +44 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-015-identity-matching.md +28 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-016-repository-identity-canonicalization.md +120 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-017-provider-brand-glyphs.md +390 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-018-daily-activity-series.md +87 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-019-two-tier-provider-vocabulary.md +139 -0
- ai_profile_cli-0.3.0/docs/decisions/ADR-020-collaboration-heatmap-and-badge.md +68 -0
- ai_profile_cli-0.3.0/docs/landscape.md +220 -0
- ai_profile_cli-0.3.0/docs/mvp.md +269 -0
- ai_profile_cli-0.3.0/docs/progress.md +352 -0
- ai_profile_cli-0.3.0/docs/proposal.md +1731 -0
- ai_profile_cli-0.3.0/docs/reviews/gate-disposition.md +354 -0
- ai_profile_cli-0.3.0/docs/reviews/gate-review.md +113 -0
- ai_profile_cli-0.3.0/docs/reviews/gate2-disposition.md +55 -0
- ai_profile_cli-0.3.0/docs/reviews/gate2-review.md +601 -0
- ai_profile_cli-0.3.0/docs/reviews/gate9-second-opinion.md +79 -0
- ai_profile_cli-0.3.0/docs/reviews/v0.1-run-log.md +98 -0
- ai_profile_cli-0.3.0/docs/schema.md +572 -0
- ai_profile_cli-0.3.0/pyproject.toml +50 -0
- ai_profile_cli-0.3.0/scripts/release_smoke.py +387 -0
- ai_profile_cli-0.3.0/scripts/vendor_brand_icons.py +575 -0
- ai_profile_cli-0.3.0/src/aiprofile/__init__.py +7 -0
- ai_profile_cli-0.3.0/src/aiprofile/__main__.py +7 -0
- ai_profile_cli-0.3.0/src/aiprofile/adapters/__init__.py +1 -0
- ai_profile_cli-0.3.0/src/aiprofile/adapters/trailers.py +381 -0
- ai_profile_cli-0.3.0/src/aiprofile/aggregate.py +338 -0
- ai_profile_cli-0.3.0/src/aiprofile/cli.py +299 -0
- ai_profile_cli-0.3.0/src/aiprofile/config.py +233 -0
- ai_profile_cli-0.3.0/src/aiprofile/errors.py +33 -0
- ai_profile_cli-0.3.0/src/aiprofile/export.py +201 -0
- ai_profile_cli-0.3.0/src/aiprofile/gitio.py +326 -0
- ai_profile_cli-0.3.0/src/aiprofile/privacy.py +256 -0
- ai_profile_cli-0.3.0/src/aiprofile/registry.py +200 -0
- ai_profile_cli-0.3.0/src/aiprofile/render/__init__.py +1 -0
- ai_profile_cli-0.3.0/src/aiprofile/render/badge_svg.py +90 -0
- ai_profile_cli-0.3.0/src/aiprofile/render/brand.py +514 -0
- ai_profile_cli-0.3.0/src/aiprofile/render/heatmap_svg.py +369 -0
- ai_profile_cli-0.3.0/src/aiprofile/render/summary_svg.py +1180 -0
- ai_profile_cli-0.3.0/src/aiprofile/render/themes.py +76 -0
- ai_profile_cli-0.3.0/src/aiprofile/scanner.py +203 -0
- ai_profile_cli-0.3.0/src/aiprofile/schema/__init__.py +37 -0
- ai_profile_cli-0.3.0/src/aiprofile/schema/event.py +528 -0
- ai_profile_cli-0.3.0/src/aiprofile/schema/vocab.py +208 -0
- ai_profile_cli-0.3.0/src/aiprofile/storage/__init__.py +1 -0
- ai_profile_cli-0.3.0/src/aiprofile/storage/db.py +136 -0
- ai_profile_cli-0.3.0/src/aiprofile/storage/migrations.py +76 -0
- ai_profile_cli-0.3.0/src/aiprofile/storage/store.py +186 -0
- ai_profile_cli-0.3.0/src/aiprofile/viz.py +535 -0
- ai_profile_cli-0.3.0/tests/integration/helpers.py +100 -0
- ai_profile_cli-0.3.0/tests/integration/test_cherry_pick.py +160 -0
- ai_profile_cli-0.3.0/tests/integration/test_console_privacy.py +241 -0
- ai_profile_cli-0.3.0/tests/integration/test_end_to_end.py +699 -0
- ai_profile_cli-0.3.0/tests/snapshots/badge_dark.svg +12 -0
- ai_profile_cli-0.3.0/tests/snapshots/badge_light.svg +12 -0
- ai_profile_cli-0.3.0/tests/snapshots/badge_zero_dark.svg +12 -0
- ai_profile_cli-0.3.0/tests/snapshots/badge_zero_light.svg +12 -0
- ai_profile_cli-0.3.0/tests/snapshots/heatmap_dark.svg +414 -0
- ai_profile_cli-0.3.0/tests/snapshots/heatmap_empty_dark.svg +13 -0
- ai_profile_cli-0.3.0/tests/snapshots/heatmap_empty_light.svg +13 -0
- ai_profile_cli-0.3.0/tests/snapshots/heatmap_light.svg +414 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_populated_dark.svg +194 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_populated_light.svg +194 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_privacy_false_dark.svg +56 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_privacy_false_light.svg +56 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_privacy_true_dark.svg +56 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_privacy_true_light.svg +56 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_zero_dark.svg +15 -0
- ai_profile_cli-0.3.0/tests/snapshots/summary_zero_light.svg +15 -0
- ai_profile_cli-0.3.0/tests/unit/test_aggregate.py +747 -0
- ai_profile_cli-0.3.0/tests/unit/test_brand.py +281 -0
- ai_profile_cli-0.3.0/tests/unit/test_calendar_band.py +622 -0
- ai_profile_cli-0.3.0/tests/unit/test_config.py +177 -0
- ai_profile_cli-0.3.0/tests/unit/test_dependency_isolation.py +112 -0
- ai_profile_cli-0.3.0/tests/unit/test_export_atomic.py +348 -0
- ai_profile_cli-0.3.0/tests/unit/test_gitio_paths.py +51 -0
- ai_profile_cli-0.3.0/tests/unit/test_gitio_uid.py +460 -0
- ai_profile_cli-0.3.0/tests/unit/test_hardening.py +245 -0
- ai_profile_cli-0.3.0/tests/unit/test_heatmap_svg.py +394 -0
- ai_profile_cli-0.3.0/tests/unit/test_privacy_boundary.py +298 -0
- ai_profile_cli-0.3.0/tests/unit/test_properties.py +477 -0
- ai_profile_cli-0.3.0/tests/unit/test_render_summary.py +854 -0
- ai_profile_cli-0.3.0/tests/unit/test_scanner_orchestration.py +207 -0
- ai_profile_cli-0.3.0/tests/unit/test_schema_event.py +899 -0
- ai_profile_cli-0.3.0/tests/unit/test_storage.py +565 -0
- ai_profile_cli-0.3.0/tests/unit/test_trailers.py +479 -0
- ai_profile_cli-0.3.0/tests/unit/test_viz_contract.py +550 -0
- ai_profile_cli-0.3.0/tests/unit/test_vocab_registry.py +246 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Continuous verification on every push/PR: the full suite + lint.
|
|
2
|
+
# This is the workflow behind the README's tests badge - the badge is
|
|
3
|
+
# only as honest as this file stays.
|
|
4
|
+
name: tests
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: ["main"]
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
tests:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
timeout-minutes: 15
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
with:
|
|
21
|
+
persist-credentials: false
|
|
22
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
- name: Full suite + lint
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install -e ".[dev]"
|
|
28
|
+
python -m pytest tests -p no:cacheprovider
|
|
29
|
+
python -m ruff check src tests scripts
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Tag-triggered PyPI publish via Trusted Publishing (OIDC - no stored
|
|
2
|
+
# secrets anywhere). Prerequisite (one-time, PyPI web UI): a publisher
|
|
3
|
+
# for project `ai-profile-cli`, owner WenyuChiou, repository ai-profile,
|
|
4
|
+
# workflow publish.yml. The suite + ruff gate the upload: a red test
|
|
5
|
+
# means no release, ever.
|
|
6
|
+
name: publish
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
publish:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 15
|
|
19
|
+
environment: pypi
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
id-token: write # OIDC token for PyPI Trusted Publishing
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.12"
|
|
30
|
+
- name: Gate - full suite + lint
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install -e ".[dev]"
|
|
33
|
+
python -m pytest tests -p no:cacheprovider
|
|
34
|
+
python -m ruff check src tests scripts
|
|
35
|
+
- name: Build sdist + wheel
|
|
36
|
+
run: |
|
|
37
|
+
python -m pip install build==1.4.3
|
|
38
|
+
python -m build
|
|
39
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.venv/
|
|
9
|
+
.playwright-mcp/
|
|
10
|
+
|
|
11
|
+
# Agent-collaboration working files (briefs, transcripts, replies) and
|
|
12
|
+
# local artifact exports — never repo content. Shared here (not in
|
|
13
|
+
# .git/info/exclude) so fresh clones are protected too: these files can
|
|
14
|
+
# carry local absolute paths.
|
|
15
|
+
/.ai/
|
|
16
|
+
/.artifact/
|
|
17
|
+
.claude/settings.local.json
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# This .gitignore file was automatically created by Hypothesis. Hypothesis gitignores
|
|
2
|
+
# .hypothesis by default, because we generally recommend that .hypothesis not be checked
|
|
3
|
+
# into version control.
|
|
4
|
+
#
|
|
5
|
+
# If you *would* like to check .hypothesis into version control, you should delete this
|
|
6
|
+
# file. Hypothesis will not re-create this .gitignore unless .hypothesis is deleted (and
|
|
7
|
+
# if it does, that's a bug - please report it!)
|
|
8
|
+
|
|
9
|
+
*
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/viz.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[365, 'All time', 'active_ai_days', 'active_days', 'actor_presences', 'ai_actor_presences', 'ai_commits', 'attributed_commits', 'commits_scanned', 'counts', 'daily', 'daily container', 'daily date', 'date', 'declared', 'display name', 'display_name', 'each day cell', 'each day count', 'each provider row', 'evidence', 'evidence_records', 'from', 'generated_on', 'imported', 'inferred', 'label', 'period', 'period.label', 'privacy', 'provider', 'provider slug', 'provider_count', 'providers', 'providers container', 'schema_version', 'to', 'total_commits', 'total_records', 'totals', 'unknown', 'unknown_commits', 'verified']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/render/themes.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['#033d8b', '#0550ae', '#0969da', '#0d1117', '#161b22', '#1f2328', '#1f6feb', '#21262d', '#218bff', '#388bfd', '#3d444d', '#4493f8', '#58a6ff', '#59636e', '#6e7681', '#6e7781', '#9198a1', '#a5d6ff', '#d1d9e0', '#eff2f5', '#f0f6fc', '#f6f8fa', '#ffffff', 'github-dark', 'github-light']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/render/summary_svg.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[0.2, 0.3, 0.35, 0.5, 0.52, 0.55, 0.56, 0.66, 0.72, 0.75, 0.82, 1.0, 100, 104, 112, 120, 122, 140, 144, 160, 164, 172, 184, 208, 224, 360, 400, 500, 512, 600, 700, 830, '0%', '0.583333', '100%', '</svg>', '<1%', '>99%', '?', 'AI actor presences', 'AI providers', 'Apr', 'Aug', 'Dec', 'Feb', 'Jan', 'Jul', 'Jun', 'Mar', 'May', 'Nov', 'Oct', 'Sep', 'Unknown commits', 'declared', 'end', 'github-dark', "iIl.,:;'`|!ftj ()[]·", 'imported', 'inferred', 'mMW@%&', 'middle', 'start', 'unknown', 'unrecognized', 'verified', '…']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/cli.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['%Y-%m-%d', '--full', '--out', '--verbose', '--version', '-v', '.git', 'aggregate', 'aiprofile', 'badge-dark.svg', 'badge-light.svg', 'command', 'dist', 'github-dark', 'github-light', 'heatmap-dark.svg', 'heatmap-light.svg', 'imported', 'inferred', 'init', 'path', 'render', 'scan', 'seconds', 'store_true', 'summary-dark.svg', 'summary-light.svg', 'verified', 'version']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/registry.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['aider', 'aider@aider.chat', 'alibaba', 'amazon', 'amazon q', 'amazon-q', 'amazon-q@amazon.com', 'amp', 'amp@ampcode.com', 'anthropic', 'cascade', 'cascade@windsurf.ai', 'cascade@windsurf.com', 'claude code', 'claude-code', 'claudecode', 'codex', 'codex cli', 'codex-cli', 'cognition', 'copilot', 'copilot@github.com', 'cursor', 'deepseek', 'devin', 'gemini', 'gemini cli', 'gemini-cli', 'gemini-code-assist', 'github', 'github copilot', 'github-copilot', 'google', 'jules', 'kimi code', 'kimi-code', 'meta', 'meta ai', 'mistral', 'mistral ai', 'moonshot', 'moonshot ai', 'noreply@google.com', 'noreply@openai.com', 'ollama', 'openai', 'openhands', 'qwen code', 'qwen-code', 'replit', 'replit agent', 'replit-agent', 'roo code', 'roo-code', 'roocode', 'roomote@roocode.com', 'vibe code', 'vibe-code', 'windsurf', 'x.ai', 'xai', 'z.ai', 'zhipu']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/config.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[384, 448, ', ', '.aiprofile', '.json.tmp', 'AIPROFILE_HOME', 'aiprofile.db', 'config.json', 'identities', 'path', 'publication_level', 'repositories', 'repository_uid', 'salt', 'utf-8', 'win32']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/schema/vocab.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['Aider', 'Amazon Q', 'Amp', 'Claude', 'Copilot', 'Cursor', 'DeepSeek', 'Devin', 'GLM', 'Gemini', 'Grok', 'Kimi', 'Llama', 'Mistral', 'Ollama', 'OpenAI', 'OpenHands', 'Qwen', 'Replit', 'Roo Code', 'Unrecognized', 'Windsurf', 'aggregate_only', 'ai', 'ai-mode', 'ai-provider', 'ai-tool', 'ai_assisted', 'ai_generated', 'ai_reviewed', 'aider', 'alibaba', 'amazon', 'amazon-q', 'amp', 'anthropic', 'claude-code', 'co-authored-by', 'codex-cli', 'cognition', 'commit', 'copilot', 'cursor', 'declared', 'deepseek', 'devin', 'documentation', 'excluded', 'full', 'gemini-cli', 'gemini-code-assist', 'git_trailer', 'git_trailer_coauthor', 'github', 'google', 'human', 'human_only', 'human_reviewed_ai', 'implementation', 'imported', 'inferred', 'jules', 'kimi-code', 'manual_declaration', 'meta', 'mistral', 'mixed', 'moonshot', 'none', 'ollama', 'openai', 'openhands', 'other', 'qwen-code', 'replit', 'replit-agent', 'repository_anonymous', 'review', 'roo-code', 'testing', 'unknown', 'unrecognized', 'verified', 'vibe-code', 'windsurf', 'xai', 'zhipu']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/adapters/trailers.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[',', '-', ':', '_', 'ai-mode', 'ai-model', 'ai-provider', 'ai-reviewed-by', 'ai-role', 'ai-schema', 'ai-tool', 'co-authored-by', 'contradictory-group', 'email', 'human', 'incomplete-group', 'malformed-mode', 'name', 'none', 'present', 'unknown-role', 'values']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/schema/__init__.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['AceEvent', 'ActivityType', 'ActorType', 'ContributionMode', 'EvidenceLevel', 'ProvenanceSource', 'PublicationLevel', 'Role', 'SourceType', 'build_event', 'canonical_json', 'compute_event_id', 'merge_event_group', 'to_dict']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/schema/event.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[',', ', ', ':', '^[0-9a-f]{40}$', 'ace-identity-v1', 'ace_', 'activity', 'activity.roles', 'activity.timestamp', 'activity.type', 'actor', 'actor.type', 'commit_sha', 'contribution_mode', 'event_id', 'evidence_level', 'human_reviewed', 'model', 'model_raw', 'provenance', 'provider', 'provider_raw', 'recorded_at', 'repository_uid', 'roles', 'schema_version', 'source', 'source_reference', 'source_type', 'sources', 'timestamp', 'tool', 'tool_raw', 'type', 'utf-8']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/render/heatmap_svg.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[0.45, 0.65, 0.85, 1.0, 112, 120, 124, 364, 600, '#', '0%', '1', '100%', '2-4', '5-7', '8+', '</svg>', 'AI share:', 'Apr', 'Aug', 'Dec', 'Feb', 'Fri', 'Jan', 'Jul', 'Jun', 'Mar', 'May', 'Mon', 'Nov', 'Oct', 'Sep', 'Volume:', 'Wed', 'end', 'middle', '≤25%', '≤50%', '≤75%']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/render/brand.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['#000000', '#0B100F', '#152347', '#17171A', '#1B1F24', '#1D1547', '#1E3833', '#2B1547', '#2B203C', '#2D2D2D', '#2E2E2E', '#2E3138', '#33302E', '#3C231B', '#4377FE', '#472315', '#472815', '#5786FE', '#6950EF', '#7A7A7A', '#8E75B2', '#97D8CB', '#9844FF', '#B74C2A', '#DE5A06', '#DFE6F6', '#E2A28D', '#E3DFF6', '#E3E5E8', '#E3F2EF', '#E7E6E4', '#E9DFF6', '#EBEBEB', '#ECE6F4', '#EEEDEC', '#EEEFF1', '#F04805', '#F26207', '#F6E5DF', '#F6E6DF', '#F6E8DF', '#FA520F', 'aider', 'alibaba', 'amazon', 'amp', 'anthropic', 'cognition', 'cursor', 'deepseek', 'github', 'google', 'meta', 'mistral', 'moonshot', 'ollama', 'openai', 'openhands', 'replit', 'roo-code', 'windsurf', 'xai', 'zhipu']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/aggregate.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
['.', '0.1', '0.2', 'activity_timestamp', 'actor_type', 'ai', 'ai_commits', 'attributed_commits', 'commit_id', 'date', 'evidence_level', 'human', 'id', 'mixed', 'n', 'provider', 'provider_raw', 'repository_uid', 'schema_version', 'tool_raw', 'total_commits', 'unknown']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/ai-profile/ai-profile/src/aiprofile/gitio.py
|
|
2
|
+
# hypothesis_version: 6.161.1
|
|
3
|
+
|
|
4
|
+
[300, 65535, '#', '--get', '--show-object-format', '--show-toplevel', '.git', '/', '0', '22', '443', '80', '9418', ':', '?', '@', 'HEAD', '[A-Za-z]', 'bad default revision', 'config', 'file', 'get-url', 'git', 'git+ssh', 'github.com', 'host', 'http', 'https', 'log', 'origin', 'path', 'remote', 'replace', 'rev-parse', 'sha1', 'ssh', 'user.email', 'utf-8', 'v5']
|
|
Binary file
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# AGENTS.md — agent orientation for ai-profile
|
|
2
|
+
|
|
3
|
+
`aiprofile` is a local-first CLI that scans local Git repos for explicit
|
|
4
|
+
AI provenance (AI-* trailers, known co-author trailers) and renders
|
|
5
|
+
privacy-safe SVG/JSON profile summaries. It is NOT an AI code detector.
|
|
6
|
+
Read `README.md` and `CONTRIBUTING.md` first; where docs and code
|
|
7
|
+
disagree, docs win and the code is the bug.
|
|
8
|
+
|
|
9
|
+
## Quality gates (must stay green after every change)
|
|
10
|
+
|
|
11
|
+
- `python -m pytest tests -p no:cacheprovider` — full suite; state the
|
|
12
|
+
count you observe (as of 2026-07-21: 340 passed, 1 skipped — the skip
|
|
13
|
+
is a POSIX-only fixture on Windows; if your run differs, update this
|
|
14
|
+
line in the same commit).
|
|
15
|
+
- `python -m ruff check src tests` — clean.
|
|
16
|
+
- Privacy invariants are test-enforced; anything weakening `VizStats`
|
|
17
|
+
structural redaction needs its own ADR. Snapshot/sample regeneration
|
|
18
|
+
only via the sanctioned per-family commands (byte-drift guarded):
|
|
19
|
+
`python tests/unit/test_render_summary.py` (summary family) and
|
|
20
|
+
`python tests/unit/test_heatmap_svg.py` (heatmap/badge family, D4).
|
|
21
|
+
- Contract changes need an ADR under `docs/decisions/` + schema bump.
|
|
22
|
+
|
|
23
|
+
## Collaboration contract (Fable ↔ Codex gate loop)
|
|
24
|
+
|
|
25
|
+
This repo is built through numbered independent "gate" review rounds:
|
|
26
|
+
|
|
27
|
+
- **Fable (Claude Code)** implements, resolves review findings
|
|
28
|
+
red-first (regression proven failing pre-fix), records dispositions in
|
|
29
|
+
`docs/reviews/gate-disposition.md` + `docs/progress.md`, and is the
|
|
30
|
+
ONLY party that commits (`Resolve gate-N review: ...`).
|
|
31
|
+
- **Codex** acts as independent Principal-Software-Engineer reviewer:
|
|
32
|
+
verification only, adversarial reproduction with runnable probes,
|
|
33
|
+
never commits, never changes production/test/design code. The review
|
|
34
|
+
overwrites `docs/reviews/gate-review.md` (repo convention; usually
|
|
35
|
+
committed alongside the commit that resolves it — but a round may
|
|
36
|
+
leave it deliberately uncommitted, as gate-9's did; check `git status`
|
|
37
|
+
and the round's own commit message/brief before assuming which).
|
|
38
|
+
|
|
39
|
+
## Handoff protocol (replaces clipboard copy-paste between apps)
|
|
40
|
+
|
|
41
|
+
Round files live in `.ai/handoff/` (git-ignored via `.git/info/exclude`;
|
|
42
|
+
Codex's file tools read them regardless):
|
|
43
|
+
|
|
44
|
+
- `NNN_<slug>.to_codex.md` — a task/review brief authored by Fable.
|
|
45
|
+
- `NNN_<slug>.to_fable.md` — Codex's durable reply (same NNN; this file
|
|
46
|
+
is never overwritten by later rounds, unlike gate-review.md).
|
|
47
|
+
- Exception: `000_gate8_review_snapshot.to_fable.md` is a one-off
|
|
48
|
+
bootstrap snapshot authored by Fable (preserving the never-committed
|
|
49
|
+
gate-8 review text), not a Codex reply.
|
|
50
|
+
- NNN is single-use: a second round over the same range or brief (a
|
|
51
|
+
second opinion, a re-run) ALWAYS gets its own fresh NNN brief — never
|
|
52
|
+
point a new round at an existing NNN, because its reply instruction
|
|
53
|
+
would overwrite that round's supposedly-durable `.to_fable.md`
|
|
54
|
+
(this happened live on 2026-07-21: an app round reusing brief 001
|
|
55
|
+
silently clobbered the headless round's 001 reply; recovered from a
|
|
56
|
+
session transcript, which will not always exist).
|
|
57
|
+
- While an external review of a committed range is in flight, do not
|
|
58
|
+
draft next-round files in the same working tree: the reviewer's
|
|
59
|
+
`git status` picks up the strays (observed live during gate-11 — a
|
|
60
|
+
concurrently-drafted test file appeared mid-review; the reviewer
|
|
61
|
+
disclosed rather than touched it, but the ambiguity is avoidable).
|
|
62
|
+
Range-pinned checks are immune, tree-state checks are not.
|
|
63
|
+
|
|
64
|
+
To run a round from the Codex app, open it with cwd = this repo's root
|
|
65
|
+
and say exactly:
|
|
66
|
+
|
|
67
|
+
> Read .ai/handoff/NNN_<slug>.to_codex.md and execute all instructions;
|
|
68
|
+
> write your reply to .ai/handoff/NNN_<slug>.to_fable.md.
|
|
69
|
+
|
|
70
|
+
The brief itself carries all round-specific instructions (review range,
|
|
71
|
+
expected test counts, output contract) — the sentence never changes.
|
|
72
|
+
|
|
73
|
+
Preferred transport (proven on the gate-10 round, 2026-07-22): Fable
|
|
74
|
+
runs the same brief headlessly — no human in the transport at all —
|
|
75
|
+
via the codex-delegate wrapper (personal-environment tooling from the
|
|
76
|
+
maintainer's global skills install, optional; the Codex-app sentence
|
|
77
|
+
above is the portable path for anyone else):
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
bash ~/.claude/skills/codex-delegate/scripts/run_codex.sh \
|
|
81
|
+
--brief-file .ai/handoff/NNN_<slug>.to_codex.md --repo <repo-root>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Machine-readable status lands at `<brief>.txt.result.json`
|
|
85
|
+
(`success` / `fallback` = Codex quota exhausted / `error`). On
|
|
86
|
+
`fallback`, wait for the quota reset or fall back to the Codex-app
|
|
87
|
+
sentence above — never substitute a same-vendor review for the
|
|
88
|
+
independent external round.
|
|
89
|
+
|
|
90
|
+
## Commit trailers (dogfood — this repo's own product)
|
|
91
|
+
|
|
92
|
+
Every commit here declares its AI participation with the tool's own
|
|
93
|
+
schema (README "Declaring AI participation"), so `aiprofile scan` on
|
|
94
|
+
this repo reports the true multi-tool history. One block per AI actor;
|
|
95
|
+
a repeated `AI-Provider:` key starts the next block (ADR-005). Example
|
|
96
|
+
for the standard round shape (Fable implements, Codex reviews):
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
AI-Provider: Anthropic
|
|
100
|
+
AI-Model: Claude-Fable-5
|
|
101
|
+
AI-Tool: Claude-Code
|
|
102
|
+
AI-Role: implementation, documentation
|
|
103
|
+
AI-Mode: AI-Assisted
|
|
104
|
+
AI-Provider: OpenAI
|
|
105
|
+
AI-Model: GPT-5.5
|
|
106
|
+
AI-Tool: Codex-CLI
|
|
107
|
+
AI-Role: review
|
|
108
|
+
AI-Mode: AI-Assisted
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
ONE CONTIGUOUS BLOCK — never put a blank line between groups: git's
|
|
112
|
+
trailer extraction (`%(trailers:only)`) keeps only the last contiguous
|
|
113
|
+
paragraph, so a blank line silently drops every group above it
|
|
114
|
+
(verified empirically 2026-07-21: the blank-line form lost the entire
|
|
115
|
+
Anthropic group). The repeated `AI-Provider:` key alone is the group
|
|
116
|
+
separator.
|
|
117
|
+
|
|
118
|
+
AND a blank line BEFORE the block — the trailer paragraph must be
|
|
119
|
+
separated from the body prose, or git rejects the whole paragraph as
|
|
120
|
+
non-trailers (too many non-trailer lines in it). Found by dogfooding
|
|
121
|
+
2026-07-23: commits ea5f37d / d2c1147 / 66bc3e9 glued their trailer
|
|
122
|
+
block to the preceding body line and scan as `unknown` forever (pushed
|
|
123
|
+
history is never rewritten here — this note is the erratum). The two
|
|
124
|
+
rules together: blank line before the block, no blank line inside it.
|
|
125
|
+
|
|
126
|
+
Honesty rules: only list actors that actually touched the commit;
|
|
127
|
+
`AI-Reviewed-By: Human` only when a human actually read the diff
|
|
128
|
+
(omit or `None` otherwise); keep the `Co-Authored-By:` line too
|
|
129
|
+
(GitHub UI + the tool's registry fallback both read it).
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
|
+
Versioning: [SemVer](https://semver.org/spec/v2.0.0.html) on the CLI
|
|
5
|
+
package. The ACE event schema carries its own semver (ADR-012) and the
|
|
6
|
+
SQLite store its own migration chain (ADR-004) — see the upgrade policy
|
|
7
|
+
below.
|
|
8
|
+
|
|
9
|
+
## Upgrade policy
|
|
10
|
+
|
|
11
|
+
- **Within a minor line (0.1.x):** drop-in. The database migration
|
|
12
|
+
runner applies any pending migrations automatically on the next
|
|
13
|
+
command; config.json is read-compatible; no action needed.
|
|
14
|
+
- **Across minors (0.1 → 0.2):** read the release notes first. The ACE
|
|
15
|
+
schema refuses aggregation across incompatible `major.minor` payload
|
|
16
|
+
versions by design (ADR-012) — a release that bumps the event schema
|
|
17
|
+
states explicitly whether existing scanned data re-aggregates or a
|
|
18
|
+
rescan is needed. Your raw repositories are always the source of
|
|
19
|
+
truth: worst case, `aiprofile scan` re-derives everything.
|
|
20
|
+
- **Downgrades are unsupported:** the migration chain is forward-only.
|
|
21
|
+
If you must roll back the CLI, delete `~/.aiprofile` (or your
|
|
22
|
+
`AIPROFILE_HOME`) and re-init + rescan — nothing in it is
|
|
23
|
+
irreplaceable (config identities/policy aside, which are a few lines
|
|
24
|
+
of JSON you can note down first).
|
|
25
|
+
|
|
26
|
+
## [Unreleased]
|
|
27
|
+
|
|
28
|
+
(nothing yet)
|
|
29
|
+
|
|
30
|
+
## [0.3.0] — 2026-07-23
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **Collaboration-ratio heatmap** (`heatmap-{light,dark}.svg`,
|
|
35
|
+
ADR-020): GitHub-style year grid where intensity = total commits
|
|
36
|
+
that day — your own human commits included — and hue = the day's
|
|
37
|
+
AI-collaboration share (five quantized bins, neutral → accent). The
|
|
38
|
+
daily series window widens to 365 days (ADR-018 addendum);
|
|
39
|
+
`profile.json` day cells gain `total_commits`/`ai_commits`
|
|
40
|
+
(additive).
|
|
41
|
+
- **AI-collaboration badge** (`badge-{light,dark}.svg`): a small flat
|
|
42
|
+
shield — "AI-assisted | K% · verified by git" — using the summary
|
|
43
|
+
card's own headline share and rounding. `aiprofile render` now
|
|
44
|
+
writes all six SVG assets plus profile.json in one atomic bundle.
|
|
45
|
+
- Provider brand marks for **OpenAI** and **Grok (xAI)** from a second
|
|
46
|
+
icon source (lobe-icons, MIT, pinned commit) via
|
|
47
|
+
`vendor_brand_icons.py --source lobe`; new `THIRD_PARTY_NOTICES.md`
|
|
48
|
+
carries the MIT text (ADR-017 D5 addendum).
|
|
49
|
+
- Two-tier provider model (ADR-019): the DECLARATION tier grows by ten
|
|
50
|
+
providers - Kimi (moonshot), DeepSeek, Qwen (alibaba), Mistral, Grok
|
|
51
|
+
(xai), GLM (zhipu), Ollama, Llama (meta), Replit, Amp - so
|
|
52
|
+
hand-written `AI-Provider:` trailers resolve and rank; the AUTO-MATCH
|
|
53
|
+
tier stays evidence-gated and gains exactly one identity: Amp
|
|
54
|
+
(`amp@ampcode.com`, documented default-on co-author trailer).
|
|
55
|
+
- Eight new provider marks vendored mechanically from the pinned CC0
|
|
56
|
+
simple-icons commit via the new `scripts/vendor_brand_icons.py`
|
|
57
|
+
(byte-verified provenance; Amp keeps the honest letter tile - its
|
|
58
|
+
lobe icon is multi-path - and Grok gained its mark via the second
|
|
59
|
+
source above).
|
|
60
|
+
- Calendar band polish: intensity-bin legend + "publishable repos only"
|
|
61
|
+
cue, clock-free month boundary labels, and clearer provider-overflow
|
|
62
|
+
wording.
|
|
63
|
+
- Repo social-preview card (docs/assets/social-preview.{svg,png}) in
|
|
64
|
+
the banner's visual language.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- Display-name provider declarations resolve (latent since v0.1):
|
|
69
|
+
`AI-Provider: Claude` / `Gemini` / `Copilot` / `Kimi` / `Qwen` /
|
|
70
|
+
`Grok` / `GLM` / `Llama` etc. previously produced canonical-null
|
|
71
|
+
events that published as "Unrecognized". `PROVIDER_ALIASES` now
|
|
72
|
+
derives an entry from every schema-owned display name plus common
|
|
73
|
+
spacing/punctuation variants (Mistral AI, Meta AI, x.ai, Z.ai,
|
|
74
|
+
Moonshot AI), closing the class for future providers too.
|
|
75
|
+
- `aiprofile --version` now reports the real version: 0.2.0 bumped
|
|
76
|
+
`pyproject.toml` but not `__version__`, so the CLI kept saying
|
|
77
|
+
0.1.0. Both sources are now pinned together by a regression test.
|
|
78
|
+
|
|
79
|
+
## [0.2.0] — 2026-07-23
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- Provider brand identity on the summary card (round D1, ADR-017):
|
|
84
|
+
official marks for Claude / Gemini / GitHub Copilot / Cursor /
|
|
85
|
+
Windsurf (CC0 simple-icons subset, byte-verified) with per-theme
|
|
86
|
+
brand-colored bars; honest letter-tile fallback for providers with
|
|
87
|
+
no CC0 mark (OpenAI, Amazon Q, Aider, Roo Code, OpenHands, Devin).
|
|
88
|
+
- README banner (docs/assets/banner-{light,dark}.svg): deterministic
|
|
89
|
+
generated hero in the card's own visual language (isometric brand
|
|
90
|
+
stacks), theme-paired.
|
|
91
|
+
- Tag-triggered PyPI publish workflow (.github/workflows/publish.yml)
|
|
92
|
+
via PyPI Trusted Publishing (OIDC, no stored secrets); gated on the
|
|
93
|
+
full test suite + ruff before build/upload.
|
|
94
|
+
- Isometric daily AI-collaboration calendar (round D2, ADR-018):
|
|
95
|
+
a 12-week 3D activity grid, stacked by provider color, built ONLY
|
|
96
|
+
from explicitly-publishable repositories — aggregate-only
|
|
97
|
+
repositories never surface their activity dates. Fully static SVG
|
|
98
|
+
(no animation - two entrance attempts were invisible in static
|
|
99
|
+
captures and were removed).
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- ACE schema version 0.1.0 -> 0.2.0: `profile.json` and the internal
|
|
104
|
+
visualization contract gain the additive `daily` series (ADR-012's
|
|
105
|
+
minor-bump rule for additive optional fields, binding post-v0.1.0).
|
|
106
|
+
Databases scanned under 0.1 remain fully aggregatable; new scans
|
|
107
|
+
stamp 0.2.0.
|
|
108
|
+
|
|
109
|
+
## [0.1.0] — 2026-07-22
|
|
110
|
+
|
|
111
|
+
First public release.
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- Vertical slice: `aiprofile init` / `scan` / `aggregate` / `render` —
|
|
116
|
+
explicit AI provenance (AI-* trailers + verified co-author registry)
|
|
117
|
+
from local git repositories into a local SQLite store, rendered as
|
|
118
|
+
privacy-safe SVG cards (light/dark) + `profile.json`.
|
|
119
|
+
- Privacy model: local-first (zero network, zero telemetry),
|
|
120
|
+
`aggregate_only` by default, `aggregate` output IS the publish
|
|
121
|
+
preview, structurally sealed `VizStats` publication boundary
|
|
122
|
+
(ten adversarial gate rounds, gates 2–11, each independently
|
|
123
|
+
verified; see `docs/reviews/`).
|
|
124
|
+
- Evidence-quality ladder (`verified > declared > imported > inferred
|
|
125
|
+
> unknown`); honest `unknown` for commits without explicit evidence —
|
|
126
|
+
never inferred from code style.
|
|
127
|
+
- Pre-release hardening: owner-only file permissions (POSIX-enforced,
|
|
128
|
+
retrofitted to existing installations on every load), git-worktree
|
|
129
|
+
placement warning, cp950-safe console text, packaged-install release
|
|
130
|
+
smoke script, cherry-pick counting semantics documented + tested,
|
|
131
|
+
console (stdout/stderr) canary sweeps, hypothesis property fuzzing
|
|
132
|
+
over the schema invariants.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution. This project is small on purpose;
|
|
4
|
+
the bar is correctness and privacy, not feature count.
|
|
5
|
+
|
|
6
|
+
## Setup and verification
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install -e ".[dev]" # Python >= 3.11, git >= 2.17 (SHA-1 repos)
|
|
10
|
+
python -m pytest # full suite must pass (states its count)
|
|
11
|
+
python -m ruff check src tests
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Integration tests build throwaway git repositories under pytest tmp dirs;
|
|
15
|
+
no network is used anywhere in the suite, ever.
|
|
16
|
+
|
|
17
|
+
## Ground rules
|
|
18
|
+
|
|
19
|
+
- `docs/schema.md` is the normative event contract; `docs/architecture.md`
|
|
20
|
+
pins module boundaries (renderers/exporters consume `VizStats` only).
|
|
21
|
+
Where code and docs disagree, the docs win and the code is a bug.
|
|
22
|
+
- **Contract changes require an ADR** under `docs/decisions/` (and a schema
|
|
23
|
+
version bump per ADR-012). New sections in existing docs get review.
|
|
24
|
+
- **Registry additions need primary evidence**: an entry in
|
|
25
|
+
`src/aiprofile/registry.py` must cite an official doc, tool source code,
|
|
26
|
+
or verified real-commit usage (see `docs/landscape.md` §2.1 for the
|
|
27
|
+
verification standard). Unverified strings stay out.
|
|
28
|
+
- **Attribution is explicit-evidence-only.** No code-style inference, no
|
|
29
|
+
LLM classification of historical commits — patches adding either will be
|
|
30
|
+
declined regardless of accuracy.
|
|
31
|
+
- Privacy invariants are test-enforced (leak tests, policy tests); a change
|
|
32
|
+
that weakens `VizStats`' structural redaction needs its own ADR and a
|
|
33
|
+
very good reason. Read `docs/PRIVACY.md` first.
|
|
34
|
+
- Deterministic rendering: snapshot updates must be intentional; regenerate
|
|
35
|
+
via `python tests/unit/test_render_summary.py` and inspect the diff. That
|
|
36
|
+
one command regenerates BOTH the test snapshots and the committed README
|
|
37
|
+
sample assets (`docs/assets/summary-sample-{light,dark}.svg`) from their
|
|
38
|
+
authoritative synthetic fixture — never hand-edit or copy either set; a
|
|
39
|
+
byte-exact drift guard fails the suite if they fall out of sync.
|
|
40
|
+
|
|
41
|
+
## Reporting privacy/security issues
|
|
42
|
+
|
|
43
|
+
Open an issue titled "privacy report" without including the sensitive
|
|
44
|
+
details, and the maintainer will follow up privately.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wenyu Chiou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|