diff --git a/.github/audits/2026-06-26T024532Z/organization.audit.json b/.github/audits/2026-06-26T024532Z/organization.audit.json new file mode 100644 index 0000000..0e15b87 --- /dev/null +++ b/.github/audits/2026-06-26T024532Z/organization.audit.json @@ -0,0 +1,85 @@ +{ + "metadata": { + "engine": "reflector.audit", + "output_directory": ".github/audits/2026-06-26T024532Z", + "passes": [ + "00_discovery" + ], + "read_only": true, + "timestamp_local": "2026-06-26T02:45:32.706374+00:00", + "timestamp_utc": "2026-06-26T02:45:32.706370+00:00", + "version": "0.1.0" + }, + "organization": { + "default_branch": "main", + "description": "Organization-wide standards, templates, and developer experience", + "name": "egohygiene" + }, + "policy": { + "analysis_goals": [ + "Observe repository documentation and structure quality", + "Capture technology manifests and metadata" + ], + "name": "documentation", + "optimization_priorities": [ + "coverage", + "reusability", + "read_only" + ], + "output": { + "formats": [ + "md", + "json" + ], + "include_repository_audits": true + }, + "recommendation_style": "disabled", + "repository_selection": { + "exclude": [], + "include": [ + "*" + ] + } + }, + "repositories": [ + { + "architectural_observations": [ + "Repository appears to be organized with top-level directories: .github, profile, reflector", + "Discovery pass is read-only and did not modify repository content" + ], + "detected_technologies": [], + "documentation_files": [ + "README.md", + "profile/README.md", + "reflector/README.md" + ], + "documentation_quality": "good", + "exists": true, + "github_metadata": { + "issue_templates": [], + "workflows": [] + }, + "metrics": { + "documentation_count": 3, + "file_count": 10, + "manifest_count": 0 + }, + "name": ".github", + "notable_questions": [ + "Are project manifests intentionally absent for this repository type?" + ], + "notable_strengths": [ + "Documentation entry points are present" + ], + "path": ".", + "primary_concepts": [ + ".github", + "profile", + "reflector" + ], + "project_manifests": [], + "purpose": "Organization profile, standards, and shared defaults", + "safe_name": ".github" + } + ] +} diff --git a/.github/audits/2026-06-26T024532Z/organization.audit.md b/.github/audits/2026-06-26T024532Z/organization.audit.md new file mode 100644 index 0000000..be8b990 --- /dev/null +++ b/.github/audits/2026-06-26T024532Z/organization.audit.md @@ -0,0 +1,9 @@ +# Organization Audit + +- Organization: egohygiene +- Policy: documentation +- UTC Timestamp: 2026-06-26T02:45:32.706370+00:00 +- Local Timestamp: 2026-06-26T02:45:32.706374+00:00 + +## Repositories +- .github: docs=good, tech=none diff --git a/.github/audits/2026-06-26T024532Z/repositories/.github.audit.json b/.github/audits/2026-06-26T024532Z/repositories/.github.audit.json new file mode 100644 index 0000000..d2d7172 --- /dev/null +++ b/.github/audits/2026-06-26T024532Z/repositories/.github.audit.json @@ -0,0 +1,39 @@ +{ + "architectural_observations": [ + "Repository appears to be organized with top-level directories: .github, profile, reflector", + "Discovery pass is read-only and did not modify repository content" + ], + "detected_technologies": [], + "documentation_files": [ + "README.md", + "profile/README.md", + "reflector/README.md" + ], + "documentation_quality": "good", + "exists": true, + "github_metadata": { + "issue_templates": [], + "workflows": [] + }, + "metrics": { + "documentation_count": 3, + "file_count": 10, + "manifest_count": 0 + }, + "name": ".github", + "notable_questions": [ + "Are project manifests intentionally absent for this repository type?" + ], + "notable_strengths": [ + "Documentation entry points are present" + ], + "path": ".", + "primary_concepts": [ + ".github", + "profile", + "reflector" + ], + "project_manifests": [], + "purpose": "Organization profile, standards, and shared defaults", + "safe_name": ".github" +} diff --git a/.github/audits/2026-06-26T024532Z/repositories/.github.audit.md b/.github/audits/2026-06-26T024532Z/repositories/.github.audit.md new file mode 100644 index 0000000..56d4345 --- /dev/null +++ b/.github/audits/2026-06-26T024532Z/repositories/.github.audit.md @@ -0,0 +1,21 @@ +# Repository Audit: .github + +- Purpose: Organization profile, standards, and shared defaults +- Path: . +- Documentation Quality: good +- Detected Technologies: none + +## Primary Concepts +- .github +- profile +- reflector + +## Architectural Observations +- Repository appears to be organized with top-level directories: .github, profile, reflector +- Discovery pass is read-only and did not modify repository content + +## Notable Strengths +- Documentation entry points are present + +## Notable Questions +- Are project manifests intentionally absent for this repository type? diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a60b85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.pyc diff --git a/reflector/README.md b/reflector/README.md new file mode 100644 index 0000000..064838e --- /dev/null +++ b/reflector/README.md @@ -0,0 +1,19 @@ +# Reflector + +Pass-based organization analysis scaffold. + +## Layout + +- `engines/audit/` — audit engine entrypoint +- `passes/00_discovery/` — read-only organization discovery pass +- `policies/` — reusable audit policies +- `specs/organization.spec` — organization source-of-truth specification +- `outputs/` — reserved for future derived outputs + +## Run + +```bash +python reflector/engines/audit/engine.py +``` + +This writes timestamped artifacts to `.github/audits//`. diff --git a/reflector/engines/audit/engine.py b/reflector/engines/audit/engine.py new file mode 100644 index 0000000..b8de954 --- /dev/null +++ b/reflector/engines/audit/engine.py @@ -0,0 +1,118 @@ +from __future__ import annotations + +import argparse +import json +from datetime import datetime, timezone +from importlib.util import module_from_spec, spec_from_file_location +from pathlib import Path +from typing import Any + + + +def _load_json(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + + +def _load_discovery_module(root_dir: Path): + pass_path = root_dir / "reflector" / "passes" / "00_discovery" / "discovery.py" + spec = spec_from_file_location("reflector_discovery_pass", pass_path) + if spec is None or spec.loader is None: + raise RuntimeError("Unable to load discovery pass") + module = module_from_spec(spec) + spec.loader.exec_module(module) + return module + + + +def _write(path: Path, content: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + + + +def _organization_markdown(payload: dict[str, Any]) -> str: + metadata = payload["metadata"] + lines = [ + "# Organization Audit", + "", + f"- Organization: {payload['organization']['name']}", + f"- Policy: {payload['policy']['name']}", + f"- UTC Timestamp: {metadata['timestamp_utc']}", + f"- Local Timestamp: {metadata['timestamp_local']}", + "", + "## Repositories", + ] + + for repo in payload["repositories"]: + lines.append(f"- {repo['name']}: docs={repo.get('documentation_quality', 'unknown')}, tech={', '.join(repo.get('detected_technologies', [])) or 'none'}") + + return "\n".join(lines) + "\n" + + + +def run(spec_path: Path) -> Path: + root_dir = Path.cwd() + spec = _load_json(spec_path) + policy_name = spec["enabled_policies"][0] + policy_path = root_dir / "reflector" / "policies" / f"{policy_name}.policy.json" + policy = _load_json(policy_path) + + now_utc = datetime.now(timezone.utc) + now_local = datetime.now().astimezone() + timestamp_folder = now_utc.strftime("%Y-%m-%dT%H%M%SZ") + + output_root = root_dir / spec["audit"]["output_root"] / timestamp_folder + repositories_dir = output_root / "repositories" + repositories_dir.mkdir(parents=True, exist_ok=True) + + discovery = _load_discovery_module(root_dir) + + repository_audits: list[dict[str, Any]] = [] + for repository in spec.get("repositories", []): + audit = discovery.run(repository, root_dir) + repository_audits.append(audit) + + safe_name = audit.get("safe_name", audit["name"]) or "repository" + _write(repositories_dir / f"{safe_name}.audit.md", discovery.markdown_report(audit)) + _write(repositories_dir / f"{safe_name}.audit.json", discovery.json_report(audit)) + + organization_payload = { + "metadata": { + "engine": spec["audit"]["engine"], + "version": spec["audit"]["version"], + "timestamp_utc": now_utc.isoformat(), + "timestamp_local": now_local.isoformat(), + "output_directory": str(output_root.relative_to(root_dir)), + "passes": spec["audit"].get("passes", []), + "read_only": True, + }, + "organization": spec["organization"], + "policy": policy, + "repositories": repository_audits, + } + + _write(output_root / "organization.audit.json", json.dumps(organization_payload, indent=2, sort_keys=True) + "\n") + _write(output_root / "organization.audit.md", _organization_markdown(organization_payload)) + + return output_root + + + +def main() -> int: + parser = argparse.ArgumentParser(description="Run Reflector organization audit") + parser.add_argument( + "--spec", + default="reflector/specs/organization.spec", + help="Path to organization specification", + ) + args = parser.parse_args() + + output_path = run(Path(args.spec)) + print(f"audit generated: {output_path}") + return 0 + + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/reflector/passes/00_discovery/discovery.py b/reflector/passes/00_discovery/discovery.py new file mode 100644 index 0000000..e7ad258 --- /dev/null +++ b/reflector/passes/00_discovery/discovery.py @@ -0,0 +1,197 @@ +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +_MANIFEST_FILES = { + "package.json": "node", + "pyproject.toml": "python", + "requirements.txt": "python", + "setup.py": "python", + "go.mod": "go", + "Cargo.toml": "rust", + "pom.xml": "java", + "build.gradle": "java", + "Gemfile": "ruby", +} + + + +def _safe_name(name: str) -> str: + return name.replace("/", "_") + + + +def _find_files(repo_path: Path) -> list[Path]: + files: list[Path] = [] + for path in repo_path.rglob("*"): + if ".git" in path.parts: + continue + if path.is_file(): + files.append(path) + return files + + + +def _documentation_files(files: list[Path], repo_path: Path) -> list[str]: + docs: list[str] = [] + for file in files: + rel = file.relative_to(repo_path) + name = rel.name.lower() + if name.startswith("readme") or rel.parts[0].lower() == "docs": + docs.append(str(rel)) + return sorted(docs) + + + +def _project_manifests(files: list[Path], repo_path: Path) -> list[str]: + manifests: list[str] = [] + for file in files: + if file.name in _MANIFEST_FILES: + manifests.append(str(file.relative_to(repo_path))) + return sorted(manifests) + + + +def _detected_technologies(manifests: list[str]) -> list[str]: + technologies = { + _MANIFEST_FILES[Path(manifest).name] + for manifest in manifests + if Path(manifest).name in _MANIFEST_FILES + } + return sorted(technologies) + + + +def _documentation_quality(docs: list[str]) -> str: + if any(Path(doc).name.lower().startswith("readme") for doc in docs) and len(docs) > 1: + return "good" + if docs: + return "basic" + return "limited" + + + +def _github_metadata(repo_path: Path) -> dict[str, Any]: + workflows = sorted( + str(path.relative_to(repo_path)) + for path in repo_path.glob(".github/workflows/*") + if path.is_file() + ) + issue_templates = sorted( + str(path.relative_to(repo_path)) + for path in repo_path.glob(".github/ISSUE_TEMPLATE/*") + if path.is_file() + ) + return { + "workflows": workflows, + "issue_templates": issue_templates, + } + + + +def run(repository: dict[str, Any], root_dir: Path) -> dict[str, Any]: + repo_name = repository["name"] + repo_path = (root_dir / repository["path"]).resolve() + + if not repo_path.exists(): + return { + "name": repo_name, + "path": repository["path"], + "purpose": repository.get("purpose", ""), + "exists": False, + "error": "Repository path does not exist", + } + + files = _find_files(repo_path) + docs = _documentation_files(files, repo_path) + manifests = _project_manifests(files, repo_path) + technologies = _detected_technologies(manifests) + github_metadata = _github_metadata(repo_path) + + top_level_dirs = sorted( + path.name + for path in repo_path.iterdir() + if path.is_dir() and path.name != ".git" + ) + + architecture_observations = [ + "Repository appears to be organized with top-level directories: " + + (", ".join(top_level_dirs) if top_level_dirs else "none"), + "Discovery pass is read-only and did not modify repository content", + ] + + strengths = [] + if docs: + strengths.append("Documentation entry points are present") + if technologies: + strengths.append("Technology manifests were detected") + + questions = [] + if not docs: + questions.append("Should this repository include a README or docs directory?") + if not manifests: + questions.append("Are project manifests intentionally absent for this repository type?") + + return { + "name": repo_name, + "safe_name": _safe_name(repo_name), + "path": repository["path"], + "purpose": repository.get("purpose", ""), + "exists": True, + "detected_technologies": technologies, + "documentation_quality": _documentation_quality(docs), + "documentation_files": docs, + "project_manifests": manifests, + "github_metadata": github_metadata, + "primary_concepts": top_level_dirs, + "architectural_observations": architecture_observations, + "notable_strengths": strengths, + "notable_questions": questions, + "metrics": { + "file_count": len(files), + "documentation_count": len(docs), + "manifest_count": len(manifests), + }, + } + + + +def markdown_report(audit: dict[str, Any]) -> str: + lines = [ + f"# Repository Audit: {audit['name']}", + "", + f"- Purpose: {audit.get('purpose', '') or 'Not specified'}", + f"- Path: {audit.get('path', '')}", + f"- Documentation Quality: {audit.get('documentation_quality', 'unknown')}", + f"- Detected Technologies: {', '.join(audit.get('detected_technologies', [])) or 'none'}", + "", + "## Primary Concepts", + ] + lines.extend(f"- {concept}" for concept in audit.get("primary_concepts", [])) + if not audit.get("primary_concepts"): + lines.append("- none") + + lines.append("") + lines.append("## Architectural Observations") + lines.extend(f"- {item}" for item in audit.get("architectural_observations", [])) + + lines.append("") + lines.append("## Notable Strengths") + lines.extend(f"- {item}" for item in audit.get("notable_strengths", [])) + if not audit.get("notable_strengths"): + lines.append("- none") + + lines.append("") + lines.append("## Notable Questions") + lines.extend(f"- {item}" for item in audit.get("notable_questions", [])) + if not audit.get("notable_questions"): + lines.append("- none") + + return "\n".join(lines) + "\n" + + + +def json_report(audit: dict[str, Any]) -> str: + return json.dumps(audit, indent=2, sort_keys=True) + "\n" diff --git a/reflector/policies/documentation.policy.json b/reflector/policies/documentation.policy.json new file mode 100644 index 0000000..0e40ae1 --- /dev/null +++ b/reflector/policies/documentation.policy.json @@ -0,0 +1,21 @@ +{ + "name": "documentation", + "analysis_goals": [ + "Observe repository documentation and structure quality", + "Capture technology manifests and metadata" + ], + "repository_selection": { + "include": ["*"], + "exclude": [] + }, + "recommendation_style": "disabled", + "optimization_priorities": [ + "coverage", + "reusability", + "read_only" + ], + "output": { + "formats": ["md", "json"], + "include_repository_audits": true + } +} diff --git a/reflector/specs/organization.spec b/reflector/specs/organization.spec new file mode 100644 index 0000000..2095f58 --- /dev/null +++ b/reflector/specs/organization.spec @@ -0,0 +1,29 @@ +{ + "organization": { + "name": "egohygiene", + "description": "Organization-wide standards, templates, and developer experience", + "default_branch": "main" + }, + "repositories": [ + { + "name": ".github", + "path": ".", + "purpose": "Organization profile, standards, and shared defaults" + } + ], + "audit": { + "engine": "reflector.audit", + "version": "0.1.0", + "output_root": ".github/audits", + "passes": [ + "00_discovery" + ] + }, + "enabled_policies": [ + "documentation" + ], + "extensions": { + "future_pass_inputs": {}, + "future_policy_overrides": {} + } +}