Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Run installer smoke tests
run: python tests/test_installer.py
- name: Verify installer dry-run
run: python scripts/install_cortex.py --dry-run
- name: Verify --list-files
run: python scripts/install_cortex.py --list-files
- name: Run CLI tests
run: python tests/test_cli.py
- name: Verify cortex --version
run: python -m cli --version
- name: Verify cortex validate
run: python -m cli validate
2 changes: 1 addition & 1 deletion MANIFEST.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: cortex
display_name: CORTEX
category: project-evolution-operating-system
version: 3.1.0
version: 4.0.0
license: Apache-2.0
entrypoint: START.md
default_mode: advisory
Expand Down
71 changes: 64 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ It installs a persistent operating layer *around* the project so any capable age
CORTEX is:
- a project continuity system for agent-driven development;
- a governance layer for AI-built repositories;
- a CLI that verifies, scores, and protects your project;
- a safety model for branch isolation and change sequencing;
- a persistent memory layer stored in repository files;
- a structured audit and restructuring workflow.
- a structured audit and restructuring workflow;
- git hooks that enforce protocol compliance automatically.

CORTEX is not:
- an app framework;
Expand Down Expand Up @@ -108,10 +110,12 @@ When CORTEX is applied to a target repository, the agent should:
current branch, repo status, recent branches, relevant commits, active risks.
4. Identify the last confirmed stable branch.
5. Create a new isolated branch from that stable branch.
6. Install `.cortex/` using `scripts/install_cortex.py` when possible.
7. Fill the installed files with repository evidence.
8. Produce the first audit and restructuring outputs.
9. Finish by documenting the next safe step in `.cortex/CURRENT_STATUS.md`.
6. Install `.cortex/` using `cortex init` (or `python -m cli init`).
7. Install git hooks using `cortex hooks install`.
8. Fill the installed files with repository evidence.
9. Produce the first audit and restructuring outputs.
10. Run `cortex score` to compute the initial CSEI.
11. Finish by documenting the next safe step in `.cortex/CURRENT_STATUS.md`.

## First use

Expand Down Expand Up @@ -155,6 +159,55 @@ You can upgrade from Lite to Full at any time by running the installer again wit

For an example of filled `.cortex/` files, see [`examples/filled-cortex/`](examples/filled-cortex/).

## CLI

CORTEX includes a command-line tool that turns governance documentation into operational mechanisms.

### Installation

```bash
pip install -e .
# or run directly:
python -m cli <command>
```

### Commands

| Command | Purpose |
|---|---|
| `cortex init <target>` | Install `.cortex/` into a target repository |
| `cortex init <target> --lite` | Install only the 3 essential files |
| `cortex doctor <target>` | Check health of a `.cortex/` installation |
| `cortex status <target>` | Quick overview of project state and CSEI |
| `cortex validate` | Verify consistency of CORTEX package |
| `cortex score <target>` | Compute CSEI score from repository evidence |
| `cortex score <target> --update` | Compute and write CSEI into CURRENT_STATUS.md |
| `cortex hooks install <target>` | Install git hooks that enforce branch policy |
| `cortex hooks remove <target>` | Remove CORTEX git hooks |
| `cortex hooks status <target>` | Check which hooks are active |

### Git hooks

CORTEX provides git hooks that enforce the protocol automatically:
- **pre-commit**: blocks direct commits to main/master (Law 3)
- **pre-push**: blocks direct pushes to main/master
- **post-checkout**: reminds the operator of project state on branch switch

Install with `cortex hooks install` — remove with `cortex hooks remove`.

### CSEI — automated scoring

The CORTEX Structural Evolution Index is computed automatically by inspecting repository evidence:
- **Structure**: .cortex/ presence and file completeness
- **Clarity**: project context and next safe step documented
- **Safety**: branch discipline, clean tree, hooks installed
- **Verification**: tests exist, CI configured
- **Continuity**: handoff and learning artifacts filled
- **Recoverability**: remote configured, stable branch documented
- **Regression Pressure**: unguarded regressions (lower is better)

Run `cortex score` to see the full breakdown.

## Using CORTEX with coding agents

### Codex
Expand Down Expand Up @@ -215,10 +268,14 @@ Apply the attached CORTEX package to this target project autonomously. Read STAR
- `docs/` — overview, first-use, boundaries, templates, and agent usage docs
- `adapters/` — agent-specific operating notes
- `templates/` — standard files installed into `.cortex/`
- `scripts/` — installation tooling
- `cli/` — CORTEX CLI (init, doctor, status, validate, score, hooks)
- `cli/core/` — core modules (manifest, repo, templates, scoring)
- `cli/hooks/` — git hook scripts
- `scripts/` — standalone installation script (legacy)
- `examples/` — first-use prompt and filled `.cortex/` example
- `tests/` — installer smoke tests
- `tests/` — installer and CLI tests (34 tests)
- `.github/workflows/` — CI pipeline
- `pyproject.toml` — Python package definition

## License

Expand Down
10 changes: 6 additions & 4 deletions START.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ Then inspect the target repository.
2. Determine whether `.cortex/` already exists.
3. Locate the latest confirmed stable branch.
4. Create a new isolated branch from that stable branch.
5. Install `.cortex/` using `scripts/install_cortex.py` when possible.
6. Populate or update the initial CORTEX files.
7. Produce the first audit and restructuring outputs.
8. Record the next safe step in `.cortex/CURRENT_STATUS.md`.
5. Install `.cortex/` using `cortex init` (or `python -m cli init`, or `scripts/install_cortex.py`).
6. Install git hooks using `cortex hooks install` for branch protection.
7. Populate or update the initial CORTEX files.
8. Produce the first audit and restructuring outputs.
9. Run `cortex score` to compute the initial CSEI.
10. Record the next safe step in `.cortex/CURRENT_STATUS.md`.

## Branch law

Expand Down
3 changes: 3 additions & 0 deletions cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""CORTEX CLI — operational layer for AI-built projects."""

__version__ = "4.0.0"
6 changes: 6 additions & 0 deletions cli/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Allow running as: python -m cli"""

from .main import main
import sys

sys.exit(main() or 0)
Empty file added cli/commands/__init__.py
Empty file.
142 changes: 142 additions & 0 deletions cli/commands/doctor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
"""cortex doctor — check health of a .cortex/ installation."""

from pathlib import Path

from ..core import manifest, repo, templates


def add_arguments(parser):
parser.add_argument(
"target",
nargs="?",
default=".",
help="Target repository root (default: current directory).",
)


def run(args):
target = Path(args.target).resolve()
issues = []
warnings = []
ok = []

# 1. Target exists
if not target.is_dir():
print(f"ERROR: {target} is not a directory.")
return 1

# 2. Git repo
if repo.is_git_repo(target):
ok.append("Git repository detected")
# Branch check
if repo.is_on_main(target):
warnings.append("Currently on main/master — CORTEX protocol requires isolated branches for work")
else:
branch = repo.current_branch(target)
ok.append(f"On branch: {branch}")
# Clean tree
if repo.is_clean(target):
ok.append("Working tree is clean")
else:
warnings.append("Working tree has uncommitted changes")
# Remote
if repo.has_remote(target):
ok.append("Remote repository configured")
else:
warnings.append("No remote configured — recoverability reduced")
else:
issues.append("Not a git repository — CORTEX requires git")

# 3. .cortex/ exists
if templates.exists(target):
ok.append(".cortex/ directory exists")
else:
issues.append(".cortex/ not found — run 'cortex init' first")
_print_report(ok, warnings, issues)
return 1 if issues else 0

# 4. File completeness
expected = manifest.full_files()
lite = manifest.lite_files()
installed = templates.installed_files(target)
missing = templates.missing_files(target, expected)
missing_lite = templates.missing_files(target, lite)

if not missing:
ok.append(f"All {len(expected)} template files present (full mode)")
elif not missing_lite:
ok.append(f"Lite mode files present ({len(lite)} essential files)")
warnings.append(f"Full mode files missing: {', '.join(missing)}")
else:
issues.append(f"Essential files missing: {', '.join(missing_lite)}")

# 5. File fill status
status = templates.file_status(target, installed)
filled = [f for f, s in status.items() if s == "filled"]
empty = [f for f, s in status.items() if s == "empty"]

if filled:
ok.append(f"{len(filled)} file(s) filled with content")
if empty:
warnings.append(f"{len(empty)} file(s) still empty (template skeleton only): {', '.join(empty)}")

# 6. Critical fields
d = templates.cortex_dir(target)
phase = templates.read_field(d / "CURRENT_STATUS.md", "Name")
if phase:
ok.append(f"Current phase documented: {phase}")
else:
warnings.append("CURRENT_STATUS.md has no current phase defined")

next_step = templates.read_field(d / "CURRENT_STATUS.md", "Action")
if next_step:
ok.append(f"Next safe step documented")
else:
warnings.append("CURRENT_STATUS.md has no next safe step defined")

stable_branch = templates.read_field(d / "CURRENT_STATUS.md", "Name")
# Check under "Last stable branch" section
stable_lines = templates.read_section(d / "CURRENT_STATUS.md", "Last stable branch")
if stable_lines:
ok.append("Last stable branch documented")
else:
warnings.append("No last stable branch documented in CURRENT_STATUS.md")

# 7. Git hooks
hooks_path = repo.hooks_dir(target)
has_precommit = (hooks_path / "pre-commit").exists()
has_prepush = (hooks_path / "pre-push").exists()
if has_precommit and has_prepush:
ok.append("CORTEX git hooks installed")
elif has_precommit or has_prepush:
warnings.append("Only partial git hooks installed — run 'cortex hooks install'")
else:
warnings.append("No CORTEX git hooks — run 'cortex hooks install' for branch protection")

_print_report(ok, warnings, issues)
return 1 if issues else 0


def _print_report(ok: list, warnings: list, issues: list):
print("CORTEX Doctor Report")
print("=" * 40)
if ok:
print(f"\n OK ({len(ok)}):")
for item in ok:
print(f" [+] {item}")
if warnings:
print(f"\n WARNINGS ({len(warnings)}):")
for item in warnings:
print(f" [!] {item}")
if issues:
print(f"\n ISSUES ({len(issues)}):")
for item in issues:
print(f" [X] {item}")
print()
total_checks = len(ok) + len(warnings) + len(issues)
if issues:
print(f" Health: UNHEALTHY — {len(issues)} issue(s) need attention")
elif warnings:
print(f" Health: FAIR — {len(warnings)} warning(s) to address")
else:
print(f" Health: GOOD — {total_checks} checks passed")
Loading
Loading