cursorfleet 0.1.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.
- cursorfleet-0.1.0/.cursor/rules/privacy-and-hooks.mdc +12 -0
- cursorfleet-0.1.0/.cursor/rules/python-conventions.mdc +12 -0
- cursorfleet-0.1.0/.github/workflows/ci.yml +95 -0
- cursorfleet-0.1.0/.github/workflows/pages.yml +56 -0
- cursorfleet-0.1.0/.github/workflows/release.yml +106 -0
- cursorfleet-0.1.0/.gitignore +34 -0
- cursorfleet-0.1.0/AGENTS.md +22 -0
- cursorfleet-0.1.0/CHANGELOG.md +121 -0
- cursorfleet-0.1.0/CONTRIBUTING.md +58 -0
- cursorfleet-0.1.0/LICENSE +21 -0
- cursorfleet-0.1.0/PKG-INFO +161 -0
- cursorfleet-0.1.0/README.md +123 -0
- cursorfleet-0.1.0/SECURITY.md +54 -0
- cursorfleet-0.1.0/docs/.gitkeep +0 -0
- cursorfleet-0.1.0/docs/adr/0000-template.md +93 -0
- cursorfleet-0.1.0/docs/adr/0001-cursor-capabilities.md +554 -0
- cursorfleet-0.1.0/docs/adr/0002-storage-layout-and-runtime-directory.md +333 -0
- cursorfleet-0.1.0/docs/adr/0003-event-model-and-sanitization.md +307 -0
- cursorfleet-0.1.0/docs/adr/0004-no-chain-of-thought-and-hook-policy.md +77 -0
- cursorfleet-0.1.0/docs/adr/0005-naming-and-trademark.md +80 -0
- cursorfleet-0.1.0/docs/adr/0006-agent-declared-events.md +167 -0
- cursorfleet-0.1.0/docs/adr/0007-narrower-v01-hook-policy.md +183 -0
- cursorfleet-0.1.0/docs/adr/0008-enforcement-boundaries.md +97 -0
- cursorfleet-0.1.0/docs/adr/0009-install-uninstall-ownership.md +277 -0
- cursorfleet-0.1.0/docs/adr/0010-reducer-state-semantics.md +139 -0
- cursorfleet-0.1.0/docs/adr/0011-evidence-trust-model.md +104 -0
- cursorfleet-0.1.0/docs/adr/0012-roster-and-worktree-ownership.md +108 -0
- cursorfleet-0.1.0/docs/adr/0013-run-metadata-and-association.md +34 -0
- cursorfleet-0.1.0/docs/adr/README.md +99 -0
- cursorfleet-0.1.0/docs/architecture.md +118 -0
- cursorfleet-0.1.0/docs/demo.md +87 -0
- cursorfleet-0.1.0/docs/docs-site-plan.md +252 -0
- cursorfleet-0.1.0/docs/empirical-test-plan.md +1559 -0
- cursorfleet-0.1.0/docs/evidence/a2-contract-decision-matrix.md +92 -0
- cursorfleet-0.1.0/docs/evidence/a2-hook-matrix.md +17 -0
- cursorfleet-0.1.0/docs/evidence/adr-0005-naming-gate.md +16 -0
- cursorfleet-0.1.0/docs/evidence/b0-live-validation-2026-10-12.md +31 -0
- cursorfleet-0.1.0/docs/evidence/b0-run-association-spike.md +52 -0
- cursorfleet-0.1.0/docs/evidence/b1-prototype-signoff.md +19 -0
- cursorfleet-0.1.0/docs/evidence/dogfood-week.md +10 -0
- cursorfleet-0.1.0/docs/evidence/external-alpha-results.md +15 -0
- cursorfleet-0.1.0/docs/evidence/latency-13b-linux-ide.md +27 -0
- cursorfleet-0.1.0/docs/evidence/live-validation-index.md +58 -0
- cursorfleet-0.1.0/docs/evidence/product-hunt-gate.md +12 -0
- cursorfleet-0.1.0/docs/evidence/pypi-trusted-publishing-setup.md +30 -0
- cursorfleet-0.1.0/docs/evidence/so01-permission-hooks.md +21 -0
- cursorfleet-0.1.0/docs/evidence/v0.1.1-backlog.md +7 -0
- cursorfleet-0.1.0/docs/evidence/v01-adr-truth-table.md +21 -0
- cursorfleet-0.1.0/docs/evidence/v01-doc-allowlist.json +25 -0
- cursorfleet-0.1.0/docs/evidence/v01-release-baseline.md +14 -0
- cursorfleet-0.1.0/docs/evidence/v01-release-ready.md +28 -0
- cursorfleet-0.1.0/docs/external-alpha.md +17 -0
- cursorfleet-0.1.0/docs/follow-ups.md +293 -0
- cursorfleet-0.1.0/docs/governance.md +101 -0
- cursorfleet-0.1.0/docs/hook-latency.md +77 -0
- cursorfleet-0.1.0/docs/kit.md +154 -0
- cursorfleet-0.1.0/docs/platform-support.md +82 -0
- cursorfleet-0.1.0/docs/privacy.md +102 -0
- cursorfleet-0.1.0/docs/product-contract.md +152 -0
- cursorfleet-0.1.0/docs/quickstart.md +157 -0
- cursorfleet-0.1.0/docs/release-checklist.md +127 -0
- cursorfleet-0.1.0/docs/security-review-v0.1.md +202 -0
- cursorfleet-0.1.0/docs/spike-prep.md +126 -0
- cursorfleet-0.1.0/docs/status-json.md +118 -0
- cursorfleet-0.1.0/docs/status.md +42 -0
- cursorfleet-0.1.0/docs/threat-model.md +135 -0
- cursorfleet-0.1.0/docs/tui.md +179 -0
- cursorfleet-0.1.0/public-docs/.meta.yml +5 -0
- cursorfleet-0.1.0/public-docs/assets/apple-touch-icon.png +0 -0
- cursorfleet-0.1.0/public-docs/assets/cursorfleet-icon-source.png +0 -0
- cursorfleet-0.1.0/public-docs/assets/cursorfleet-wordmark.png +0 -0
- cursorfleet-0.1.0/public-docs/assets/favicon-32.png +0 -0
- cursorfleet-0.1.0/public-docs/assets/logo-circle.png +0 -0
- cursorfleet-0.1.0/public-docs/assets/og-card.png +0 -0
- cursorfleet-0.1.0/public-docs/changelog.md +50 -0
- cursorfleet-0.1.0/public-docs/cli/doctor.md +64 -0
- cursorfleet-0.1.0/public-docs/cli/init.md +72 -0
- cursorfleet-0.1.0/public-docs/cli/status.md +55 -0
- cursorfleet-0.1.0/public-docs/cli/validate.md +42 -0
- cursorfleet-0.1.0/public-docs/concepts/agents-and-events.md +69 -0
- cursorfleet-0.1.0/public-docs/concepts/sessions.md +44 -0
- cursorfleet-0.1.0/public-docs/concepts/worktrees.md +51 -0
- cursorfleet-0.1.0/public-docs/contributing.md +88 -0
- cursorfleet-0.1.0/public-docs/getting-started/installation.md +65 -0
- cursorfleet-0.1.0/public-docs/getting-started/quickstart.md +116 -0
- cursorfleet-0.1.0/public-docs/index.md +62 -0
- cursorfleet-0.1.0/public-docs/known-limitations.md +82 -0
- cursorfleet-0.1.0/public-docs/overrides/main.html +66 -0
- cursorfleet-0.1.0/public-docs/privacy-and-security.md +79 -0
- cursorfleet-0.1.0/public-docs/stylesheets/site-brand.css +40 -0
- cursorfleet-0.1.0/public-docs/tui/current-status.md +30 -0
- cursorfleet-0.1.0/public-docs/tui/overview.md +81 -0
- cursorfleet-0.1.0/pyproject.toml +108 -0
- cursorfleet-0.1.0/schemas/.gitkeep +0 -0
- cursorfleet-0.1.0/schemas/config.schema.json +201 -0
- cursorfleet-0.1.0/schemas/event.schema.json +653 -0
- cursorfleet-0.1.0/schemas/policy.schema.json +10 -0
- cursorfleet-0.1.0/schemas/roster.schema.json +174 -0
- cursorfleet-0.1.0/scripts/bench_hook.py +156 -0
- cursorfleet-0.1.0/scripts/check_dist.py +96 -0
- cursorfleet-0.1.0/scripts/demo.py +278 -0
- cursorfleet-0.1.0/scripts/demo.sh +10 -0
- cursorfleet-0.1.0/scripts/gen_schemas.py +12 -0
- cursorfleet-0.1.0/scripts/smoke_wheel.py +178 -0
- cursorfleet-0.1.0/spike/README.md +270 -0
- cursorfleet-0.1.0/spike/analyze.py +1025 -0
- cursorfleet-0.1.0/spike/bench_latency.py +120 -0
- cursorfleet-0.1.0/spike/capture_hook.py +797 -0
- cursorfleet-0.1.0/spike/doc_examples/README.md +21 -0
- cursorfleet-0.1.0/spike/doc_examples/afterFileEdit.doc-derived.json +35 -0
- cursorfleet-0.1.0/spike/doc_examples/afterShellExecution.doc-derived.json +32 -0
- cursorfleet-0.1.0/spike/doc_examples/beforeShellExecution.doc-derived.json +31 -0
- cursorfleet-0.1.0/spike/doc_examples/postToolUse.doc-derived.json +36 -0
- cursorfleet-0.1.0/spike/doc_examples/postToolUseFailure.doc-derived.json +38 -0
- cursorfleet-0.1.0/spike/doc_examples/preCompact.doc-derived.json +35 -0
- cursorfleet-0.1.0/spike/doc_examples/preToolUse.doc-derived.json +36 -0
- cursorfleet-0.1.0/spike/doc_examples/sessionEnd.doc-derived.json +33 -0
- cursorfleet-0.1.0/spike/doc_examples/sessionStart.doc-derived.json +31 -0
- cursorfleet-0.1.0/spike/doc_examples/stop.doc-derived.json +30 -0
- cursorfleet-0.1.0/spike/doc_examples/subagentStart.doc-derived.json +36 -0
- cursorfleet-0.1.0/spike/doc_examples/subagentStop.doc-derived.json +41 -0
- cursorfleet-0.1.0/spike/hooks.json.example +77 -0
- cursorfleet-0.1.0/spike/hooks.windows.json.example +77 -0
- cursorfleet-0.1.0/spike/questions.md +157 -0
- cursorfleet-0.1.0/spike/results/latency-linux.json +54 -0
- cursorfleet-0.1.0/src/cursorfleet/__init__.py +9 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/blocks.py +104 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/diagnostics.py +547 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/fsutil.py +156 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/hook_main.py +428 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/hook_normalize.py +527 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/hook_policy.py +76 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/hook_sanitize.py +474 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/hooksjson.py +305 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/installer.py +626 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/kit.py +210 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/kit_probe.py +54 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/lock.py +145 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/templates.py +60 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/validation.py +365 -0
- cursorfleet-0.1.0/src/cursorfleet/adapters/cursor/workspace.py +80 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/__init__.py +1 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/_common.py +82 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/_resolution.py +56 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/doctor.py +81 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/events.py +197 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/index.py +55 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/init.py +71 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/migrate.py +43 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/replay.py +76 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/run.py +97 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/status.py +210 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/tui.py +47 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/uninstall.py +73 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/commands/validate.py +69 -0
- cursorfleet-0.1.0/src/cursorfleet/cli/main.py +81 -0
- cursorfleet-0.1.0/src/cursorfleet/config/__init__.py +44 -0
- cursorfleet-0.1.0/src/cursorfleet/config/io.py +27 -0
- cursorfleet-0.1.0/src/cursorfleet/config/models.py +154 -0
- cursorfleet-0.1.0/src/cursorfleet/config/roster.py +245 -0
- cursorfleet-0.1.0/src/cursorfleet/events/__init__.py +39 -0
- cursorfleet-0.1.0/src/cursorfleet/events/forbidden.py +45 -0
- cursorfleet-0.1.0/src/cursorfleet/events/ids.py +109 -0
- cursorfleet-0.1.0/src/cursorfleet/events/kinds.py +132 -0
- cursorfleet-0.1.0/src/cursorfleet/events/models.py +213 -0
- cursorfleet-0.1.0/src/cursorfleet/events/pathcheck.py +45 -0
- cursorfleet-0.1.0/src/cursorfleet/git/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/git/collector.py +226 -0
- cursorfleet-0.1.0/src/cursorfleet/git/runner.py +135 -0
- cursorfleet-0.1.0/src/cursorfleet/git/worktrees.py +71 -0
- cursorfleet-0.1.0/src/cursorfleet/policy/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/py.typed +0 -0
- cursorfleet-0.1.0/src/cursorfleet/safeexe.py +70 -0
- cursorfleet-0.1.0/src/cursorfleet/schema_gen.py +73 -0
- cursorfleet-0.1.0/src/cursorfleet/state/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/state/artifact_scan.py +309 -0
- cursorfleet-0.1.0/src/cursorfleet/state/context.py +38 -0
- cursorfleet-0.1.0/src/cursorfleet/state/event_store.py +227 -0
- cursorfleet-0.1.0/src/cursorfleet/state/indexer.py +443 -0
- cursorfleet-0.1.0/src/cursorfleet/state/lock.py +74 -0
- cursorfleet-0.1.0/src/cursorfleet/state/models.py +268 -0
- cursorfleet-0.1.0/src/cursorfleet/state/reducer.py +588 -0
- cursorfleet-0.1.0/src/cursorfleet/state/retention.py +218 -0
- cursorfleet-0.1.0/src/cursorfleet/state/run_builder.py +136 -0
- cursorfleet-0.1.0/src/cursorfleet/state/run_model.py +43 -0
- cursorfleet-0.1.0/src/cursorfleet/state/run_store.py +95 -0
- cursorfleet-0.1.0/src/cursorfleet/state/runtime.py +645 -0
- cursorfleet-0.1.0/src/cursorfleet/state/spool.py +186 -0
- cursorfleet-0.1.0/src/cursorfleet/state/spool_read.py +242 -0
- cursorfleet-0.1.0/src/cursorfleet/state/status_doc.py +293 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/app.py +581 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/data.py +545 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/filters.py +82 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/gates.py +255 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/help.py +101 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/layout.py +26 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/theme.py +176 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/views.py +1077 -0
- cursorfleet-0.1.0/src/cursorfleet/tui/watch.py +33 -0
- cursorfleet-0.1.0/src/cursorfleet/workflow/__init__.py +0 -0
- cursorfleet-0.1.0/src/cursorfleet/workflow/artifacts.py +148 -0
- cursorfleet-0.1.0/src/cursorfleet/workflow/frontmatter.py +232 -0
- cursorfleet-0.1.0/templates/cursor/agents/architect.md +18 -0
- cursorfleet-0.1.0/templates/cursor/agents/implementer.md +20 -0
- cursorfleet-0.1.0/templates/cursor/agents/patcher.md +17 -0
- cursorfleet-0.1.0/templates/cursor/agents/qa.md +21 -0
- cursorfleet-0.1.0/templates/cursor/agents/reviewer.md +20 -0
- cursorfleet-0.1.0/templates/cursor/agents/scout.md +17 -0
- cursorfleet-0.1.0/templates/cursor/agents/tester.md +20 -0
- cursorfleet-0.1.0/templates/cursor/agents-md/root.md +7 -0
- cursorfleet-0.1.0/templates/cursor/agents-md/work.md +7 -0
- cursorfleet-0.1.0/templates/cursor/config/config.toml +47 -0
- cursorfleet-0.1.0/templates/cursor/hooks/entry.json +4 -0
- cursorfleet-0.1.0/templates/cursor/rules/cursorfleet-core.mdc +10 -0
- cursorfleet-0.1.0/templates/cursor/rules/cursorfleet-handoff.mdc +15 -0
- cursorfleet-0.1.0/templates/cursor/skills/cursorfleet-artifacts/SKILL.md +57 -0
- cursorfleet-0.1.0/templates/cursor/skills/cursorfleet-coordinator/SKILL.md +35 -0
- cursorfleet-0.1.0/tests/conftest.py +3 -0
- cursorfleet-0.1.0/tests/event_factory.py +45 -0
- cursorfleet-0.1.0/tests/fixtures/cursor/.gitkeep +0 -0
- cursorfleet-0.1.0/tests/fixtures/cursor/legacy_test_completed.jsonl +1 -0
- cursorfleet-0.1.0/tests/fixtures/cursor/post_m25_verification_observed.jsonl +1 -0
- cursorfleet-0.1.0/tests/fixtures/status/status.v1.golden.json +275 -0
- cursorfleet-0.1.0/tests/integration/test_cli_state.py +295 -0
- cursorfleet-0.1.0/tests/integration/test_doctor_validate_resolution.py +282 -0
- cursorfleet-0.1.0/tests/integration/test_git_collector.py +293 -0
- cursorfleet-0.1.0/tests/integration/test_hook_main.py +299 -0
- cursorfleet-0.1.0/tests/integration/test_kit_doctor_validate.py +406 -0
- cursorfleet-0.1.0/tests/integration/test_kit_init_uninstall.py +442 -0
- cursorfleet-0.1.0/tests/integration/test_runtime_inheritance.py +318 -0
- cursorfleet-0.1.0/tests/integration/test_runtime_resolution.py +110 -0
- cursorfleet-0.1.0/tests/integration/test_spool_migration.py +75 -0
- cursorfleet-0.1.0/tests/kit_helpers.py +44 -0
- cursorfleet-0.1.0/tests/m2_helpers.py +214 -0
- cursorfleet-0.1.0/tests/m2_strategies.py +99 -0
- cursorfleet-0.1.0/tests/perf/test_hook_benchmark.py +49 -0
- cursorfleet-0.1.0/tests/security/test_event_privacy.py +186 -0
- cursorfleet-0.1.0/tests/security/test_hook_policy.py +66 -0
- cursorfleet-0.1.0/tests/security/test_hook_privacy.py +432 -0
- cursorfleet-0.1.0/tests/security/test_hook_redos.py +96 -0
- cursorfleet-0.1.0/tests/security/test_hostile_repo.py +312 -0
- cursorfleet-0.1.0/tests/security/test_kit_installer_policy.py +124 -0
- cursorfleet-0.1.0/tests/security/test_no_network.py +161 -0
- cursorfleet-0.1.0/tests/security/test_runtime_trust.py +108 -0
- cursorfleet-0.1.0/tests/security/test_terminal_injection.py +86 -0
- cursorfleet-0.1.0/tests/tui/test_tui_app.py +670 -0
- cursorfleet-0.1.0/tests/tui/test_tui_cli.py +104 -0
- cursorfleet-0.1.0/tests/tui/test_tui_data.py +354 -0
- cursorfleet-0.1.0/tests/tui/test_tui_gates.py +158 -0
- cursorfleet-0.1.0/tests/tui/test_tui_privacy.py +214 -0
- cursorfleet-0.1.0/tests/tui_helpers.py +189 -0
- cursorfleet-0.1.0/tests/unit/test_artifact_scan.py +205 -0
- cursorfleet-0.1.0/tests/unit/test_cli.py +22 -0
- cursorfleet-0.1.0/tests/unit/test_config_models.py +66 -0
- cursorfleet-0.1.0/tests/unit/test_event_models.py +239 -0
- cursorfleet-0.1.0/tests/unit/test_event_store.py +90 -0
- cursorfleet-0.1.0/tests/unit/test_fs_names.py +60 -0
- cursorfleet-0.1.0/tests/unit/test_hook_normalize.py +240 -0
- cursorfleet-0.1.0/tests/unit/test_hook_sanitize.py +232 -0
- cursorfleet-0.1.0/tests/unit/test_ids.py +43 -0
- cursorfleet-0.1.0/tests/unit/test_indexer.py +273 -0
- cursorfleet-0.1.0/tests/unit/test_kit_blocks.py +51 -0
- cursorfleet-0.1.0/tests/unit/test_kit_frontmatter.py +104 -0
- cursorfleet-0.1.0/tests/unit/test_kit_hooksjson.py +134 -0
- cursorfleet-0.1.0/tests/unit/test_kit_probe.py +39 -0
- cursorfleet-0.1.0/tests/unit/test_kit_templates.py +85 -0
- cursorfleet-0.1.0/tests/unit/test_reducer.py +372 -0
- cursorfleet-0.1.0/tests/unit/test_retention.py +158 -0
- cursorfleet-0.1.0/tests/unit/test_roster.py +103 -0
- cursorfleet-0.1.0/tests/unit/test_run_builder.py +122 -0
- cursorfleet-0.1.0/tests/unit/test_run_store.py +14 -0
- cursorfleet-0.1.0/tests/unit/test_schemas.py +46 -0
- cursorfleet-0.1.0/tests/unit/test_spike_analyze.py +1111 -0
- cursorfleet-0.1.0/tests/unit/test_spool.py +351 -0
- cursorfleet-0.1.0/uv.lock +1288 -0
- cursorfleet-0.1.0/zensical.toml +92 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Privacy and hook hot-path constraints; apply when touching events, adapters or hooks
|
|
3
|
+
globs: src/cursorfleet/events/**,src/cursorfleet/adapters/**,templates/cursor/hooks/**
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
- Hook entrypoint code is **stdlib-only** with lazy imports and must always fail open (exit 0; print `{"permission":"allow"}` for permission hooks, `{}` for the rest).
|
|
8
|
+
- Parse hook payloads through an allowlist at the boundary. Never persist prompts, thinking or response text, file contents, command output, env, `user_email` or `transcript_path`.
|
|
9
|
+
- Do not register `beforeSubmitPrompt`, `afterAgentThought`, `afterAgentResponse` or `beforeReadFile` in v0.1; keep a test that generated hook config never contains them.
|
|
10
|
+
- Hooks only append to per-session JSONL spools; only the indexer writes SQLite.
|
|
11
|
+
- Runtime dir is `<git-common-dir>/cursorfleet/` with 0700 dirs and 0600 files.
|
|
12
|
+
- No network calls anywhere in the hook path.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Python style and typing conventions for CursorFleet source and tests
|
|
3
|
+
globs: src/**/*.py,tests/**/*.py
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
- Python >=3.11, fully typed (`mypy --strict`), formatted/linted with ruff (line length 100).
|
|
8
|
+
- Use `from __future__ import annotations` in new modules.
|
|
9
|
+
- Subprocess calls: argv list, explicit `timeout=`, never `shell=True`.
|
|
10
|
+
- Tests: no `time.sleep`; prefer deterministic fakes, `tmp_path`, and Textual `run_test()` for TUI.
|
|
11
|
+
- Tests live in `tests/{unit,integration,tui,security}`; fixtures in `tests/fixtures/cursor` must be sanitized.
|
|
12
|
+
- CLI command groups: one module per group in `src/cursorfleet/cli/commands/` exposing `register(app)`.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
# Least privilege: every job only reads the repository. No job has a token that can write.
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
# Third-party actions are pinned by major version. Pinning them to full commit SHAs (with
|
|
18
|
+
# Dependabot to bump them) is a documented follow-up: docs/security-review-v0.1.md (SO-02).
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
lint:
|
|
22
|
+
name: lint, format, types
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: astral-sh/setup-uv@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
enable-cache: true
|
|
30
|
+
- run: uv sync --locked --all-extras
|
|
31
|
+
- run: uv run ruff check .
|
|
32
|
+
- run: uv run ruff format --check .
|
|
33
|
+
- run: uv run mypy src
|
|
34
|
+
|
|
35
|
+
test:
|
|
36
|
+
name: test ${{ matrix.os }} / py${{ matrix.python-version }}
|
|
37
|
+
runs-on: ${{ matrix.os }}
|
|
38
|
+
strategy:
|
|
39
|
+
fail-fast: false
|
|
40
|
+
matrix:
|
|
41
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
42
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: astral-sh/setup-uv@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: ${{ matrix.python-version }}
|
|
48
|
+
enable-cache: true
|
|
49
|
+
- run: uv sync --locked --all-extras
|
|
50
|
+
# Benchmark-marked tests are excluded by default (pyproject addopts).
|
|
51
|
+
- run: uv run pytest --cov=cursorfleet --cov-report=term-missing --cov-report=xml
|
|
52
|
+
- name: Hook benchmark smoke (records timings, no assertions on speed)
|
|
53
|
+
if: matrix.python-version == '3.12'
|
|
54
|
+
continue-on-error: true
|
|
55
|
+
run: uv run pytest -m benchmark -q
|
|
56
|
+
- uses: actions/upload-artifact@v4
|
|
57
|
+
if: matrix.python-version == '3.12'
|
|
58
|
+
with:
|
|
59
|
+
name: coverage-${{ matrix.os }}
|
|
60
|
+
path: coverage.xml
|
|
61
|
+
if-no-files-found: ignore
|
|
62
|
+
|
|
63
|
+
package:
|
|
64
|
+
name: build and smoke-test the wheel on ${{ matrix.os }}
|
|
65
|
+
runs-on: ${{ matrix.os }}
|
|
66
|
+
needs: lint
|
|
67
|
+
strategy:
|
|
68
|
+
fail-fast: false
|
|
69
|
+
matrix:
|
|
70
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
71
|
+
defaults:
|
|
72
|
+
run:
|
|
73
|
+
shell: bash
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v4
|
|
76
|
+
- uses: astral-sh/setup-uv@v5
|
|
77
|
+
with:
|
|
78
|
+
python-version: "3.12"
|
|
79
|
+
enable-cache: true
|
|
80
|
+
- name: Build sdist and wheel
|
|
81
|
+
run: uv build
|
|
82
|
+
- name: Verify the distributions (templates, scripts, license, long description)
|
|
83
|
+
run: uv run --no-project python scripts/check_dist.py dist
|
|
84
|
+
- name: Install the wheel into a clean venv outside the checkout
|
|
85
|
+
run: |
|
|
86
|
+
uv venv "$RUNNER_TEMP/smoke-venv"
|
|
87
|
+
uv pip install --python "$RUNNER_TEMP/smoke-venv" dist/*.whl
|
|
88
|
+
- name: Smoke test the installed scripts (synthetic payloads; Cursor is never started)
|
|
89
|
+
run: uv run --no-project python scripts/smoke_wheel.py "$RUNNER_TEMP/smoke-venv"
|
|
90
|
+
- uses: actions/upload-artifact@v4
|
|
91
|
+
if: matrix.os == 'ubuntu-latest'
|
|
92
|
+
with:
|
|
93
|
+
name: dist
|
|
94
|
+
path: dist/
|
|
95
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Public docs site (Zensical → GitHub Pages).
|
|
2
|
+
#
|
|
3
|
+
# Build runs on pull requests and on main. Deploy is off by default so a push
|
|
4
|
+
# cannot publish. The owner must later: (1) enable Pages with source
|
|
5
|
+
# "GitHub Actions", (2) set the repository variable PAGES_ENABLED=true.
|
|
6
|
+
# Official Pages actions: https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages
|
|
7
|
+
# Zensical build: https://zensical.org/docs/publish-your-site/
|
|
8
|
+
|
|
9
|
+
name: Pages
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
branches: [main]
|
|
14
|
+
pull_request:
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
|
|
17
|
+
# Least privilege: every job starts read-only. Only deploy elevates.
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: pages-${{ github.workflow }}-${{ github.ref }}
|
|
23
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
name: build docs site
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- uses: astral-sh/setup-uv@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.12"
|
|
34
|
+
enable-cache: true
|
|
35
|
+
- run: uv sync --locked --all-extras
|
|
36
|
+
- run: uv run zensical build --clean
|
|
37
|
+
- uses: actions/configure-pages@v6
|
|
38
|
+
- uses: actions/upload-pages-artifact@v5
|
|
39
|
+
with:
|
|
40
|
+
path: site
|
|
41
|
+
|
|
42
|
+
deploy:
|
|
43
|
+
name: deploy to GitHub Pages
|
|
44
|
+
# Kill switch: unset/false keeps this workflow build-only.
|
|
45
|
+
if: github.event_name != 'pull_request' && vars.PAGES_ENABLED == 'true'
|
|
46
|
+
needs: build
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
environment:
|
|
49
|
+
name: github-pages
|
|
50
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
51
|
+
permissions:
|
|
52
|
+
pages: write
|
|
53
|
+
id-token: write
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/deploy-pages@v5
|
|
56
|
+
id: deployment
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# INACTIVE until the owner acts: this workflow only runs when a tag named v* is pushed, and
|
|
4
|
+
# the PyPI publish job additionally requires the repository variable RELEASE_ENABLED=true and
|
|
5
|
+
# the protected `pypi` environment. Nothing here has ever been run. See
|
|
6
|
+
# docs/release-checklist.md for the exact owner steps (and which are blocking).
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
# Third-party actions are pinned by major version; SHA pinning is a documented follow-up
|
|
16
|
+
# (docs/security-review-v0.1.md, SO-02).
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
checks:
|
|
20
|
+
name: checks ${{ matrix.os }} / py${{ matrix.python-version }}
|
|
21
|
+
runs-on: ${{ matrix.os }}
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: true
|
|
24
|
+
matrix:
|
|
25
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
26
|
+
python-version: ["3.11", "3.14"]
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: astral-sh/setup-uv@v5
|
|
30
|
+
with:
|
|
31
|
+
python-version: ${{ matrix.python-version }}
|
|
32
|
+
enable-cache: true
|
|
33
|
+
- run: uv sync --locked --all-extras
|
|
34
|
+
- run: uv run ruff check .
|
|
35
|
+
- run: uv run ruff format --check .
|
|
36
|
+
- run: uv run mypy src
|
|
37
|
+
- run: uv run pytest
|
|
38
|
+
|
|
39
|
+
build:
|
|
40
|
+
name: build distributions
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
needs: checks
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: astral-sh/setup-uv@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
- name: The tag must match the version in pyproject.toml
|
|
49
|
+
run: |
|
|
50
|
+
version="$(uv run --no-project python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")"
|
|
51
|
+
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
|
|
52
|
+
echo "tag ${GITHUB_REF_NAME} does not match pyproject version ${version}" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
- run: uv build
|
|
56
|
+
- run: uv run --no-project python scripts/check_dist.py dist
|
|
57
|
+
- name: Smoke test the wheel in a clean venv
|
|
58
|
+
run: |
|
|
59
|
+
uv venv "$RUNNER_TEMP/smoke-venv"
|
|
60
|
+
uv pip install --python "$RUNNER_TEMP/smoke-venv" dist/*.whl
|
|
61
|
+
uv run --no-project python scripts/smoke_wheel.py "$RUNNER_TEMP/smoke-venv"
|
|
62
|
+
- uses: actions/upload-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: dist
|
|
65
|
+
path: dist/
|
|
66
|
+
if-no-files-found: error
|
|
67
|
+
|
|
68
|
+
github-release:
|
|
69
|
+
name: draft GitHub release
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
needs: build
|
|
72
|
+
permissions:
|
|
73
|
+
contents: write # only this job can create the (draft) release
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v4
|
|
76
|
+
- uses: actions/download-artifact@v4
|
|
77
|
+
with:
|
|
78
|
+
name: dist
|
|
79
|
+
path: dist/
|
|
80
|
+
# A DRAFT: the owner reviews the notes and publishes it by hand.
|
|
81
|
+
- name: Create the draft release with the sdist and wheel attached
|
|
82
|
+
env:
|
|
83
|
+
GH_TOKEN: ${{ github.token }}
|
|
84
|
+
run: |
|
|
85
|
+
gh release create "${GITHUB_REF_NAME}" dist/* \
|
|
86
|
+
--draft --verify-tag \
|
|
87
|
+
--title "CursorFleet ${GITHUB_REF_NAME}" \
|
|
88
|
+
--notes "Draft. Copy the matching section of CHANGELOG.md here before publishing. Unofficial: not affiliated with or endorsed by Anysphere or Cursor."
|
|
89
|
+
|
|
90
|
+
publish-pypi:
|
|
91
|
+
name: publish to PyPI (Trusted Publishing)
|
|
92
|
+
runs-on: ubuntu-latest
|
|
93
|
+
needs: build
|
|
94
|
+
# Kill switch: set the repository variable RELEASE_ENABLED=true to allow publishing.
|
|
95
|
+
if: vars.RELEASE_ENABLED == 'true'
|
|
96
|
+
environment:
|
|
97
|
+
name: pypi # protected environment: configure required reviewers in the repository settings
|
|
98
|
+
url: https://pypi.org/project/cursorfleet/
|
|
99
|
+
permissions:
|
|
100
|
+
id-token: write # OIDC token for Trusted Publishing; granted to this job only
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/download-artifact@v4
|
|
103
|
+
with:
|
|
104
|
+
name: dist
|
|
105
|
+
path: dist/
|
|
106
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Generated public docs site (zensical.toml site_dir)
|
|
2
|
+
site/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.eggs/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.hypothesis/
|
|
15
|
+
.coverage
|
|
16
|
+
coverage.xml
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# Environments
|
|
20
|
+
.venv/
|
|
21
|
+
venv/
|
|
22
|
+
.env
|
|
23
|
+
|
|
24
|
+
# CursorFleet runtime state (committed config in .cursorfleet/ is config.toml, roster.toml, work/)
|
|
25
|
+
.cursorfleet/runtime/
|
|
26
|
+
.cursorfleet/*.sqlite*
|
|
27
|
+
.cursorfleet/*.jsonl
|
|
28
|
+
.cursorfleet/*.lock
|
|
29
|
+
|
|
30
|
+
# OS / editor
|
|
31
|
+
.DS_Store
|
|
32
|
+
Thumbs.db
|
|
33
|
+
.idea/
|
|
34
|
+
.vscode/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# CursorFleet: developer conventions
|
|
2
|
+
|
|
3
|
+
CursorFleet is a local TUI and workflow harness for Cursor agent teams. v0.1 is **Observe** only: no enforcement, no forced approvals, no cloud-agent visibility. Cursor is the only officially supported IDE; keep internals adapter-ready (`cursorfleet.adapters.*`, normalized events).
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
- `src/cursorfleet/`: package (`cli`, `config`, `adapters/cursor`, `events`, `state`, `git`, `policy`, `workflow`, `tui`).
|
|
7
|
+
- `tests/{unit,integration,tui,security}`, `tests/fixtures/cursor` (sanitized real payloads only).
|
|
8
|
+
- `schemas/` JSON Schemas, `templates/cursor/` generated-kit templates, `docs/` documentation.
|
|
9
|
+
- Committed config: `.cursorfleet/`. Runtime state lives under `<git-common-dir>/cursorfleet/`, never in the working tree.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
- `uv sync` then `uv run ruff check .`, `uv run mypy src`, `uv run pytest`.
|
|
13
|
+
|
|
14
|
+
## Rules
|
|
15
|
+
- **Hook hot path is stdlib-only.** No pydantic/typer/textual imports (even transitively) in hook entrypoints; lazy-import everything else. Hooks must fail open: always exit 0 on any internal error, printing the right reply for the hook type: `{"permission":"allow"}` for permission hooks (`preToolUse`, `subagentStart`, `beforeShellExecution`, and `beforeMCPExecution`/`beforeReadFile` should they ever be wired), `{}` for all others (see `hook_policy.fail_open_response` and ADR 0004). An invalid reply from a permission hook blocks the action.
|
|
16
|
+
- **Every subprocess** uses an argv list (never `shell=True`) and an explicit `timeout=`.
|
|
17
|
+
- **Never persist** prompts, thinking/response text, file contents, command output, env vars, user emails or transcript paths. Drop them at the parser boundary using an allowlist. Never register `beforeSubmitPrompt`, `afterAgentThought`, `afterAgentResponse` or `beforeReadFile` hooks in v0.1.
|
|
18
|
+
- Paths stored are workspace-relative; anything outside workspace roots becomes `<external>`.
|
|
19
|
+
- **No sleeps in tests.** Use events, polling with deadlines on fakes, or Textual `run_test()` pilots.
|
|
20
|
+
- New CLI command groups go in their own module under `cli/commands/` exposing `register(app)`; do not edit `cli/main.py`.
|
|
21
|
+
- Rules in `.cursor/rules/` must be `.mdc` with frontmatter and under 500 lines.
|
|
22
|
+
- Python >=3.11; type-annotate everything (`mypy --strict`); keep Windows/macOS/Linux parity.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to CursorFleet are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project intends to follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/) once a first release exists.
|
|
6
|
+
|
|
7
|
+
CursorFleet is an unofficial tool: it is not affiliated with or endorsed by Anysphere or Cursor.
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
Development version `0.1.1.dev0` (post-v0.1.0). Planned: TUI attach picker, external alpha metrics.
|
|
12
|
+
|
|
13
|
+
## [0.1.0] - 2026-10-12
|
|
14
|
+
|
|
15
|
+
First public pre-alpha on PyPI (when `RELEASE_ENABLED` is approved). **Observe-only:** no
|
|
16
|
+
enforcement, no cloud-agent visibility. External user validation and B0 live scenarios 1/2/5
|
|
17
|
+
remain documented in [docs/evidence/v01-release-ready.md](docs/evidence/v01-release-ready.md).
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Active run TUI** (default): participant groups/instances, runs list (`u`), sessions archive (`o`).
|
|
22
|
+
- **`cursorfleet run`** start/list/attach/archive; run files under git common dir ([ADR 0013](docs/adr/0013-run-metadata-and-association.md)).
|
|
23
|
+
- **`status --json` `runs[]`** when telemetry exists (`cursorfleet.status/0.2`).
|
|
24
|
+
- Legacy spool **`test.completed`** fixture + migration integration test; sanitized corpus under `tests/fixtures/cursor/`.
|
|
25
|
+
|
|
26
|
+
### Process
|
|
27
|
+
|
|
28
|
+
- **M2.5 charter (2026-10-05).** Task-centric local observer work is active; M0a capture kit
|
|
29
|
+
and product hooks are tracked separately ([docs/evidence/live-validation-index.md](docs/evidence/live-validation-index.md)).
|
|
30
|
+
Linux Cursor IDE 3.22.7 product-hook smoke confirmed telemetry; Q1/Q2 remain OPEN.
|
|
31
|
+
See [docs/status.md](docs/status.md).
|
|
32
|
+
- **M0a freeze (2026-10-04, superseded for product direction).** Formal ADR 0001 matrix and
|
|
33
|
+
spike kit remain for Q1–Q6; see [spike/README.md](spike/README.md).
|
|
34
|
+
|
|
35
|
+
### Documentation
|
|
36
|
+
|
|
37
|
+
- ADR process and template accepted as ADR 0000, with required fields on every ADR
|
|
38
|
+
(supersession, related ADRs, implementation status, review trigger, release gate) and an
|
|
39
|
+
indexed list of release gates in [docs/adr/README.md](docs/adr/README.md).
|
|
40
|
+
- New ADRs: 0007 narrower v0.1 hook policy (supersedes 0004; nine hooks), 0008 enforcement
|
|
41
|
+
boundaries, 0009 install and uninstall ownership, 0010 reducer state semantics, 0011
|
|
42
|
+
evidence trust model, 0012 roster and worktree ownership.
|
|
43
|
+
- Decisions recorded that the code does **not** yet follow (tracked in
|
|
44
|
+
[docs/follow-ups.md](docs/follow-ups.md), to be done after the spike): nine registered
|
|
45
|
+
hooks, event schema version `0.1`, `verification.observed` instead of `test.completed`,
|
|
46
|
+
command display off by default, BLAKE2s segment fingerprints, HMAC worktree ids, a
|
|
47
|
+
maintenance lock, TOML artifact frontmatter, no gate derived from heuristic events, and
|
|
48
|
+
`init`/`uninstall` repository-root preconditions (exit 2; no `--allow-non-git`), and
|
|
49
|
+
runtime inheritance of an initialized enclosing repository for nested non-Git directories
|
|
50
|
+
(ADR 0002; `init` still refuses ordinary subdirectories).
|
|
51
|
+
- ADR 0001 stays provisional and now carries an empirical test matrix; the local Cursor IDE
|
|
52
|
+
(desktop) is the only supported v0.1 surface, and the CLI, Agents Window and worktrees are
|
|
53
|
+
not claimed. See [docs/empirical-test-plan.md](docs/empirical-test-plan.md).
|
|
54
|
+
- ADR 0005: `CursorFleet` is a working name; the public name, registry availability and a
|
|
55
|
+
trademark review are release gates. `fleet-for-cursor` is withdrawn as a fallback because
|
|
56
|
+
it still contains the Cursor mark.
|
|
57
|
+
- Docs-site plan only ([docs/docs-site-plan.md](docs/docs-site-plan.md)); no site, workflow or
|
|
58
|
+
dependency was added.
|
|
59
|
+
- ADR 0002 / 0009: a nested non-Git directory inherits an already initialized enclosing
|
|
60
|
+
repository for runtime event attribution; `init` from an ordinary subdirectory still
|
|
61
|
+
exits 2 (documentation only).
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- **M0 foundations:** project scaffold, ADRs 0001 to 0006, product contract, threat model,
|
|
66
|
+
privacy statement, JSON Schemas for events, config, roster and policy (reserved), a throwaway
|
|
67
|
+
capture kit under `spike/` and a Linux hook-latency benchmark (27.7 ms steady-state p95).
|
|
68
|
+
- **M1 kit:** `cursorfleet init --cursor`, `uninstall`, `doctor` and `validate`. Deterministic
|
|
69
|
+
generation of subagent files, rules, skills, `AGENTS.md` blocks and a merged
|
|
70
|
+
`.cursor/hooks.json` of twelve passive hooks (ADR 0007 later narrowed this to nine; code not yet changed), with a visible diff, confirmation, an install
|
|
71
|
+
lockfile and byte-for-byte uninstall.
|
|
72
|
+
- **M2 observer:** a stdlib-only, fail-open hook entry point (`cursorfleet-hook`) with an
|
|
73
|
+
allowlist parser, command and path sanitizer, per-writer append-only JSONL spool with CRC and
|
|
74
|
+
size caps, a single-writer SQLite projection with quarantine and rebuild, deterministic
|
|
75
|
+
reducer and `replay`, a read-only git/worktree collector, retention and `events export` /
|
|
76
|
+
`events purge`, and `status --json` (`cursorfleet.status/1`).
|
|
77
|
+
- **M3 dashboard:** the Textual TUI (`cursorfleet tui`) with overview, agent detail, timeline,
|
|
78
|
+
worktrees, gates (display-only), evidence and tiles views, filtering, pinning, and a degraded
|
|
79
|
+
mode for missing telemetry.
|
|
80
|
+
- **M4 release preparation:**
|
|
81
|
+
- security and privacy review ([docs/security-review-v0.1.md](docs/security-review-v0.1.md))
|
|
82
|
+
with regression tests, including a no-network test;
|
|
83
|
+
- cross-platform CI (Linux, macOS, Windows; Python 3.11 to 3.14) with lint, format, types,
|
|
84
|
+
coverage, and a wheel build-and-smoke-test job; inactive release workflow
|
|
85
|
+
(`.github/workflows/release.yml`) using PyPI Trusted Publishing and a draft GitHub release;
|
|
86
|
+
- `docs/quickstart.md`, `governance.md`, `demo.md`, `platform-support.md`,
|
|
87
|
+
`release-checklist.md` and a reproducible synthetic demo (`scripts/demo.sh`).
|
|
88
|
+
|
|
89
|
+
### Security
|
|
90
|
+
|
|
91
|
+
- Bounded redaction window removes a regular-expression denial of service in the hook's command
|
|
92
|
+
and text redaction (SR-01).
|
|
93
|
+
- The runtime directory is refused when it is a symlink, a reparse point, owned by another user
|
|
94
|
+
or group/other-writable (SR-02).
|
|
95
|
+
- Tools (`git`, `cursor`) are resolved from absolute `PATH` entries only, never the current
|
|
96
|
+
directory (SR-03); NTFS junctions count as links (SR-04); the workspace resolver uses the same
|
|
97
|
+
hostile-repository git hardening as the collector (SR-05); paths inside `.git` are rejected in
|
|
98
|
+
config and lockfile (SR-06).
|
|
99
|
+
- Lower-severity hardening: planted-database recovery, no local variables in tracebacks,
|
|
100
|
+
escaped terminal control characters in error and doctor output, `O_NOFOLLOW` artifact reads,
|
|
101
|
+
non-blocking spool open, drive-letter refs refused, attached `mysql -p` passwords redacted.
|
|
102
|
+
|
|
103
|
+
### Known limitations (0.1.0)
|
|
104
|
+
|
|
105
|
+
- Run association requires explicit `cursorfleet run` / env attach; TUI picker planned for 0.1.1.
|
|
106
|
+
- Observations screen is non-authoritative (ADR 0011); artifacts are self-reported (ADR 0006 amendment).
|
|
107
|
+
- Twelve passive observe hooks (ADR 0007 amendment 2026-10-12).
|
|
108
|
+
- ADR 0001 Q1/Q2 OPEN; end-to-end latency 13B may be OPEN — see evidence index.
|
|
109
|
+
- SO-01 live permission-hook confirmation may be pending — see [so01-permission-hooks.md](docs/evidence/so01-permission-hooks.md).
|
|
110
|
+
|
|
111
|
+
### Known limitations (historical pre-0.1.0 notes)
|
|
112
|
+
|
|
113
|
+
- The TUI derives PASS/FAIL gate tiles from heuristic command classification. This is
|
|
114
|
+
non-authoritative and contradicts ADR 0003 rule R1; fix pending after the spike.
|
|
115
|
+
- The code registers twelve hooks; ADR 0007 decides nine.
|
|
116
|
+
- Hook payload shapes come from documentation, not captures. Agent attribution on tool events,
|
|
117
|
+
custom subagent names, CLI and Agents Window behaviour, and macOS/Windows hook latency are
|
|
118
|
+
unverified (see [docs/platform-support.md](docs/platform-support.md)).
|
|
119
|
+
- Windows ACLs are not set on the runtime directory.
|
|
120
|
+
- GitHub Actions are pinned by major version, not by commit SHA.
|
|
121
|
+
- `cursorfleet emit` (ADR 0006 fallback) is not implemented.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Contributing to CursorFleet
|
|
2
|
+
|
|
3
|
+
CursorFleet is pre-alpha and unofficial. Issues and small PRs are welcome; for larger changes
|
|
4
|
+
please open an issue first. For security problems do **not** open a public issue: see
|
|
5
|
+
[SECURITY.md](SECURITY.md).
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync --all-extras
|
|
11
|
+
uv run cursorfleet --version
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Checks (must pass before a PR)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv run ruff check .
|
|
18
|
+
uv run ruff format --check . # `uv run ruff format .` fixes it
|
|
19
|
+
uv run mypy src
|
|
20
|
+
uv run pytest # benchmark-marked tests are excluded by default
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
CI runs the same on Linux, macOS and Windows with Python 3.11 to 3.14, plus a job that builds
|
|
24
|
+
the wheel and smoke-tests it in a clean venv. To reproduce that locally:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv build && python scripts/check_dist.py dist
|
|
28
|
+
uv venv /tmp/cf-venv && uv pip install --python /tmp/cf-venv dist/*.whl
|
|
29
|
+
python scripts/smoke_wheel.py /tmp/cf-venv
|
|
30
|
+
python scripts/demo.py --venv /tmp/cf-venv # synthetic demo, no Cursor
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Coverage: `uv run pytest --cov=cursorfleet --cov-report=term-missing`. Hook timings:
|
|
34
|
+
`uv run pytest -m benchmark` or `uv run python scripts/bench_hook.py`.
|
|
35
|
+
|
|
36
|
+
Without uv: `python -m venv .venv && .venv/bin/pip install -e ".[watch]" --group dev` (pip >= 25.1),
|
|
37
|
+
then run the tools from `.venv/bin`.
|
|
38
|
+
|
|
39
|
+
## Conventions
|
|
40
|
+
|
|
41
|
+
Read [`AGENTS.md`](AGENTS.md). Highlights:
|
|
42
|
+
|
|
43
|
+
- the hook hot path is stdlib-only and fails open (exit 0 with the right reply);
|
|
44
|
+
- every subprocess uses an argv list and an explicit `timeout=`; resolve tools with
|
|
45
|
+
`cursorfleet.safeexe.find_executable`, never from the current directory;
|
|
46
|
+
- never persist prompts, thinking, file contents, command output, env, emails or transcript
|
|
47
|
+
paths; drop them at the parser boundary with an allowlist;
|
|
48
|
+
- no sleeps in tests; keep Windows, macOS and Linux behaviour in step and skip a test only with
|
|
49
|
+
an explicit `reason=`;
|
|
50
|
+
- security-relevant changes get a regression test under `tests/security/`;
|
|
51
|
+
- documentation must stay honest: mark anything that depends on unverified Cursor behaviour
|
|
52
|
+
as PROVISIONAL, and do not claim enforcement.
|
|
53
|
+
|
|
54
|
+
Do not commit real Cursor payloads. Fixtures under `tests/fixtures/cursor` must be captured,
|
|
55
|
+
reviewed and sanitized, with the Cursor version recorded; doc-derived examples live in
|
|
56
|
+
`spike/doc_examples` and are not fixtures.
|
|
57
|
+
|
|
58
|
+
By contributing you agree your work is licensed under the MIT License.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mounir Al-Suroji
|
|
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.
|