workspace-repo-map 0.2.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.
Files changed (34) hide show
  1. workspace_repo_map-0.2.0/.github/workflows/ci.yml +16 -0
  2. workspace_repo_map-0.2.0/.github/workflows/release-artifacts.yml +26 -0
  3. workspace_repo_map-0.2.0/.gitignore +10 -0
  4. workspace_repo_map-0.2.0/.warden-safe-cache/prompts/2450a49b8338078957f882e5.audit.json +5 -0
  5. workspace_repo_map-0.2.0/.warden-safe-cache/prompts/2450a49b8338078957f882e5.raw +1 -0
  6. workspace_repo_map-0.2.0/AUTHORS.md +1 -0
  7. workspace_repo_map-0.2.0/CHANGELOG.md +27 -0
  8. workspace_repo_map-0.2.0/CONTRIBUTING.md +12 -0
  9. workspace_repo_map-0.2.0/LICENSE +21 -0
  10. workspace_repo_map-0.2.0/PKG-INFO +78 -0
  11. workspace_repo_map-0.2.0/README.md +55 -0
  12. workspace_repo_map-0.2.0/RELEASE.md +16 -0
  13. workspace_repo_map-0.2.0/USAGE.md +215 -0
  14. workspace_repo_map-0.2.0/docs/superpowers/plans/2026-06-18-productize-core-phase1.md +1249 -0
  15. workspace_repo_map-0.2.0/docs/superpowers/specs/2026-06-18-productize-core-design.md +416 -0
  16. workspace_repo_map-0.2.0/example.repomap.toml +21 -0
  17. workspace_repo_map-0.2.0/examples/demo.py +81 -0
  18. workspace_repo_map-0.2.0/pyproject.toml +41 -0
  19. workspace_repo_map-0.2.0/src/workspace_repo_map/__init__.py +16 -0
  20. workspace_repo_map-0.2.0/src/workspace_repo_map/__main__.py +4 -0
  21. workspace_repo_map-0.2.0/src/workspace_repo_map/classify.py +29 -0
  22. workspace_repo_map-0.2.0/src/workspace_repo_map/cli.py +49 -0
  23. workspace_repo_map-0.2.0/src/workspace_repo_map/config.py +124 -0
  24. workspace_repo_map-0.2.0/src/workspace_repo_map/gitmeta.py +47 -0
  25. workspace_repo_map-0.2.0/src/workspace_repo_map/model.py +67 -0
  26. workspace_repo_map-0.2.0/src/workspace_repo_map/scan.py +116 -0
  27. workspace_repo_map-0.2.0/tests/test_classify.py +22 -0
  28. workspace_repo_map-0.2.0/tests/test_cli.py +37 -0
  29. workspace_repo_map-0.2.0/tests/test_config.py +81 -0
  30. workspace_repo_map-0.2.0/tests/test_example_config.py +11 -0
  31. workspace_repo_map-0.2.0/tests/test_gitmeta.py +49 -0
  32. workspace_repo_map-0.2.0/tests/test_model.py +40 -0
  33. workspace_repo_map-0.2.0/tests/test_scan.py +71 -0
  34. workspace_repo_map-0.2.0/tests/test_version.py +5 -0
@@ -0,0 +1,16 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v5
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.12"
15
+ - run: python -m pip install -e ".[test]"
16
+ - run: python -m pytest
@@ -0,0 +1,26 @@
1
+ name: Release Artifacts
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ tags:
7
+ - "v*"
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v5
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+ - name: Build package
18
+ run: |
19
+ python -m pip install --upgrade pip
20
+ python -m pip install build twine
21
+ python -m build
22
+ python -m twine check dist/*
23
+ - uses: actions/upload-artifact@v5
24
+ with:
25
+ name: workspace-repo-map-dist
26
+ path: dist/*
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ .pytest_cache/
3
+ .venv/
4
+ env/
5
+ *.pyc
6
+ .idea/
7
+ dist/
8
+ build/
9
+ .ruff_cache/
10
+ .mypy_cache/
@@ -0,0 +1,5 @@
1
+ {
2
+ "session_id": "2a7ea611-2ded-46e4-9204-a5c2a3024929",
3
+ "audit_counts": {},
4
+ "total": 0
5
+ }
@@ -0,0 +1 @@
1
+ Zain Dana Harper
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ - Makes generated repository maps portable by default.
6
+ - Replaces absolute local root paths with a root hash prefix.
7
+ - Omits protected remotes and redacts credential-shaped remote URL material.
8
+
9
+ ## 0.2.0 - 2026-06-18
10
+
11
+ - Config-driven classification via optional `.repomap.toml` (ordered path-glob rules,
12
+ neutral remote-host fallback). Personal taxonomy moves to user config.
13
+ - Unifies the CLI into a single argument parser; removes the duplicate.
14
+ - Adds a stable public API (`__all__`, `__version__`) and a versioned output
15
+ (`schema_version: 1`); drops the duplicated `relative` field and protected-specific
16
+ counts in favor of generic `class_counts`.
17
+ - Parallelizes per-repo git calls; output remains deterministic.
18
+ - Adds a portable (default) / local output mode and an `annotations` passthrough.
19
+ - Raises the Python floor to 3.11 (stdlib `tomllib`); runtime dependencies stay empty.
20
+
21
+ ## 0.1.0 - 2026-06-13
22
+
23
+ - Initial public release candidate.
24
+ - Ships compact JSON repository inventory mapping for multi-repo local
25
+ workspaces.
26
+ - Adds Python package metadata, CI, license, authorship, and contribution
27
+ boundary files.
@@ -0,0 +1,12 @@
1
+ # Contributing
2
+
3
+ ## Success Criteria
4
+
5
+ - Public docs and scripts include explicit references to known limitations.
6
+ - No secrets and no em-dash characters in public markdown.
7
+ - Release artifacts are deterministic and reproducible.
8
+ - Tests cover core behavior.
9
+
10
+ ## How to Contribute
11
+
12
+ Open PRs with targeted changes and include test coverage for behavior changes.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zain Dana Harper
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.
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: workspace-repo-map
3
+ Version: 0.2.0
4
+ Summary: Compact JSON repository inventory maps for multi-repo workspaces.
5
+ Project-URL: Homepage, https://github.com/HarperZ9/workspace-repo-map
6
+ Project-URL: Repository, https://github.com/HarperZ9/workspace-repo-map
7
+ Project-URL: Issues, https://github.com/HarperZ9/workspace-repo-map/issues
8
+ Author: Zain Dana Harper
9
+ License: MIT
10
+ License-File: AUTHORS.md
11
+ License-File: LICENSE
12
+ Keywords: cli,git,inventory,workspace
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Requires-Python: >=3.11
20
+ Provides-Extra: test
21
+ Requires-Dist: pytest>=8; extra == 'test'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Workspace Repo Map
25
+
26
+ > Compact JSON repository inventory maps for multi-repo workspaces.
27
+
28
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
29
+ ![python](https://img.shields.io/badge/python-3.11%2B-blue.svg)
30
+ ![version](https://img.shields.io/badge/version-0.2.0-informational.svg)
31
+ [![CI](https://github.com/HarperZ9/workspace-repo-map/actions/workflows/ci.yml/badge.svg)](https://github.com/HarperZ9/workspace-repo-map/actions/workflows/ci.yml)
32
+ ![deps: none](https://img.shields.io/badge/deps-none-success.svg)
33
+ [![part of: AI-accountability toolkit](https://img.shields.io/badge/part_of-AI--accountability_toolkit-7a5cff.svg)](https://harperz9.github.io)
34
+
35
+ `workspace-repo-map` scans a workspace root for Git repositories and writes a
36
+ compact JSON map of remotes, branches, dirty counts, marker files, and public or
37
+ local-only classification hints.
38
+
39
+ Generated maps are portable by default: repository paths are root-relative, the local
40
+ root is represented by a short hash, and credential-shaped material in remote URLs is
41
+ always redacted. Dropping whole origins by class is opt-in via `.repomap.toml`.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ python -m pip install workspace-repo-map
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ```bash
52
+ workspace-repo-map --root . --output WORKSPACE-REPO-MAP.json
53
+ workspace-repo-map --json
54
+ ```
55
+
56
+ Without `--json`, the map is written to `<root>/WORKSPACE-REPO-MAP.json` (or `--output`)
57
+ and a one-line summary (`wrote <path>` / `repos=N dirty=M`) is printed.
58
+
59
+ Classification is driven by an optional `.repomap.toml` at the workspace root (see
60
+ `example.repomap.toml`). With no config, repos are classified by a neutral remote-host
61
+ heuristic: `local` (no remote), `public` (origin on a public host), or `private`. Here
62
+ `public` means "origin is on a public code-hosting platform" — a heuristic, not a
63
+ guarantee of visibility.
64
+
65
+ For a full install line, the complete flag list, the importable Python API, and worked
66
+ examples with expected output, see [USAGE.md](USAGE.md). A runnable end-to-end demo lives
67
+ in [`examples/demo.py`](examples/demo.py).
68
+
69
+ ## Notes
70
+
71
+ - This CLI is agent assisted. Review output before sharing it in public.
72
+ - Repository names and branch details are exported from local git metadata.
73
+ - Absolute local root paths are not included by default.
74
+
75
+ ---
76
+ **Zain Dana Harper** — small tools with explicit edges.
77
+ [Portfolio](https://harperz9.github.io) · [HarperZ9](https://github.com/HarperZ9)
78
+ <sub>Built with Claude Code; reviewed, tested, and owned by me.</sub>
@@ -0,0 +1,55 @@
1
+ # Workspace Repo Map
2
+
3
+ > Compact JSON repository inventory maps for multi-repo workspaces.
4
+
5
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+ ![python](https://img.shields.io/badge/python-3.11%2B-blue.svg)
7
+ ![version](https://img.shields.io/badge/version-0.2.0-informational.svg)
8
+ [![CI](https://github.com/HarperZ9/workspace-repo-map/actions/workflows/ci.yml/badge.svg)](https://github.com/HarperZ9/workspace-repo-map/actions/workflows/ci.yml)
9
+ ![deps: none](https://img.shields.io/badge/deps-none-success.svg)
10
+ [![part of: AI-accountability toolkit](https://img.shields.io/badge/part_of-AI--accountability_toolkit-7a5cff.svg)](https://harperz9.github.io)
11
+
12
+ `workspace-repo-map` scans a workspace root for Git repositories and writes a
13
+ compact JSON map of remotes, branches, dirty counts, marker files, and public or
14
+ local-only classification hints.
15
+
16
+ Generated maps are portable by default: repository paths are root-relative, the local
17
+ root is represented by a short hash, and credential-shaped material in remote URLs is
18
+ always redacted. Dropping whole origins by class is opt-in via `.repomap.toml`.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ python -m pip install workspace-repo-map
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```bash
29
+ workspace-repo-map --root . --output WORKSPACE-REPO-MAP.json
30
+ workspace-repo-map --json
31
+ ```
32
+
33
+ Without `--json`, the map is written to `<root>/WORKSPACE-REPO-MAP.json` (or `--output`)
34
+ and a one-line summary (`wrote <path>` / `repos=N dirty=M`) is printed.
35
+
36
+ Classification is driven by an optional `.repomap.toml` at the workspace root (see
37
+ `example.repomap.toml`). With no config, repos are classified by a neutral remote-host
38
+ heuristic: `local` (no remote), `public` (origin on a public host), or `private`. Here
39
+ `public` means "origin is on a public code-hosting platform" — a heuristic, not a
40
+ guarantee of visibility.
41
+
42
+ For a full install line, the complete flag list, the importable Python API, and worked
43
+ examples with expected output, see [USAGE.md](USAGE.md). A runnable end-to-end demo lives
44
+ in [`examples/demo.py`](examples/demo.py).
45
+
46
+ ## Notes
47
+
48
+ - This CLI is agent assisted. Review output before sharing it in public.
49
+ - Repository names and branch details are exported from local git metadata.
50
+ - Absolute local root paths are not included by default.
51
+
52
+ ---
53
+ **Zain Dana Harper** — small tools with explicit edges.
54
+ [Portfolio](https://harperz9.github.io) · [HarperZ9](https://github.com/HarperZ9)
55
+ <sub>Built with Claude Code; reviewed, tested, and owned by me.</sub>
@@ -0,0 +1,16 @@
1
+ # Release Checklist
2
+
3
+ ## 0.1.0 Candidate
4
+
5
+ - [ ] Confirm `README.md`, `LICENSE`, `AUTHORS.md`, `CONTRIBUTING.md`, and
6
+ `CHANGELOG.md` are present.
7
+ - [ ] Run `python -m pytest -q`.
8
+ - [ ] Run `python -m build`.
9
+ - [ ] Run `python -m twine check dist/*`.
10
+ - [ ] Run `public-surface-sweeper . --summary`.
11
+ - [ ] Create a signed `v0.1.0` tag when signing is configured, or an
12
+ annotated `v0.1.0` tag when it is not.
13
+ - [ ] Publish to PyPI only after account ownership, 2FA, and trusted publishing
14
+ configuration are confirmed.
15
+
16
+ This repository does not auto-publish to a package registry.
@@ -0,0 +1,215 @@
1
+ # Usage
2
+
3
+ `workspace-repo-map` scans a workspace root for Git repositories and emits a compact
4
+ JSON inventory map. It ships a CLI (`workspace-repo-map`) and a small importable Python
5
+ API. Runtime dependencies: none. Python: 3.11+.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ python -m pip install workspace-repo-map
11
+ ```
12
+
13
+ Or from a checkout (editable):
14
+
15
+ ```bash
16
+ python -m pip install -e .
17
+ ```
18
+
19
+ ## CLI
20
+
21
+ The console script is `workspace-repo-map` (equivalently `python -m workspace_repo_map`).
22
+
23
+ ```text
24
+ workspace-repo-map [--root ROOT] [--output OUTPUT] [--json]
25
+ [--config CONFIG] [--jobs JOBS] [--version]
26
+ ```
27
+
28
+ | Flag | Default | Meaning |
29
+ | ----------- | -------------------------------- | ---------------------------------------------------- |
30
+ | `--root` | current directory | Workspace root to scan. |
31
+ | `--output` | `<root>/WORKSPACE-REPO-MAP.json` | Output path (ignored when `--json` is given). |
32
+ | `--json` | off | Print the JSON map to stdout instead of writing it. |
33
+ | `--config` | `<root>/.repomap.toml` if present | Path to a `.repomap.toml`. Missing explicit path is fatal. |
34
+ | `--jobs` | config / CPU heuristic | Override the parallel git worker count (must be ≥ 1).|
35
+ | `--version` | — | Print `workspace-repo-map 0.2.0` and exit. |
36
+
37
+ Classification with no config falls back to a remote-host heuristic: `local` (no
38
+ remote), `public` (origin host in the known public set), or `private`. Supply a
39
+ `.repomap.toml` (see `example.repomap.toml`) for ordered path-glob rules.
40
+
41
+ ### Example 1 — print a map to stdout
42
+
43
+ ```bash
44
+ workspace-repo-map --root ./my-workspace --json
45
+ ```
46
+
47
+ Expected output (illustrative — paths, hashes, and timestamps vary):
48
+
49
+ ```json
50
+ {
51
+ "schema_version": 1,
52
+ "tool_version": "0.2.0",
53
+ "generated_at": "2026-06-18T10:16:44-07:00",
54
+ "root_sha256_prefix": "617a55395ac0d599",
55
+ "absolute_paths_included": false,
56
+ "repo_count": 2,
57
+ "dirty_count": 0,
58
+ "class_counts": {
59
+ "public": 1,
60
+ "local": 1
61
+ },
62
+ "top_level": [
63
+ { "name": "proj-a", "kind": "directory", "class": "entry", "bytes": null,
64
+ "modified": "2026-06-18T10:16:37-07:00" },
65
+ { "name": "proj-b", "kind": "directory", "class": "entry", "bytes": null,
66
+ "modified": "2026-06-18T10:16:37-07:00" }
67
+ ],
68
+ "repositories": [
69
+ { "path": "proj-a", "class": "public", "branch": "main", "head": "eb4e19b",
70
+ "origin": "https://github.com/example/proj-a.git",
71
+ "dirty_count": 0, "untracked_count": 1, "markers": ["README.md"] },
72
+ { "path": "proj-b", "class": "local", "branch": "main", "head": "e4f1b0c",
73
+ "origin": "", "dirty_count": 0, "untracked_count": 0,
74
+ "markers": ["pyproject.toml"] }
75
+ ]
76
+ }
77
+ ```
78
+
79
+ ### Example 2 — write a map file (default mode)
80
+
81
+ ```bash
82
+ workspace-repo-map --root ./my-workspace
83
+ ```
84
+
85
+ Expected output (illustrative):
86
+
87
+ ```text
88
+ wrote /path/to/my-workspace/WORKSPACE-REPO-MAP.json
89
+ repos=2 dirty=0
90
+ ```
91
+
92
+ The JSON file content matches the structure shown in Example 1.
93
+
94
+ ### Example 3 — custom output path and worker count
95
+
96
+ ```bash
97
+ workspace-repo-map --root ./my-workspace --output ./inventory.json --jobs 8
98
+ ```
99
+
100
+ Expected output (illustrative):
101
+
102
+ ```text
103
+ wrote /path/to/inventory.json
104
+ repos=2 dirty=0
105
+ ```
106
+
107
+ ### Example 4 — use an explicit config
108
+
109
+ ```bash
110
+ workspace-repo-map --root ./my-workspace --config ./example.repomap.toml --json
111
+ ```
112
+
113
+ Rules in the config are matched against each repo's workspace-relative path (first
114
+ match wins) before the remote-host fallback. A `--config` path that does not exist is a
115
+ fatal error (non-zero exit).
116
+
117
+ ## Configuration (`.repomap.toml`)
118
+
119
+ Place a `.repomap.toml` at the workspace root (auto-discovered) or pass `--config PATH`.
120
+ Every section is optional; with no file, the neutral remote-host heuristic applies.
121
+
122
+ ```toml
123
+ # Ordered classification rules — first match wins. `pattern` is matched against each
124
+ # repo's workspace-relative POSIX path (and against top-level entry names).
125
+ [[rule]]
126
+ pattern = "oss/**" # * matches within one path segment (stops at "/")
127
+ class = "public" # ** matches across segments; "oss/**" also matches bare "oss"
128
+
129
+ [[rule]]
130
+ pattern = "work/**"
131
+ class = "internal"
132
+
133
+ [scan]
134
+ jobs = 16 # parallel git workers (default: a CPU heuristic)
135
+ prune = ["vendor"] # ADDED to the built-in safety set (.git, node_modules, .venv, ...)
136
+ markers = ["go.mod"] # REPLACES the default marker-file list when present
137
+
138
+ [privacy]
139
+ omit_origin_classes = ["internal"] # blank the `origin` for repos of these classes
140
+
141
+ [output]
142
+ portable = true # false = absolute paths + a `root` field (private local maps)
143
+ annotations = { team = "infra" } # arbitrary key/values emitted verbatim under "annotations"
144
+ ```
145
+
146
+ When no rule matches a repo, classification falls back to the remote host: no remote →
147
+ `local`, a public-hosting domain (`github.com`, `gitlab.com`, `bitbucket.org`,
148
+ `codeberg.org`, `git.sr.ht`) → `public`, otherwise → `private`. Credential-shaped material
149
+ in remote URLs is redacted in **every** mode; `portable = false` additionally emits
150
+ absolute paths and a `root` field and is meant only for maps that never leave the machine.
151
+
152
+ ## Python API
153
+
154
+ The package exposes a stable surface via `__all__`:
155
+
156
+ ```python
157
+ from workspace_repo_map import (
158
+ build_map, write_map, discover_repos,
159
+ Map, RepoRow, SCHEMA_VERSION,
160
+ Config, Rule, load_config, default_config,
161
+ classify, __version__,
162
+ )
163
+ ```
164
+
165
+ Key entry points:
166
+
167
+ - `build_map(root: Path, config: Config, tool_version: str) -> Map` — scan and return
168
+ the in-memory map.
169
+ - `write_map(root, config, tool_version, output: Path) -> Map` — same, but also writes
170
+ pretty JSON to `output`.
171
+ - `load_config(path: Path | None, root: Path) -> Config` / `default_config() -> Config`.
172
+ - `classify(path: str, is_repo: bool, origin: str, config: Config) -> str`.
173
+ - `Map.to_json()` / `RepoRow.to_json()` — plain-dict serialization.
174
+
175
+ ### Example — build a map in code
176
+
177
+ ```python
178
+ from pathlib import Path
179
+ from workspace_repo_map import build_map, default_config, __version__
180
+
181
+ config = default_config()
182
+ m = build_map(Path("./my-workspace"), config, __version__)
183
+
184
+ print(m.repo_count, m.dirty_count) # e.g. 2 0
185
+ print(m.class_counts) # e.g. {'public': 1, 'local': 1}
186
+ for row in m.repositories:
187
+ print(row.path, row.class_, row.branch, row.head)
188
+ ```
189
+
190
+ Expected output (illustrative):
191
+
192
+ ```text
193
+ 2 0
194
+ {'public': 1, 'local': 1}
195
+ proj-a public main eb4e19b
196
+ proj-b local main e4f1b0c
197
+ ```
198
+
199
+ ### Example — classify a single path
200
+
201
+ ```python
202
+ from workspace_repo_map import classify, default_config
203
+
204
+ cfg = default_config()
205
+ classify("proj-a", True, "https://github.com/example/proj-a.git", cfg) # -> "public"
206
+ classify("proj-b", True, "", cfg) # -> "local"
207
+ ```
208
+
209
+ ## Notes
210
+
211
+ - This CLI is agent assisted. Review output before sharing it in public.
212
+ - Maps are portable by default: repo paths are root-relative, the absolute root is
213
+ replaced by a short hash prefix, and credential-shaped material in remote URLs is
214
+ redacted.
215
+ - The output schema is versioned (`schema_version: 1`).