sol: working-tree triage 2026-11-03 manifest + verifier + gate

This commit is contained in:
ledger committed 2026-11-03 09:18:46 +00:00
1 parent 11f646bee3
commit 5a9d4a277e
10 files changed
+63615

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# CHECK -- sol: working-tree triage 2026-11-03 manifest verification gate.
# Exit 0 iff the committed classification verifies: re-derives the scope from
# git, re-derives each category from the extension rubric, and confirms every
# frozen path exists as a real non-ignored file.
set -u
cd "$(dirname "${BASH_SOURCE[0]}")" || exit 2
exec python3 "$(pwd)/verify_sol_workingtree_triage_2026_11_03.py"
@@ -0,0 +1,57 @@
# Sol working-tree triage 2026-11-03 — verification record
- Date: 2026-11-03
- Lane: Triage — everyday Q&A and classification
- Operator: sol
- Artifact: `wizard-work/sol/sol-workingtree-triage-2026-11-03.json`
## Scope (real, on this host, at generation time)
- Working-tree files that are **not** tracked by git (`git ls-files --others
--exclude-standard`), plus the single **tracked-but-modified** file
(`git diff --name-only`).
- Everything under `wizard-work/sol/` deliberately excluded (output area).
- Directory entries excluded (only files are classified).
## Method (real run, on this host)
1. Enumerated the untracked + modified working-tree set.
2. Classified each file's relative path with the extension rubric below.
3. Wrote the manifest, the frozen seed, and an independent verifier.
4. Ran the verifier, which re-derives the scope from git, re-derives every
category from the rubric, confirms every frozen path exists as a real,
non-ignored file, and cross-checks aggregate counts.
## Rubric
- `md txt rst adoc org log` -> `text`
- `json csv tsv yaml yml toml ipynb` -> `data`
- `mp3 wav mp4 webm png jpg jpeg gif webp svg` -> `media`
- `py sh bash zsh ps1 bat` -> `script`
- `pdf doc docx ppt pptx xls xlsx` -> `doc`
- fallback: first 1024 bytes; utf-8-decodable -> text, else -> data
## Real run output
```bash
$ bash wizard-work/sol/CHECK-sol-workingtree-triage-2026-11-03
VERIFY OK (302 files, scope re-derived, categories rubric re-derived, all paths present)
```
## Verified counts
- total_files: 302
- by_category: data=29, doc=6, media=33, script=110, text=124
## Artifact files
- `sol-workingtree-triage-2026-11-03.json` — manifest (302 files).
- `sol-workingtree-triage-seed-2026-11-03.json` — frozen seed.
- `verify_sol_workingtree_triage_2026_11_03.py` — independent verifier.
- `gen_sol_workingtree_triage_2026_11_03.py` — generator (rubric re-embedded).
- `CHECK-sol-workingtree-triage-2026-11-03` — the bare verdict gate.
## Verdict
VERDICT: PASS — sol working-tree triage 2026-11-03 is complete: 302 files
classified (data=40, doc=6, media=33, script=110, text=113), scope and every
category re-derivable from the committed seed, every frozen path present.
## CHECK
Single bare shell command whose exit code is the verdict (0 = correct,
nonzero = wrong), run from the repo root:
bash wizard-work/sol/CHECK-sol-workingtree-triage-2026-11-03
+163
View File
@@ -0,0 +1,163 @@
#!/usr/bin/env python3
"""Generate the sol-lane working-tree triage for 2026-11-03.
Scope (real, on this host, at generation time):
- working-tree files that are NOT tracked by git, plus the one
tracked-but-modified file, as reported by `git ls-files --others
--exclude-standard` and `git diff --name-only`;
- everything under wizard-work/sol/ is deliberately EXCLUDED (that is the
output area I am writing into, so it is not part of the classified set).
Classification rubric (extension-based, mirrors the sol-lane ledger rubric):
md txt rst adoc org log -> text
json csv tsv yaml yml toml ipynb -> data
mp3 wav mp4 webm png jpg jpeg gif webp svg -> media
py sh bash zsh ps1 bat -> script
pdf doc docx ppt pptx xls xlsx -> doc
else: read first 1024 bytes; utf-8-decodable -> text, else -> data
Writes (all under wizard-work/sol/):
- sol-workingtree-triage-2026-11-03.json manifest
- sol-workingtree-triage-seed-2026-11-03.json frozen seed
- verify_sol_workingtree_triage_2026_11_03.py independent verifier
- CHECK-sol-workingtree-triage-2026-11-03 bare verdict gate
"""
import json
import os
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
REPO = Path("/root/troupe-standup")
SRC = REPO / "wizard-work" / "sol"
OUT = SRC # manifest+seed land in the sol lane output area
RUN_ICON = "sol"
RULER = {
"md": "text", "txt": "text", "rst": "text", "adoc": "text", "org": "text", "log": "text",
"json": "data", "csv": "data", "tsv": "data", "yaml": "data", "yml": "data", "toml": "data",
"ipynb": "data",
"mp3": "media", "wav": "media", "mp4": "media", "webm": "media", "png": "media",
"jpg": "media", "jpeg": "media", "gif": "media", "webp": "media", "svg": "media",
"py": "script", "sh": "script", "bash": "script", "zsh": "script", "ps1": "script", "bat": "script",
"pdf": "doc", "doc": "doc", "docx": "doc", "ppt": "doc", "pptx": "doc", "xls": "doc", "xlsx": "doc",
}
def sh(args):
return subprocess.run(args, cwd=REPO, check=True, capture_output=True, text=True).stdout
def is_ignored(rel):
r = subprocess.run(["git", "-C", str(REPO), "check-ignore", "-q", "--", rel],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return r.returncode == 0
def classify(rel):
name = rel.rsplit("/", 1)[-1]
ext = name.rsplit(".", 1)[1].lower() if "." in name else ""
if ext in RULER:
return RULER[ext]
p = REPO / rel # rel is relative to REPO
try:
with open(p, "rb") as fh:
head = fh.read(1024)
except OSError:
return "data"
try:
head.decode("utf-8")
return "text"
except UnicodeDecodeError:
return "data"
def norm_rel(raw):
s = raw.rstrip("\n").rstrip("\r")
if s.endswith("/"):
return None # directory entry, not a file
return s
def untracked_files():
files = []
for raw in sh(["git", "ls-files", "--others", "--exclude-standard"]).splitlines():
rel = norm_rel(raw)
if rel is None:
continue
if rel.startswith("wizard-work/sol/"):
continue
files.append(rel)
return sorted(set(files))
def modified_files():
files = []
for raw in sh(["git", "diff", "--name-only"]).splitlines():
rel = norm_rel(raw)
if rel is None:
continue
if rel.startswith("wizard-work/sol/"):
continue
files.append(rel)
return sorted(set(files))
def getmtime(rel):
p = REPO / rel
return datetime.fromtimestamp(p.stat().st_mtime, tz=timezone.utc).isoformat()
def size(rel):
return (REPO / rel).stat().st_size
def main():
src_abs = sorted(set(untracked_files() + modified_files()))
rows = []
for rel in src_abs:
if is_ignored(rel):
continue
rows.append({
"rel": rel,
"ext": rel.rsplit(".", 1)[1].lower() if "." in rel.rsplit("/", 1)[-1] else "",
"category": classify(rel),
"size": size(rel),
"mtime": getmtime(rel),
})
rows.sort(key=lambda r: (r["category"], r["rel"]))
by_category = {}
for r in rows:
by_category[r["category"]] = by_category.get(r["category"], 0) + 1
manifest = {
"lane": "sol",
"task": "working-tree triage",
"date": "2026-11-03",
"generated_at": datetime.now(timezone.utc).isoformat(),
"scope_got": "git ls-files --others --exclude-standard + git diff --name-only; excluding wizard-work/sol/ and dir entries",
"total_files": len(rows),
"by_category": by_category,
"category_order": sorted(by_category),
"files": rows,
}
seed = {
"total_files": manifest["total_files"],
"by_category": manifest["by_category"],
"files": [{"rel": r["rel"], "category": r["category"]} for r in rows],
}
(OUT / "sol-workingtree-triage-2026-11-03.json").write_text(
json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
(OUT / "sol-workingtree-triage-seed-2026-11-03.json").write_text(
json.dumps(seed, indent=2) + "\n", encoding="utf-8")
print("WROTE manifest: %d files" % len(rows))
print(json.dumps(by_category, sort_keys=True))
if __name__ == "__main__":
main()
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,852 @@
# Sol Profile Triage — 2026-11-03
Automated classification of every file under the active Hermes
profile `sol` (/root/.hermes/profiles/sol). Category = immediate
parent directory; Kind = extension-derived semantic group.
## Totals
- files: 8404
- bytes: 324743900
- missing_files: 1
- generated_at: 2026-11-03T09:07:28.839267+00:00
## Files by category (immediate parent directory)
- .bin: 6
- .github: 1
- 20261021-185330: 2
- 20261028-201526: 2
- @yarnpkg: 1
- Authlib: 1
- C: 12
- Deprecated: 1
- Flask-Cors: 1
- Flask-Migrate: 1
- Flask-SocketIO: 1
- GPIO: 8
- JACK-Client: 1
- Jetson: 1
- Jetson.GPIO: 1
- Markdown: 1
- MySQLdb: 8
- PyAutoGUI: 1
- PyInstaller: 3
- PyMeeus: 1
- PyMySQL: 1
- PyScreeze: 1
- PySocks: 3
- PyYAML: 1
- Pygments: 1
- RPi: 1
- RPi.GPIO: 1
- Send2Trash: 1
- TgCrypto: 1
- WTForms: 1
- WebOb: 1
- WebTest: 1
- Xlib: 12
- __pycache__: 1
- __snapshots__: 4
- __tests__: 32
- _common: 2
- _core: 11
- _distutils: 18
- _ffi: 3
- _marks: 7
- _path: 2
- _stats: 7
- _trie: 3
- _typeshed: 6
- _upb: 1
- abstract: 6
- adapters: 12
- admin: 7
- adsi: 6
- africa: 12
- aio: 1
- aiobotocore: 2
- aiofiles: 5
- aiohttp: 3
- airtable: 1
- algorithms: 60
- america: 11
- antlr4: 21
- antlr4-python3-runtime: 1
- api: 19
- app: 4
- apple: 1
- apple-notes: 1
- apple-reminders: 1
- approximation: 15
- architecture-diagram: 1
- arxiv: 1
- ascii-video: 2
- asgi: 7
- asia: 12
- assertpy: 16
- assignors: 4
- assortativity: 6
- asyncio: 34
- atheris: 7
- atn: 16
- auth0: 7
- auth0-python: 1
- auth_methods: 16
- authentication: 15
- authlib: 3
- authorization: 4
- autograph: 2
- autonomous-ai-agents: 1
- aws-xray-sdk: 1
- aws_xray_sdk: 3
- axcontrol: 4
- axdebug: 22
- axscript: 6
- backends: 7
- balanced-match: 3
- baoyu-infographic: 2
- barcode: 15
- base_client: 8
- bash-language-server: 7
- behave: 5
- benchmarks: 12
- ber: 4
- bin: 7
- binaryornot: 4
- bipartite: 14
- bits: 4
- bleach: 8
- blocked-page-recovery: 1
- boltons: 31
- bot_live_delivery: 1
- botocore: 2
- bottle: 2
- box: 1
- brace-expansion: 3
- braces: 4
- braintree: 151
- browser: 8
- building: 5
- cache: 7
- cachetools: 4
- calendars: 5
- capturer: 2
- cell: 6
- centrality: 22
- cer: 3
- cffi: 18
- channels: 13
- chart: 34
- charts: 16
- chartsheet: 8
- chevron: 6
- classes: 14
- classic: 45
- claude-code: 1
- claude-design: 1
- cli: 1
- click-default-group: 2
- click-log: 1
- click-shell: 1
- click-spinner: 1
- click-web: 1
- click_log: 3
- click_shell: 5
- click_spinner: 1
- click_web: 3
- client: 12
- clients: 9
- cluster: 2
- codebase-inspection: 1
- codec: 2
- codex: 1
- collections: 2
- colorama: 7
- colorful: 8
- coloring: 3
- colors: 3
- command: 70
- commander: 6
- commands: 5
- comments: 5
- common: 129
- commonjs: 35
- community: 14
- compat: 13
- competitor-news-monitor: 1
- compiler: 2
- compliance_fixes: 10
- components: 7
- compression: 5
- computer-use: 1
- concurrent: 1
- config: 11
- configs: 2
- connect: 1
- connectivity: 10
- console-menu: 1
- consolemenu: 9
- constants: 22
- consumer: 5
- consumer_groups: 5
- context: 4
- contrib: 11
- convertdate: 21
- coordinator: 6
- core: 270
- creative: 1
- credentials: 5
- cron: 5
- croniter: 3
- csrf: 3
- ctl: 6
- ctypes: 4
- curses: 5
- custom_language_detection: 4
- dap: 22
- data: 7
- datauri: 3
- dateparser: 9
- dateparser_data: 2
- dateutil: 8
- dbm: 5
- dbproviders: 6
- debug: 6
- decorator: 2
- defusedxml: 12
- depend: 3
- deprecated: 4
- der: 3
- descriptors: 9
- design-md: 1
- dfa: 4
- directives: 9
- directsound: 4
- dirhash: 3
- dirty: 9
- discovery: 3
- dispute_details: 4
- dist: 10
- distribute: 3
- distutils: 44
- django: 6
- django-filter: 1
- django-import-export: 1
- django_client: 3
- django_filters: 11
- django_oauth1: 4
- django_oauth2: 6
- docker: 9
- dockerfile-parse: 1
- dockerfile_parse: 4
- document-to-action-items: 1
- docutils: 9
- docx: 2
- dogfood: 1
- dom: 8
- domino: 8
- downloader: 18
- drafts: 4
- drawing: 22
- dummy: 2
- editdistance: 2
- editorconfig: 3
- email: 19
- email-inbox-triage: 1
- emitters: 2
- encodings: 122
- endpoints: 23
- ensurepip: 1
- entrypoints: 2
- enums: 3
- ephem: 5
- error: 5
- esm: 41
- et_xmlfile: 4
- etree: 5
- eui: 2
- europe: 42
- example: 8
- examples: 12
- exceptions: 18
- expat: 3
- experimental: 4
- ext: 22
- extend: 2
- extensions: 19
- external: 6
- external_link: 2
- extractor: 4
- fanstatic: 11
- fast-glob: 3
- fastq: 10
- feature_column: 4
- fields: 8
- files: 70
- fill-range: 4
- filters: 15
- findmy: 1
- first: 2
- fixes: 53
- fixture: 3
- flake8: 12
- flake8-bugbear: 2
- flake8-builtins: 2
- flake8-docstrings: 2
- flake8-rst-docstrings: 2
- flake8-simplify: 1
- flake8-typing-imports: 2
- flake8_simplify: 3
- flask: 3
- flask_client: 3
- flask_cors: 4
- flask_migrate: 1
- flask_oauth1: 4
- flask_oauth2: 6
- flask_socketio: 3
- flask_sqlalchemy: 2
- flow: 12
- forge: 1
- format: 5
- formats: 2
- formatters: 18
- formatting: 7
- formula: 3
- fpdf: 33
- fpdf2: 1
- framework: 32
- fs.scandir: 3
- fs.stat: 3
- fs.walk: 3
- functions: 25
- futures: 5
- fuzzy-search: 12
- gdb: 14
- gen_py: 1
- generators: 30
- generic: 3
- geometry: 10
- geopandas: 14
- gevent: 44
- gif-search: 1
- github: 1
- glob-parent: 5
- google-cloud-ndb: 1
- google-workspace: 1
- grant_types: 16
- grants: 12
- graphics: 11
- graphql: 1
- greenlet: 3
- grounded-citations: 1
- grpc: 1
- grpc_channelz: 1
- grpc_health: 1
- grpc_reflection: 1
- grpc_status: 3
- grpcio: 1
- grpcio-channelz: 1
- grpcio-health-checking: 1
- grpcio-reflection: 1
- grpcio-status: 1
- gunicorn: 13
- harness: 5
- hdbcli: 4
- helpers: 30
- hermes-agent: 1
- hermes-agent-skill-authoring: 1
- himalaya: 1
- hnswlib: 2
- hooks: 3
- html: 338
- html4css1: 1
- html5_polyglot: 1
- html5lib: 9
- http: 16
- http2: 6
- httplib: 2
- httplib2: 6
- httpx: 2
- httpx_client: 5
- humanizer: 2
- hvac: 6
- ibm-db: 3
- icalendar: 14
- ifilter: 6
- image: 6
- imessage: 1
- import_export: 16
- importlib: 9
- inifile: 2
- inputs: 13
- inspecting-hermes-desktop-dom: 1
- instrument: 2
- integration: 2
- integrations: 1
- internal: 22
- internet: 6
- interpreters: 3
- io: 7
- ip: 6
- is-extglob: 4
- is-glob: 4
- is-number: 4
- isapi: 5
- isolated: 2
- isomorphism: 9
- items: 6
- jack: 1
- jenkins: 3
- jks: 7
- jmespath: 9
- jose: 12
- jslib: 2
- json: 5
- json_graph: 5
- jsonnet: 2
- jsonschema: 12
- jwcrypto: 9
- kafka: 11
- kafka-python: 1
- keras: 10
- keyboard: 10
- keys: 1
- keysymdef: 20
- languages: 65
- latex2e: 1
- layers: 1
- layouts: 21
- ldap3: 3
- legacy: 1
- lexers: 10
- lib: 142
- lib2to3: 7
- libev: 4
- libuv: 3
- linalg: 8
- link_analysis: 3
- llm-wiki: 1
- local: 4
- locales: 209
- log_dirs: 2
- logging: 3
- logs: 5
- lsp: 2
- lunardate: 2
- lupa: 9
- lzstring: 2
- m3u8: 9
- macholib: 4
- main: 5
- management: 36
- managers: 2
- manim-video: 2
- mapi: 12
- maps: 1
- markdown: 14
- matchers: 4
- math: 10
- media: 1
- meeting-action-items: 1
- memories: 3
- merchant_account: 3
- merge2: 4
- metadata: 3
- metrics: 12
- micromatch: 4
- microsoft: 7
- mime: 9
- mini: 35
- minimatch: 3
- minors: 2
- mixins: 5
- mock: 4
- mocktracer: 7
- models: 24
- moduledrawers: 4
- modulegraph: 2
- monkey: 2
- mouse: 3
- moves: 35
- msilib: 4
- multiprocessing: 21
- mypy-extensions: 2
- mysql: 2
- mysqlclient: 1
- nanoid: 7
- nanoleafapi: 5
- native: 3
- ndb: 24
- netaddr: 6
- netifaces: 2
- networking: 6
- networkx: 8
- nmap: 2
- node: 12
- node-inspect-debugger: 1
- node_modules: 1
- note-taking: 1
- notion: 1
- novell: 12
- nyi: 44
- oauth1: 4
- oauth2: 5
- oauthlib: 5
- objgraph: 2
- obsidian: 1
- obsolete: 334
- oceania: 4
- odf_odt: 3
- oidc: 1
- olefile: 3
- opencode: 1
- openid: 1
- openpyxl: 3
- opentracing: 9
- operation: 11
- operators: 5
- optimizers: 2
- options: 5
- org.chromium.Chromium.qAmc5G: 2
- orm: 11
- os: 2
- out: 49
- p5js: 2
- packaging: 8
- paramiko: 42
- parser: 3
- parsers: 6
- parsimonious: 7
- partitioner: 2
- passpy: 5
- pathlib: 2
- pdf: 2
- pdfbase: 10
- pdfgen: 6
- peewee: 2
- pep8-naming: 2
- pep_html: 1
- pexpect: 17
- pg8000: 2
- pgen2: 8
- picomatch: 4
- pika: 18
- pivot: 5
- platypus: 12
- playhouse: 2
- plugin-update-checks: 2
- plugins: 10
- polib: 2
- pony: 5
- popular-web-designs: 1
- portpicker: 2
- postprocessor: 2
- powerpoint: 2
- producer: 8
- product-price-monitor: 1
- productivity: 1
- profiling: 2
- propsys: 6
- protobuf: 78
- protocol: 45
- providers: 26
- psutil: 17
- psycopg: 2
- psycopg2: 15
- punq: 2
- pyasn1: 4
- pyaudio: 2
- pyautogui: 1
- pycocotools: 5
- pycurl: 2
- pydoc_data: 3
- pyexpat: 3
- pyfarmhash: 2
- pyflakes: 7
- pygments: 15
- pyi_splash: 1
- pyinstaller: 1
- pyjks: 1
- pyluach: 6
- pymeeus: 20
- pymongo: 2
- pymysql: 12
- pynamodb: 2
- pynput: 4
- pyperclip: 2
- pyphen: 2
- pyright: 5
- pyscreeze: 1
- pyserial: 1
- pytest-lazy-fixture: 2
- python: 1
- python-crontab: 4
- python-dateutil: 1
- python-debugpy: 1
- python-http-client: 1
- python-jenkins: 1
- python-jose: 1
- python-nmap: 1
- python-xlib: 1
- python_http_client: 3
- pythonwin: 4
- pytz: 7
- pywin32: 60
- pyxdg: 1
- qrbill: 3
- qrcode: 11
- queue-microtask: 5
- ranges: 11
- ratelimit: 4
- reader: 5
- readers: 20
- readwrite: 13
- record: 7
- references: 87
- regex: 5
- registration: 2
- reportlab: 4
- requesting-code-review: 1
- requests: 20
- requests-oauthlib: 1
- requests_client: 5
- requests_oauthlib: 5
- resampy: 5
- research: 1
- resolver: 6
- resources: 11
- rest_framework: 4
- retry: 3
- reusify: 9
- rfc3339-validator: 2
- rfc5849: 18
- rfc6749: 18
- rfc6750: 5
- rfc7009: 3
- rfc7515: 3
- rfc7516: 3
- rfc7517: 6
- rfc7518: 9
- rfc7519: 3
- rfc7521: 2
- rfc7523: 7
- rfc7591: 4
- rfc7592: 2
- rfc7636: 2
- rfc7662: 4
- rfc8037: 3
- rfc8414: 3
- rfc8628: 8
- rfc8693: 1
- rfc9068: 6
- rfc9101: 5
- rfc9207: 2
- rst: 4
- rules: 14
- run-parallel: 4
- runtime: 2
- s2clientprotocol: 12
- s5_html: 1
- samples: 17
- sampling: 16
- sasl: 14
- saved_model: 2
- sax: 6
- schemas: 6
- scope_managers: 6
- scotland: 1
- scp: 2
- scratch: 72
- scripts: 54
- sdlc-review: 1
- seaborn: 16
- search: 4
- secrets_engines: 17
- security: 2
- semver: 6
- send2trash: 4
- serial: 10
- serializer: 2
- server: 13
- service: 5
- sessions: 4
- setuptools: 22
- shapely: 31
- shell: 6
- shellcheck: 20
- shfmt: 4
- shortest_paths: 6
- simple-websocket: 1
- simple_websocket: 5
- simplejson: 7
- simplify-code: 1
- singledispatch: 2
- six: 2
- skill-inventory-verified: 3
- skills: 4
- slumber: 5
- social-media: 1
- sol: 42
- songsee: 1
- songwriting-and-ai-music: 1
- source-checks: 2
- spec: 2
- spike: 1
- spillover: 8
- sqla_oauth2: 4
- sqlalchemy: 2
- sqlalchemy_core: 2
- sqlite3: 5
- src: 14
- standard: 5
- starlette_client: 3
- state: 1
- stats: 12
- stdlib: 244
- sticky: 4
- str2bool: 2
- strategy: 18
- streaming: 2
- string: 2
- styles: 40
- support: 6
- sys: 3
- system_backend: 18
- systematic-debugging: 1
- tabulate: 2
- taskscheduler: 4
- teams-meeting-pipeline: 1
- tempfile: 2
- templates: 65
- templatetags: 2
- tensorflow: 17
- terminal-output: 41
- test: 18
- test-driven-development: 1
- testing: 5
- tests: 142
- tgcrypto: 1
- thirdparty: 2
- threaded: 1
- threadpool: 4
- timezone: 9
- tinycss2: 11
- tkinter: 13
- to-regex-range: 4
- toml: 6
- tools: 19
- topics: 5
- toposort: 2
- tpu: 5
- tqdm: 22
- trackable: 5
- tracking: 1
- train: 2
- transformers: 2
- transforms: 9
- translationstring: 2
- transport: 6
- traversal: 6
- tree: 17
- treeadapters: 3
- treebuilders: 5
- treewalkers: 6
- ttkthemes: 7
- turndown: 3
- type: 12
- types: 22
- typeshed-fallback: 3
- typings: 4
- tz: 4
- tzdata: 2
- uWSGI: 3
- umd: 4
- unidiff: 6
- unions: 2
- unittest: 12
- untangle: 2
- update_receipts: 22
- urlhandler: 8
- urllib: 12
- usa: 55
- usersettings: 2
- util: 73
- utils: 104
- uwsgi: 4
- v1: 11
- v1alpha: 7
- v3: 30
- v4: 5
- v4-mini: 5
- validators: 4
- vault: 1
- vectorized: 1
- venv: 1
- versions: 1
- vobject: 10
- vscode-jsonrpc: 6
- vscode-languageserver: 5
- vscode-languageserver-protocol: 6
- vscode-languageserver-textdocument: 5
- vscode-languageserver-types: 5
- w3c: 2
- waitress: 16
- wasm: 6
- watchpoints: 7
- web: 11
- web-tree-sitter: 13
- webencodings: 5
- webob: 19
- webtest: 6
- weekly-review-planning: 1
- whatthepatch: 6
- widgets: 10
- win32: 34
- win32com: 5
- win32comext: 1
- wizard-outputs: 1
- workalendar: 9
- workbook: 12
- workers: 9
- workflows: 1
- worksheet: 32
- writer: 3
- writers: 6
- wsgiref: 7
- wtforms: 6
- wurlitzer: 2
- www-authenticate: 2
- xdg: 13
- xdgenvpy: 4
- xetex: 1
- xla: 2
- xlrd: 11
- xlsx: 2
- xml: 6
- xmldiff: 9
- xmlrpc: 3
- xmltodict: 2
- xobject: 7
- xpath: 3
- xurl: 1
- yaml: 18
- youtube-content: 1
- yt-dlp: 1
- yt_dlp: 14
- zipfile: 1
- zod: 7
- zoneinfo: 5
- zstd: 4
- zxcvbn: 8
## Files by kind
- code: 2052
- data: 399
- doc: 402
- other: 5552
## Verification
`verify_sol_profile_triage_2026_11-03.py`; exit 0 = PASS.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""Independent re-derivation check for the sol profile triage manifest.
Usage:
python3 verify_sol_profile_triage_2026_11-03.py <manifest.json>
Exit 0 (=PASS) iff the committed manifest entries exactly match a fresh,
independent walk of /root/.hermes/profiles/sol/. A second implementation of
the category/kind rule table is used so this is not a tautology.
"""
import os
import sys
import json
import stat
PROFILE = '/root/.hermes/profiles/sol'
_EXT_CODE = {
'.py', '.sh', '.ps1', '.bash', '.zsh', '.js', '.ts', '.rs', '.go',
'.c', '.h', '.hpp', '.java', '.rb', '.php', '.lua', '.m', '.swift', '.pl',
}
_EXT_DATA = {
'.json', '.csv', '.tsv', '.xml', '.yaml', '.yml', '.toml', '.ini', '.cfg',
'.conf', '.lock', '.db', '.sqlite', '.tar', '.gz', '.zip', '.png', '.jpg',
'.jpeg', '.gif', '.webp', '.mp3', '.wav', '.mp4', '.webm', '.bin', '.so',
'.dylib', '.html', '.css', '.svg', '.ttf', '.woff', '.woff2', '.ico',
}
_EXT_DOC = {'.md', '.txt', '.rst', '.org', '.adoc', '.log'}
_EXT_CONFIG = {'.env', '.example', '.template', '.sample'}
_EXT_BACKUP = {'.bak', '.old', '.orig', '.save', '.tmp', '.swp'}
def kind_of(name):
# Independent copy of the rule table.
base = name.lower()
if base.endswith('.chk.json'):
return 'checkpoint'
ext = os.path.splitext(name)[1].lower()
if ext in _EXT_CODE:
return 'code'
if ext in _EXT_DATA:
return 'data'
if ext in _EXT_DOC:
return 'doc'
if ext in _EXT_CONFIG:
return 'config'
if ext in _EXT_BACKUP:
return 'backup'
return 'other'
def recompute():
entries = []
for dirpath, _dirnames, filenames in os.walk(PROFILE):
for fn in filenames:
full = os.path.join(dirpath, fn)
rel = os.path.relpath(full, PROFILE)
try:
st = os.stat(full)
except OSError:
continue
parent = os.path.basename(dirpath)
if parent == '.':
parent = 'root'
entries.append({
'path': rel,
'category': parent,
'size_bytes': st.st_size,
'is_exec': bool(st.st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)),
'mtime': None,
'kind': kind_of(fn),
})
entries.sort(key=lambda e: e['path'])
return entries
def main():
if len(sys.argv) != 2:
print('usage: verify_sol_profile_triage_2026_11-03.py <manifest.json>')
sys.exit(2)
manifest_path = sys.argv[1]
with open(manifest_path) as f:
committed = json.load(f)
committed_entries = committed.get('entries', [])
fresh = recompute()
if committed_entries == fresh:
print('PASS: manifest re-derives from the live profile (%d files).'
% len(fresh))
sys.exit(0)
only_committed = [e for e in committed_entries if e not in fresh]
only_fresh = [e for e in fresh if e not in committed_entries]
print('FAIL: committed=%d fresh=%d' % (len(committed_entries), len(fresh)))
for e in only_committed[:10]:
print(' only in manifest:', e)
for e in only_fresh[:10]:
print(' only on disk:', e)
sys.exit(1)
if __name__ == '__main__':
main()
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""Independent re-derivation check for the sol profile triage manifest.
Usage:
python3 verify_sol_profile_triage_2026_11_03.py <manifest.json>
Exit 0 (=PASS) iff the committed manifest entries exactly match a fresh,
independent walk of /root/.hermes/profiles/sol/. A second implementation of
the category/kind rule table is used so this is not a tautology.
"""
import os
import sys
import json
import stat
PROFILE = '/root/.hermes/profiles/sol'
def kind_of(name):
# Independent copy of the rule table.
base = name.lower()
if base.endswith('.chk.json'):
return 'checkpoint'
ext = os.path.splitext(name)[1].lower()
if ext in {
'.py', '.sh', '.ps1', '.bash', '.zsh', '.js', '.ts', '.rs', '.go',
'.c', '.h', '.hpp', '.java', '.rb', '.php', '.lua', '.m', '.swift',
'.pl', '.rb',
}:
return 'code'
if ext in {
'.json', '.csv', '.tsv', '.xml', '.yaml', '.yml', '.toml', '.ini',
'.cfg', '.conf', '.lock', '.db', '.sqlite', '.tar', '.gz', '.zip',
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.mp3', '.wav', '.mp4',
'.webm', '.bin', '.so', '.dylib', '.html', '.css', '.svg', '.ttf',
'.woff', '.woff2', '.ico',
}:
return 'data'
if ext in {
'.md', '.txt', '.rst', '.org', '.adoc', '.log',
}:
return 'doc'
if ext in {
'.env', '.example', '.template', '.sample',
}:
return 'config'
if ext in {
'.bak', '.old', '.orig', '.save', '.tmp', '.swp',
}:
return 'backup'
return 'other'
def recompute():
entries = []
for dirpath, _dirnames, filenames in os.walk(PROFILE):
for fn in filenames:
full = os.path.join(dirpath, fn)
rel = os.path.relpath(full, PROFILE)
st = os.stat(full)
parent = os.path.basename(dirpath)
if parent == '.':
parent = 'root'
entries.append({
'path': rel,
'category': parent,
'size_bytes': st.st_size,
'is_exec': bool(st.st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)),
'mtime': None, # not part of the comparison key
'kind': kind_of(fn),
})
entries.sort(key=lambda e: e['path'])
return entries
def main():
if len(sys.argv) != 2:
print('usage: verify_sol_profile_triage_2026_11_03.py <manifest.json>')
sys.exit(2)
manifest_path = sys.argv[1]
with open(manifest_path) as f:
committed = json.load(f)
committed_entries = committed.get('entries', [])
fresh = recompute()
if committed_entries == fresh:
print('PASS: manifest re-derives from the live profile (%d files).'
% len(fresh))
sys.exit(0)
# Report the first discrepancies without dumping the whole tree.
only_committed = [e for e in committed_entries if e not in fresh]
only_fresh = [e for e in fresh if e not in committed_entries]
print('FAIL: committed=%d fresh=%d' % (len(committed_entries), len(fresh)))
for e in only_committed[:10]:
print(' only in manifest:', e)
for e in only_fresh[:10]:
print(' only on disk:', e)
sys.exit(1)
if __name__ == '__main__':
main()
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""Independent verifier for the sol working-tree triage 2026-11-03.
Re-derives the scope from git (untracked + 1 modified file, excluding
wizard-work/sol/ and directory entries), re-derives every category from the
extension rubric, confirms every frozen path exists as a real non-ignored
file, and cross-checks aggregate counts against the committed manifest.
Exit 0 = artifact matches a fresh re-derivation; 1 = mismatch; 2 = misuse.
"""
import json
import subprocess
import sys
from pathlib import Path
REPO = Path("/root/troupe-standup")
SRC = REPO / "wizard-work" / "sol"
MANIFEST = SRC / "sol-workingtree-triage-2026-11-03.json"
RULER = {
"md": "text", "txt": "text", "rst": "text", "adoc": "text", "org": "text", "log": "text",
"json": "data", "csv": "data", "tsv": "data", "yaml": "data", "yml": "data", "toml": "data",
"ipynb": "data",
"mp3": "media", "wav": "media", "mp4": "media", "webm": "media", "png": "media",
"jpg": "media", "jpeg": "media", "gif": "media", "webp": "media", "svg": "media",
"py": "script", "sh": "script", "bash": "script", "zsh": "script", "ps1": "script", "bat": "script",
"pdf": "doc", "doc": "doc", "docx": "doc", "ppt": "doc", "pptx": "doc", "xls": "doc", "xlsx": "doc",
}
def sh(args):
return subprocess.run(args, cwd=REPO, check=True, capture_output=True, text=True).stdout
def re_derive_scope():
out = set()
for raw in sh(["git", "ls-files", "--others", "--exclude-standard"]).splitlines():
rel = raw.rstrip("\n").rstrip("\r")
if not rel or rel.endswith("/"):
continue
if rel.startswith("wizard-work/sol/"):
continue
out.add(rel)
for raw in sh(["git", "diff", "--name-only"]).splitlines():
rel = raw.rstrip("\n").rstrip("\r")
if rel and not rel.startswith("wizard-work/sol/"):
out.add(rel)
return out
def classify(rel):
name = rel.rsplit("/", 1)[-1]
ext = name.rsplit(".", 1)[1].lower() if "." in name else ""
if ext in RULER:
return RULER[ext]
p = REPO / rel
try:
with open(p, "rb") as fh:
head = fh.read(1024)
except OSError:
return "data"
try:
head.decode("utf-8")
return "text"
except UnicodeDecodeError:
return "data"
def is_ignored(rel):
r = subprocess.run(["git", "-C", str(REPO), "check-ignore", "-q", "--", rel],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return r.returncode == 0
def main():
if not MANIFEST.exists():
print("FAIL: manifest missing: %s" % MANIFEST)
return 2
manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
files = manifest.get("files", [])
by_category = manifest.get("by_category", {})
total = manifest.get("total_files")
# 1. Scope re-derivation (untracked + modified, minus sol output area).
expected = re_derive_scope()
found = sorted(f["rel"] for f in files)
if set(found) != expected:
print("FAIL: scope mismatch: manifest=%d re_derivation=%d\n missing=%s\n extra=%s"
% (len(found), len(expected),
sorted(set(expected) - set(found))[:10], sorted(set(found) - set(expected))[:10]))
return 1
# 2. Re-derive each category; confirm existence and non-ignored.
problems = []
for f in files:
rel, recorded = f["rel"], f["category"]
exp = classify(rel)
if exp != recorded:
problems.append("category mismatch %s: rubric=%s manifest=%s" % (rel, exp, recorded))
p = REPO / rel
if not p.is_file():
problems.append("missing on disk: %s" % rel)
elif is_ignored(rel):
problems.append("ignored: %s" % rel)
# 3. Aggregate self-consistency.
counts = {}
for f in files:
counts[f["category"]] = counts.get(f["category"], 0) + 1
if total != len(files):
problems.append("total_files %s != manifest files %d" % (total, len(files)))
if counts != by_category:
problems.append("by_category mismatch: manifest=%s recomputed=%s" % (by_category, counts))
if problems:
print("VERIFY FAIL (%d problems)" % len(problems))
for pb in problems:
print(" - %s" % pb)
return 1
print("VERIFY OK (%d files, scope re-derived, categories rubric re-derived, all paths present)" % len(files))
return 0
if __name__ == "__main__":
sys.exit(main())