pulse-coding-agent 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.
Files changed (196) hide show
  1. pulse_coding_agent-0.1.0/.env.example +39 -0
  2. pulse_coding_agent-0.1.0/.gitignore +82 -0
  3. pulse_coding_agent-0.1.0/ARCHITECTURE.md +119 -0
  4. pulse_coding_agent-0.1.0/CHANGELOG.md +52 -0
  5. pulse_coding_agent-0.1.0/OPERATIONS.md +161 -0
  6. pulse_coding_agent-0.1.0/PKG-INFO +211 -0
  7. pulse_coding_agent-0.1.0/PRIVACY.md +66 -0
  8. pulse_coding_agent-0.1.0/README.md +180 -0
  9. pulse_coding_agent-0.1.0/SECURITY.md +30 -0
  10. pulse_coding_agent-0.1.0/agent.config.json +25 -0
  11. pulse_coding_agent-0.1.0/evals/provider-live-v1.json +19 -0
  12. pulse_coding_agent-0.1.0/evals/release-v1.json +54 -0
  13. pulse_coding_agent-0.1.0/pyproject.toml +101 -0
  14. pulse_coding_agent-0.1.0/scripts/__init__.py +1 -0
  15. pulse_coding_agent-0.1.0/scripts/finalize_sbom.py +67 -0
  16. pulse_coding_agent-0.1.0/scripts/generate_release_metadata.py +88 -0
  17. pulse_coding_agent-0.1.0/scripts/run_docker_release_tests.py +69 -0
  18. pulse_coding_agent-0.1.0/scripts/run_provider_e2e.py +97 -0
  19. pulse_coding_agent-0.1.0/scripts/run_release_evals.py +87 -0
  20. pulse_coding_agent-0.1.0/scripts/verify_release_artifacts.py +191 -0
  21. pulse_coding_agent-0.1.0/src/pulse/__init__.py +5 -0
  22. pulse_coding_agent-0.1.0/src/pulse/__main__.py +4 -0
  23. pulse_coding_agent-0.1.0/src/pulse/agent.py +270 -0
  24. pulse_coding_agent-0.1.0/src/pulse/agent_manager.py +335 -0
  25. pulse_coding_agent-0.1.0/src/pulse/audit.py +70 -0
  26. pulse_coding_agent-0.1.0/src/pulse/auth.py +670 -0
  27. pulse_coding_agent-0.1.0/src/pulse/ci/github_client.py +66 -0
  28. pulse_coding_agent-0.1.0/src/pulse/ci/runner.py +28 -0
  29. pulse_coding_agent-0.1.0/src/pulse/cli.py +1075 -0
  30. pulse_coding_agent-0.1.0/src/pulse/cli_ui.py +977 -0
  31. pulse_coding_agent-0.1.0/src/pulse/config.py +167 -0
  32. pulse_coding_agent-0.1.0/src/pulse/context.py +960 -0
  33. pulse_coding_agent-0.1.0/src/pulse/conversations/__init__.py +8 -0
  34. pulse_coding_agent-0.1.0/src/pulse/conversations/manager.py +312 -0
  35. pulse_coding_agent-0.1.0/src/pulse/core/agent.py +188 -0
  36. pulse_coding_agent-0.1.0/src/pulse/core/planner.py +105 -0
  37. pulse_coding_agent-0.1.0/src/pulse/core/protocols.py +37 -0
  38. pulse_coding_agent-0.1.0/src/pulse/edits.py +65 -0
  39. pulse_coding_agent-0.1.0/src/pulse/episodic.py +93 -0
  40. pulse_coding_agent-0.1.0/src/pulse/eval/__init__.py +8 -0
  41. pulse_coding_agent-0.1.0/src/pulse/eval/trajectory_logger.py +91 -0
  42. pulse_coding_agent-0.1.0/src/pulse/eval/verifier.py +133 -0
  43. pulse_coding_agent-0.1.0/src/pulse/execution/__init__.py +5 -0
  44. pulse_coding_agent-0.1.0/src/pulse/execution/remote_task.py +76 -0
  45. pulse_coding_agent-0.1.0/src/pulse/git.py +162 -0
  46. pulse_coding_agent-0.1.0/src/pulse/interactive.py +234 -0
  47. pulse_coding_agent-0.1.0/src/pulse/mcp/__init__.py +4 -0
  48. pulse_coding_agent-0.1.0/src/pulse/mcp/client.py +215 -0
  49. pulse_coding_agent-0.1.0/src/pulse/mcp/local_tools.py +105 -0
  50. pulse_coding_agent-0.1.0/src/pulse/memory.py +212 -0
  51. pulse_coding_agent-0.1.0/src/pulse/mutations.py +283 -0
  52. pulse_coding_agent-0.1.0/src/pulse/orchestration/__init__.py +3 -0
  53. pulse_coding_agent-0.1.0/src/pulse/orchestration/orchestrator.py +162 -0
  54. pulse_coding_agent-0.1.0/src/pulse/patch.py +129 -0
  55. pulse_coding_agent-0.1.0/src/pulse/planner/__init__.py +3 -0
  56. pulse_coding_agent-0.1.0/src/pulse/planner/dag_planner.py +85 -0
  57. pulse_coding_agent-0.1.0/src/pulse/planner/execution_loop.py +159 -0
  58. pulse_coding_agent-0.1.0/src/pulse/production.py +235 -0
  59. pulse_coding_agent-0.1.0/src/pulse/provider.py +59 -0
  60. pulse_coding_agent-0.1.0/src/pulse/provider_keys.py +278 -0
  61. pulse_coding_agent-0.1.0/src/pulse/providers/__init__.py +26 -0
  62. pulse_coding_agent-0.1.0/src/pulse/providers/anthropic.py +65 -0
  63. pulse_coding_agent-0.1.0/src/pulse/providers/base.py +251 -0
  64. pulse_coding_agent-0.1.0/src/pulse/providers/deepseek.py +10 -0
  65. pulse_coding_agent-0.1.0/src/pulse/providers/failover.py +32 -0
  66. pulse_coding_agent-0.1.0/src/pulse/providers/gemini.py +66 -0
  67. pulse_coding_agent-0.1.0/src/pulse/providers/groq.py +10 -0
  68. pulse_coding_agent-0.1.0/src/pulse/providers/manager.py +262 -0
  69. pulse_coding_agent-0.1.0/src/pulse/providers/openai.py +40 -0
  70. pulse_coding_agent-0.1.0/src/pulse/providers/openrouter.py +20 -0
  71. pulse_coding_agent-0.1.0/src/pulse/py.typed +1 -0
  72. pulse_coding_agent-0.1.0/src/pulse/reasoning.py +570 -0
  73. pulse_coding_agent-0.1.0/src/pulse/refactor/__init__.py +3 -0
  74. pulse_coding_agent-0.1.0/src/pulse/refactor/impact_analyzer.py +44 -0
  75. pulse_coding_agent-0.1.0/src/pulse/repository.py +209 -0
  76. pulse_coding_agent-0.1.0/src/pulse/rpc.py +249 -0
  77. pulse_coding_agent-0.1.0/src/pulse/rule_synthesizer.py +54 -0
  78. pulse_coding_agent-0.1.0/src/pulse/runtime.py +217 -0
  79. pulse_coding_agent-0.1.0/src/pulse/safety/__init__.py +3 -0
  80. pulse_coding_agent-0.1.0/src/pulse/safety/safety_manager.py +97 -0
  81. pulse_coding_agent-0.1.0/src/pulse/sandbox/SECURITY.md +57 -0
  82. pulse_coding_agent-0.1.0/src/pulse/sandbox/__init__.py +57 -0
  83. pulse_coding_agent-0.1.0/src/pulse/sandbox/api.py +594 -0
  84. pulse_coding_agent-0.1.0/src/pulse/sandbox/audit.py +153 -0
  85. pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/__init__.py +7 -0
  86. pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/base.py +72 -0
  87. pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/docker.py +498 -0
  88. pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/host.py +140 -0
  89. pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/remote.py +224 -0
  90. pulse_coding_agent-0.1.0/src/pulse/sandbox/errors.py +106 -0
  91. pulse_coding_agent-0.1.0/src/pulse/sandbox/filesystem.py +476 -0
  92. pulse_coding_agent-0.1.0/src/pulse/sandbox/git_safe.py +50 -0
  93. pulse_coding_agent-0.1.0/src/pulse/sandbox/lifecycle.py +88 -0
  94. pulse_coding_agent-0.1.0/src/pulse/sandbox/network.py +205 -0
  95. pulse_coding_agent-0.1.0/src/pulse/sandbox/path_validator.py +280 -0
  96. pulse_coding_agent-0.1.0/src/pulse/sandbox/policy.py +209 -0
  97. pulse_coding_agent-0.1.0/src/pulse/sandbox/process.py +331 -0
  98. pulse_coding_agent-0.1.0/src/pulse/sandbox/project.py +158 -0
  99. pulse_coding_agent-0.1.0/src/pulse/sandbox/python_safe.py +62 -0
  100. pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/__init__.py +1 -0
  101. pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/client.py +389 -0
  102. pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/models.py +167 -0
  103. pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/protocol.py +65 -0
  104. pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/server.py +984 -0
  105. pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/worker.py +175 -0
  106. pulse_coding_agent-0.1.0/src/pulse/sandbox/resources.py +236 -0
  107. pulse_coding_agent-0.1.0/src/pulse/sandbox/secrets.py +241 -0
  108. pulse_coding_agent-0.1.0/src/pulse/session_manager.py +365 -0
  109. pulse_coding_agent-0.1.0/src/pulse/software_engineer.py +189 -0
  110. pulse_coding_agent-0.1.0/src/pulse/storage.py +140 -0
  111. pulse_coding_agent-0.1.0/src/pulse/streaming.py +385 -0
  112. pulse_coding_agent-0.1.0/src/pulse/subprocesses.py +79 -0
  113. pulse_coding_agent-0.1.0/src/pulse/task_manager.py +2005 -0
  114. pulse_coding_agent-0.1.0/src/pulse/telemetry/__init__.py +25 -0
  115. pulse_coding_agent-0.1.0/src/pulse/telemetry/cost_tracker.py +95 -0
  116. pulse_coding_agent-0.1.0/src/pulse/telemetry/logger.py +110 -0
  117. pulse_coding_agent-0.1.0/src/pulse/tool_policy.py +197 -0
  118. pulse_coding_agent-0.1.0/src/pulse/tool_registry.py +163 -0
  119. pulse_coding_agent-0.1.0/src/pulse/tools.py +372 -0
  120. pulse_coding_agent-0.1.0/src/pulse/verification.py +118 -0
  121. pulse_coding_agent-0.1.0/tests/conftest.py +38 -0
  122. pulse_coding_agent-0.1.0/tests/test_agent_manager.py +173 -0
  123. pulse_coding_agent-0.1.0/tests/test_architecture_contracts.py +109 -0
  124. pulse_coding_agent-0.1.0/tests/test_auth.py +227 -0
  125. pulse_coding_agent-0.1.0/tests/test_ci.py +59 -0
  126. pulse_coding_agent-0.1.0/tests/test_cli_entrypoint.py +90 -0
  127. pulse_coding_agent-0.1.0/tests/test_cli_flow.py +139 -0
  128. pulse_coding_agent-0.1.0/tests/test_cli_ui.py +55 -0
  129. pulse_coding_agent-0.1.0/tests/test_context.py +458 -0
  130. pulse_coding_agent-0.1.0/tests/test_conversation_manager.py +287 -0
  131. pulse_coding_agent-0.1.0/tests/test_core_agent.py +56 -0
  132. pulse_coding_agent-0.1.0/tests/test_correlation.py +69 -0
  133. pulse_coding_agent-0.1.0/tests/test_dag_and_impact.py +88 -0
  134. pulse_coding_agent-0.1.0/tests/test_docker_release_gate.py +30 -0
  135. pulse_coding_agent-0.1.0/tests/test_edits.py +59 -0
  136. pulse_coding_agent-0.1.0/tests/test_episodic_rules.py +82 -0
  137. pulse_coding_agent-0.1.0/tests/test_eval_harness.py +90 -0
  138. pulse_coding_agent-0.1.0/tests/test_execution_loop_failover.py +65 -0
  139. pulse_coding_agent-0.1.0/tests/test_git.py +33 -0
  140. pulse_coding_agent-0.1.0/tests/test_interactive.py +158 -0
  141. pulse_coding_agent-0.1.0/tests/test_mcp.py +102 -0
  142. pulse_coding_agent-0.1.0/tests/test_memory.py +31 -0
  143. pulse_coding_agent-0.1.0/tests/test_mutations.py +40 -0
  144. pulse_coding_agent-0.1.0/tests/test_orchestrator_safety.py +43 -0
  145. pulse_coding_agent-0.1.0/tests/test_patch.py +96 -0
  146. pulse_coding_agent-0.1.0/tests/test_planner.py +86 -0
  147. pulse_coding_agent-0.1.0/tests/test_production.py +167 -0
  148. pulse_coding_agent-0.1.0/tests/test_provider.py +62 -0
  149. pulse_coding_agent-0.1.0/tests/test_provider_e2e.py +60 -0
  150. pulse_coding_agent-0.1.0/tests/test_provider_manager.py +142 -0
  151. pulse_coding_agent-0.1.0/tests/test_provider_system.py +58 -0
  152. pulse_coding_agent-0.1.0/tests/test_public_cli.py +274 -0
  153. pulse_coding_agent-0.1.0/tests/test_reasoning.py +222 -0
  154. pulse_coding_agent-0.1.0/tests/test_release_artifacts.py +75 -0
  155. pulse_coding_agent-0.1.0/tests/test_release_evals.py +57 -0
  156. pulse_coding_agent-0.1.0/tests/test_release_metadata.py +65 -0
  157. pulse_coding_agent-0.1.0/tests/test_release_workflows.py +42 -0
  158. pulse_coding_agent-0.1.0/tests/test_remote_reconciliation.py +143 -0
  159. pulse_coding_agent-0.1.0/tests/test_repository.py +50 -0
  160. pulse_coding_agent-0.1.0/tests/test_rpc.py +73 -0
  161. pulse_coding_agent-0.1.0/tests/test_runtime.py +49 -0
  162. pulse_coding_agent-0.1.0/tests/test_sandbox.py +30 -0
  163. pulse_coding_agent-0.1.0/tests/test_sandbox_cow_adversarial.py +112 -0
  164. pulse_coding_agent-0.1.0/tests/test_sandbox_cow_crash.py +227 -0
  165. pulse_coding_agent-0.1.0/tests/test_sandbox_cow_hard_crash.py +160 -0
  166. pulse_coding_agent-0.1.0/tests/test_sandbox_lifecycle_recovery.py +143 -0
  167. pulse_coding_agent-0.1.0/tests/test_sandbox_phase1.py +171 -0
  168. pulse_coding_agent-0.1.0/tests/test_sandbox_phase2.py +85 -0
  169. pulse_coding_agent-0.1.0/tests/test_sandbox_phase3.py +151 -0
  170. pulse_coding_agent-0.1.0/tests/test_sandbox_phase4.py +72 -0
  171. pulse_coding_agent-0.1.0/tests/test_sandbox_phase5.py +103 -0
  172. pulse_coding_agent-0.1.0/tests/test_sandbox_phase7_network.py +219 -0
  173. pulse_coding_agent-0.1.0/tests/test_sandbox_phase8_secrets.py +241 -0
  174. pulse_coding_agent-0.1.0/tests/test_sandbox_r2_security.py +486 -0
  175. pulse_coding_agent-0.1.0/tests/test_sandbox_remote_auth.py +60 -0
  176. pulse_coding_agent-0.1.0/tests/test_sandbox_remote_security.py +36 -0
  177. pulse_coding_agent-0.1.0/tests/test_sandbox_resource_bombs.py +78 -0
  178. pulse_coding_agent-0.1.0/tests/test_sandbox_security.py +849 -0
  179. pulse_coding_agent-0.1.0/tests/test_sbom.py +54 -0
  180. pulse_coding_agent-0.1.0/tests/test_security_audit_regressions.py +324 -0
  181. pulse_coding_agent-0.1.0/tests/test_session_manager.py +125 -0
  182. pulse_coding_agent-0.1.0/tests/test_software_engineer.py +140 -0
  183. pulse_coding_agent-0.1.0/tests/test_storage.py +111 -0
  184. pulse_coding_agent-0.1.0/tests/test_streaming.py +199 -0
  185. pulse_coding_agent-0.1.0/tests/test_subprocesses.py +80 -0
  186. pulse_coding_agent-0.1.0/tests/test_task_execution_durability.py +194 -0
  187. pulse_coding_agent-0.1.0/tests/test_task_manager.py +238 -0
  188. pulse_coding_agent-0.1.0/tests/test_task_manager_concurrency.py +280 -0
  189. pulse_coding_agent-0.1.0/tests/test_task_manager_crash.py +253 -0
  190. pulse_coding_agent-0.1.0/tests/test_task_manager_lease_execution.py +507 -0
  191. pulse_coding_agent-0.1.0/tests/test_task_manager_migration.py +53 -0
  192. pulse_coding_agent-0.1.0/tests/test_telemetry.py +88 -0
  193. pulse_coding_agent-0.1.0/tests/test_tool_policy.py +134 -0
  194. pulse_coding_agent-0.1.0/tests/test_tool_registry.py +52 -0
  195. pulse_coding_agent-0.1.0/tests/test_verification.py +57 -0
  196. pulse_coding_agent-0.1.0/uv.lock +1353 -0
@@ -0,0 +1,39 @@
1
+ OPENROUTER_API_KEY=replace_me
2
+ GEMINI_API_KEY=replace_me
3
+ OPENAI_API_KEY=replace_me
4
+
5
+ AGENT_PROVIDER=openrouter
6
+ AGENT_FALLBACK_PROVIDER=gemini
7
+ AGENT_MODEL=qwen/qwen3-coder
8
+ AGENT_MAX_TOKENS=8192
9
+
10
+ PULSE_MAX_SESSION_TOKENS=100000
11
+ PULSE_MAX_SESSION_COST=1.00
12
+
13
+ # Google OAuth 2.0 ("Continue with Google")
14
+ # Create credentials at: https://console.cloud.google.com/apis/credentials
15
+ # Application type: Web application
16
+ # Authorized redirect URIs: http://localhost:8080
17
+ GOOGLE_CLIENT_ID=replace_me
18
+ GOOGLE_CLIENT_SECRET=replace_me
19
+ GOOGLE_REDIRECT_URI=http://localhost:8080
20
+
21
+ # Remote-sandbox client. Uncomment both values to prefer remote execution;
22
+ # local Docker/Podman is the secure fallback when the endpoint is unavailable.
23
+ # PULSE_REMOTE_URL=wss://sandbox.example.com
24
+ # PULSE_REMOTE_TOKEN=replace_with_a_random_32_character_token
25
+ # PULSE_TLS_CERT=/absolute/path/to/client.crt
26
+ # PULSE_TLS_KEY=/absolute/path/to/client.key
27
+ # PULSE_TLS_CA=/absolute/path/to/ca.crt
28
+
29
+ # Dedicated remote-worker server. Use a random token with at least 32 characters.
30
+ # Non-loopback workers also require all three mTLS paths.
31
+ # PULSE_REMOTE_HOST=127.0.0.1
32
+ # PULSE_REMOTE_PORT=8080
33
+ # PULSE_REMOTE_TOKEN=replace_with_a_random_32_character_token
34
+ # PULSE_REMOTE_WORKSPACE_ROOT=/var/lib/pulse/workspaces
35
+ # PULSE_REMOTE_DB=/var/lib/pulse/executions.sqlite3
36
+ # PULSE_REMOTE_MAX_CONCURRENCY=10
37
+ # PULSE_REMOTE_RETENTION_HOURS=24
38
+ # The worker process uses the same TLS variable names with its server
39
+ # certificate, key, and trusted client CA.
@@ -0,0 +1,82 @@
1
+ # Secrets and machine-specific configuration
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+ *.pem
6
+ *.key
7
+ *.p12
8
+ *.pfx
9
+ *.crt
10
+ *.cer
11
+ credentials.json
12
+ service-account*.json
13
+ secrets*.json
14
+
15
+ # Python environments, bytecode, and tooling caches
16
+ .venv/
17
+ .audit-wheel-venv*/
18
+ venv/
19
+ env/
20
+ ENV/
21
+ __pycache__/
22
+ *.py[cod]
23
+ *$py.class
24
+ .pytest_cache/
25
+ .mypy_cache/
26
+ .ruff_cache/
27
+ .tox/
28
+ .nox/
29
+ .hypothesis/
30
+ .coverage
31
+ .coverage.*
32
+ htmlcov/
33
+
34
+ # Python packaging and build output
35
+ build/
36
+ dist/
37
+ *.egg-info/
38
+ *.egg
39
+ pip-wheel-metadata/
40
+
41
+ # Local data, logs, and editor/OS files
42
+ .agent/logs/
43
+ .agent/repository-index.json
44
+ .agent/provider.json
45
+ .agent/*.sqlite3-shm
46
+ .agent/*.sqlite3-wal
47
+ *.log
48
+ *.sqlite
49
+ *.sqlite3
50
+ *.db
51
+ .idea/
52
+ .vscode/
53
+ .DS_Store
54
+ Thumbs.db
55
+
56
+ # JavaScript dependencies (if used by future tooling)
57
+ node_modules/
58
+
59
+ # Auth session and token files — never commit these
60
+ .agent/.pulse-session.json
61
+ .agent/.pulse-auth-session.json
62
+ .agent/pulse-auth.sqlite3
63
+
64
+ # Pulse agent workspace default
65
+ .sandbox/
66
+ .pulse/
67
+
68
+ # Local release/debug artifacts
69
+ coverage.json
70
+ release-metadata/
71
+ fetch_logs.py
72
+ get_logs.py
73
+ gh/
74
+ gh.zip
75
+ patch_tm.py
76
+ pytest_output*.txt
77
+ run_adversarial_audit.py
78
+ run_linux_tests.py
79
+ runs.json
80
+ server_log.txt
81
+ vscode-extension/out/
82
+ vscode-extension/*.vsix
@@ -0,0 +1,119 @@
1
+ # Pulse Architecture Contract
2
+
3
+ ## Purpose
4
+
5
+ Pulse is a permissioned coding agent. Its architecture is designed so that a
6
+ model response cannot bypass policy, durable state, verification, or execution
7
+ isolation by importing a convenient lower-level implementation.
8
+
9
+ ## Layer Direction
10
+
11
+ Dependencies point inward. A layer may depend only on the layer beneath it or
12
+ on a protocol/model owned by a lower layer.
13
+
14
+ ```text
15
+ CLI / RPC
16
+ -> Orchestration and agent workflow
17
+ -> Planning, tools, verification, task coordination
18
+ -> Domain contracts and durable state
19
+ -> Providers | Sandbox backends | storage adapters | telemetry adapters
20
+ ```
21
+
22
+ ### Layer responsibilities
23
+
24
+ | Layer | Owns | Must not own |
25
+ | --- | --- | --- |
26
+ | CLI and RPC | Input/output, presentation, API compatibility | Policy decisions, direct provider calls, database writes |
27
+ | Orchestration and agent workflow | Prompt lifecycle, plan execution, cancellation propagation | Shell execution, persistence implementation, credential handling |
28
+ | Planning, tools, verification | Typed intent, scoped plans, approval requests, evidence collection | Provider transport and sandbox implementation details |
29
+ | Task coordination | Durable task lifecycle, leases, checkpoints, fencing, recovery | UI behavior and provider-specific reasoning |
30
+ | Sandbox | Policy enforcement, isolated execution, artifacts, execution lifecycle | Agent planning and provider selection |
31
+ | Providers | Model request/response translation and normalized errors | Tool authorization, filesystem access, task lifecycle mutation |
32
+ | Storage and telemetry adapters | Persistence and observation mechanics | Business-policy decisions |
33
+
34
+ ## Domain Contracts
35
+
36
+ The following contracts are the stable integration points. New behavior must
37
+ extend one of them rather than coupling across layers.
38
+
39
+ - **Task:** durable user-visible unit of work, identified by `Task.id`.
40
+ - **Lease fence:** `(owner_id, lease_epoch)` capability required to mutate a
41
+ running task.
42
+ - **Checkpoint:** durable resumable state belonging to a task and step.
43
+ - **Task event:** append-only lifecycle observation for UI, audit, and metrics.
44
+ - **Sandbox execution:** isolated command attempt identified by an execution
45
+ ID, with policy, result, artifact, and terminal reason.
46
+ - **Remote execution:** remote sandbox attempt with an execution ID persisted
47
+ against the task before work starts.
48
+ - **Tool call:** typed, policy-authorized operation with validated input and a
49
+ structured result/error.
50
+ - **Approval:** explicit user authorization linked to the requested action and
51
+ its scope.
52
+ - **Mutation:** a reversible workspace change with before/after evidence.
53
+
54
+ ## Task Lifecycle Contract
55
+
56
+ `TaskStatus` is persisted in SQLite and is authoritative after restart.
57
+
58
+ ```text
59
+ PENDING -> QUEUED -> RUNNING -> COMPLETED
60
+ | | -> FAILED -> QUEUED (bounded retry)
61
+ | | -> PAUSED -> QUEUED
62
+ | | -> CANCELLED
63
+ | `-> RECOVERY_PENDING
64
+ `-> CANCELLED
65
+
66
+ RECOVERY_PENDING -> QUEUED | COMPLETED | FAILED
67
+ ```
68
+
69
+ ### Lifecycle invariants
70
+
71
+ 1. Only a worker holding the current unexpired lease fence may mutate a
72
+ `RUNNING` task.
73
+ 2. Recovery first persists `RECOVERY_PENDING`; it never retries an ambiguous
74
+ remote outcome automatically.
75
+ 3. A live recorded local owner PID blocks requeue unless that executor
76
+ acknowledges termination. Absence from another process's in-memory registry
77
+ is not evidence that the executor stopped.
78
+ 4. `COMPLETED`, `FAILED`, and `CANCELLED` clear active ownership. A completed
79
+ result is immutable except through an explicit new task/retry workflow.
80
+ 5. `RemoteTaskExecutor` obtains the attempt ID from `TaskManager` before sandbox
81
+ submission and passes it as the backend execution ID. Recovery reconciles
82
+ that exact ID, not a generated replacement.
83
+
84
+ ## Sandbox Lifecycle Contract
85
+
86
+ Sandbox execution uses the `SandboxExecution` state machine:
87
+
88
+ ```text
89
+ CREATED -> STARTING -> RUNNING -> COMPLETING -> CLEANING -> FINALIZED
90
+ | |
91
+ v v
92
+ STOPPING FAILED -> CLEANING
93
+ |
94
+ v
95
+ RECOVERY_REQUIRED
96
+ ```
97
+
98
+ `RECOVERY_REQUIRED` is terminal and requires explicit operator action. Lack of
99
+ an available secure backend, an unenforceable policy, or an unknown external
100
+ outcome must fail closed.
101
+
102
+ ## Dependency Rules Enforced in Tests
103
+
104
+ - `pulse.core` is domain-only and must not import orchestration, providers,
105
+ sandbox, CLI/RPC, or persistence implementations.
106
+ - `pulse.providers` must not import agent, orchestration, task-manager, or
107
+ sandbox modules.
108
+ - `pulse.sandbox` must not import agent, orchestration, planner, or provider
109
+ modules.
110
+ - `pulse.task_manager` must not import CLI/RPC, agent orchestration, or a
111
+ provider implementation.
112
+
113
+ Exceptions require an architecture decision record and an accompanying
114
+ boundary-test update explaining why the dependency is safe.
115
+
116
+ ## Change Checklist
117
+
118
+ Before merging a behavior change, identify its owning layer, contract,
119
+ lifecycle transition, failure mode, audit signal, and recovery/rollback path.
@@ -0,0 +1,52 @@
1
+ # Changelog
2
+
3
+ All notable changes are recorded here. Pulse follows Semantic Versioning while
4
+ pre-1.0 APIs may change with release notes and migration guidance.
5
+
6
+ ## [Unreleased]
7
+
8
+ ### Added
9
+
10
+ - Post-login BYOK onboarding now guides provider and model selection before
11
+ collecting the selected provider key through hidden terminal input.
12
+ - Provider keys are stored in workspace-scoped native OS credential-vault
13
+ entries, with safe status, rotation, and removal through `pulse keys`.
14
+
15
+ ### Changed
16
+
17
+ - Successful key set or rotation migrates that provider away from a legacy
18
+ plaintext workspace `.env` entry without ever displaying the secret.
19
+
20
+ ## [0.1.0] - 2026-08-29
21
+
22
+ ### Added
23
+
24
+ - Permissioned local coding-agent CLI with repository intelligence, durable
25
+ tasks, conversations, mutation tracking, provider routing, and loopback RPC.
26
+ - Docker and authenticated remote sandbox implementations with policy,
27
+ resource, filesystem, network, secret-redaction, and recovery tests.
28
+ - Configured remote execution is preferred on client machines, with local
29
+ Docker/Podman used as the secure fallback and no implicit host execution.
30
+ - Production doctor, correlation IDs, remote health/readiness endpoints,
31
+ operations/security documentation, and explicit deployment boundaries.
32
+ - Reproducible wheel/source builds, artifact-content verification, clean-install
33
+ smoke tests, cross-platform CI, coverage gate, dependency audit, secret scan,
34
+ OIDC trusted-publishing workflow, release checksums, source manifest, and
35
+ CycloneDX SBOM.
36
+ - Direct application dependencies pinned to the versions exercised by the
37
+ release suite, preventing unreviewed major-version drift at installation.
38
+ - Explicit live-Docker test markers, a single no-skip Docker security gate, and
39
+ stable Windows pytest teardown behavior in hosted CI.
40
+ - Public `version` and secure provider-key rotation commands, simplified OAuth
41
+ login/logout UX, authenticated Google userinfo verification, and literal-safe
42
+ terminal rendering for untrusted text.
43
+ - Non-root Docker overlay export that avoids archive metadata preservation on
44
+ bind mounts, preventing successful sandbox commands from exiting with 125.
45
+
46
+ ### Known limitations
47
+
48
+ - The supported release boundary is local and single-user.
49
+ - Hosted tenancy, centralized observability, and independent multi-tenant
50
+ security validation are outside the supported beta boundary.
51
+ - The VS Code extension is not included in the Python release; it remains
52
+ source-only and evaluation-only, and its legacy stdio transport is unsupported.
@@ -0,0 +1,161 @@
1
+ # Pulse Operations Runbook
2
+
3
+ ## Supported release boundary
4
+
5
+ Version 0.1.0 is a public beta for local, single-user CLI use. The supported
6
+ artifact is the `pulse-coding-agent` Python distribution and its loopback
7
+ JSON-RPC server. The remote worker is available for controlled evaluation but
8
+ is not approved for multi-tenant or unattended production use.
9
+
10
+ The VS Code extension is source-only in this release. It compiles in CI but is
11
+ not published, and its legacy stdio client is not a supported transport.
12
+ The loopback JSON-RPC compatibility contract is major version `1`; additive
13
+ methods and fields may be introduced within `1.x`, while removals or semantic
14
+ changes require a new major version. Clients should negotiate with
15
+ `pulse.protocolVersion` and reject incompatible major versions.
16
+
17
+ ## Preflight
18
+
19
+ From the target project, run:
20
+
21
+ ```text
22
+ pulse doctor --production --target local
23
+ ```
24
+
25
+ Exit code `0` means every blocking local check passed. Exit code `2` means the
26
+ table contains at least one release blocker. Automation should use
27
+ `--json` and inspect the top-level `passed` field.
28
+
29
+ The loopback JSON-RPC server (`pulse-rpc` or `pulse serve`) requires
30
+ `PULSE_RPC_TOKEN` to be a non-placeholder bearer secret of 32 to 512 characters.
31
+ Start it only on loopback and configure the IDE client to send that bearer token
32
+ in the HTTP authorization header.
33
+
34
+ For a controlled remote-worker evaluation, configure absolute durable paths,
35
+ a cryptographically random token, and mTLS, then run:
36
+
37
+ ```text
38
+ pulse doctor --production --target remote --json
39
+ pulse-remote --host 0.0.0.0
40
+ ```
41
+
42
+ The remote doctor requires Docker or Podman, a token of at least 32
43
+ non-placeholder characters, an absolute tenant workspace root, an absolute
44
+ SQLite path, bounded concurrency/retention, and all three mTLS files for a
45
+ non-loopback host. `pulse-remote` enforces the same token policy unless
46
+ `--development` is explicitly used on loopback.
47
+
48
+ ## Health and readiness
49
+
50
+ The remote worker exposes HTTP responses on its WebSocket listener:
51
+
52
+ - `/healthz` reports process liveness.
53
+ - `/readyz` returns `503` until the Docker worker and durable execution store
54
+ have initialized, then returns `200`.
55
+
56
+ On non-loopback deployments the TLS handshake requires a trusted client
57
+ certificate before these endpoints are reachable. Do not expose them directly
58
+ to the public internet.
59
+
60
+ ## State inventory
61
+
62
+ | State | Default location | Backup requirement |
63
+ | --- | --- | --- |
64
+ | Tasks | `.pulse/tasks.sqlite3` or task-manager store | Back up before upgrade |
65
+ | Conversations and memory | `.agent/*.sqlite3` | Back up before upgrade |
66
+ | Sessions | `.pulse/sessions/` | Back up before upgrade |
67
+ | Mutation/audit/telemetry logs | `.agent/logs/` | Retain according to project policy; logs can contain source snapshots |
68
+ | Remote execution store | `PULSE_REMOTE_DB` | Durable volume and periodic SQLite backup |
69
+ | Remote tenant workspaces | `PULSE_REMOTE_WORKSPACE_ROOT` | Ephemeral; do not treat as the source of record |
70
+
71
+ Never copy a live SQLite database file without coordinating its WAL. Use the
72
+ bundled online backup operation:
73
+
74
+ ```text
75
+ python -m pulse.storage backup SOURCE.sqlite3 BACKUP.sqlite3
76
+ ```
77
+
78
+ Verify backups with `PRAGMA integrity_check;`, encrypt them, and test restore
79
+ on a separate path. Pulse validates every backup before returning. With all
80
+ Pulse processes stopped, restore using:
81
+
82
+ ```text
83
+ python -m pulse.storage restore BACKUP.sqlite3 SOURCE.sqlite3 --confirm-stopped
84
+ ```
85
+
86
+ Operators still own scheduling, encryption, and retention.
87
+
88
+ ## Upgrade and migration
89
+
90
+ 1. Stop Pulse and remote workers; allow active executions to finish or record
91
+ them for reconciliation.
92
+ 2. Back up every store in the state inventory and record the running Pulse
93
+ version and artifact SHA-256.
94
+ 3. Install the new wheel into a new environment; do not overwrite the known
95
+ good environment.
96
+ 4. Run `pulse doctor --production`, then the artifact entry-point smoke tests.
97
+ 5. Start one canary workspace. Confirm health/readiness, task recovery, audit
98
+ output, and provider access before broader rollout.
99
+
100
+ Every supported SQLite store records `PRAGMA user_version`. Migrations run in
101
+ an immediate transaction, create an online pre-migration backup for an existing
102
+ schema, reject databases newer than the running binary, and roll back on an
103
+ error. Task schema is v3, remote execution is v2, and conversation, episodic,
104
+ and long-term memory stores are v1.
105
+
106
+ Pulse is an application distribution, so its direct runtime dependencies are
107
+ pinned to the versions exercised by CI and recorded in the release SBOM.
108
+ Upgrades to those pins require a new Pulse release and the complete release
109
+ gate; do not loosen them in a production environment.
110
+
111
+ ## Rollback
112
+
113
+ 1. Stop the failing process. Do not automatically replay executions with an
114
+ unknown external outcome.
115
+ 2. Reinstall the previous wheel by exact version or SHA-256-verified artifact.
116
+ 3. Restore the pre-upgrade database backup only if the older version cannot
117
+ read the migrated store. Preserve the failed database for investigation.
118
+ 4. Restart on loopback, run the production doctor, and reconcile
119
+ `RECOVERY_PENDING` or remote `UNKNOWN` executions manually.
120
+
121
+ PyPI releases are immutable. A bad public release must be yanked, not replaced;
122
+ publish a new patch version after verification.
123
+
124
+ ## Credential rotation
125
+
126
+ 1. Generate a new random remote token and distribute it through the secret
127
+ manager, never through Git or command-line history.
128
+ 2. During a bounded overlap window, configure old and new tokens as a
129
+ comma-separated set, restart the worker, and move clients to the new token.
130
+ 3. Remove the old token and restart again. Check redacted audit logs for failed
131
+ uses of the retired credential.
132
+ 4. Rotate mTLS certificates and provider/OAuth credentials at their issuers if
133
+ exposure is possible.
134
+
135
+ ## Incident response
136
+
137
+ Contain the worker, revoke credentials, preserve the execution database and
138
+ redacted logs, and quarantine ambiguous tasks. Do not paste raw model output,
139
+ source snapshots, access tokens, or tenant artifacts into tickets. Record the
140
+ release SHA, correlation ID, task ID, remote execution ID, and mutation
141
+ transaction ID. See `SECURITY.md` and `src/pulse/sandbox/SECURITY.md` for the
142
+ threat boundary.
143
+
144
+ ## Release procedure
145
+
146
+ 1. Update `CHANGELOG.md`; make version values agree in `pyproject.toml` and
147
+ `pulse.__version__`.
148
+ 2. Run the full local release verification and push the commits.
149
+ 3. Wait for required CI checks on the release commit, including live Docker
150
+ security tests.
151
+ 4. Confirm the protected `public-beta` and `pypi` environments, provider secret,
152
+ and PyPI trusted-publisher mapping are configured.
153
+ 5. Push tag `vX.Y.Z`. Do not manually create the GitHub Release.
154
+ 6. The protected tag workflow rebuilds and verifies the source, runs the live
155
+ provider and no-skip Docker security gates, publishes to PyPI through OIDC,
156
+ then creates the GitHub Release. It attaches SHA-256 checksums, a
157
+ source-bound manifest, evaluation evidence, and a CycloneDX SBOM.
158
+
159
+ The `public-beta` environment requires `OPENAI_API_KEY` and may set
160
+ `PULSE_E2E_MODEL`. The `pypi` environment must match the trusted publisher for
161
+ `.github/workflows/release.yml`.
@@ -0,0 +1,211 @@
1
+ Metadata-Version: 2.5
2
+ Name: pulse-coding-agent
3
+ Version: 0.1.0
4
+ Summary: Permissioned coding-agent CLI with durable planning and isolated execution.
5
+ Project-URL: Homepage, https://github.com/Roastedpotato21/pulse
6
+ Project-URL: Repository, https://github.com/Roastedpotato21/pulse
7
+ Project-URL: Issues, https://github.com/Roastedpotato21/pulse/issues
8
+ Project-URL: Changelog, https://github.com/Roastedpotato21/pulse/blob/master/CHANGELOG.md
9
+ Project-URL: Security, https://github.com/Roastedpotato21/pulse/security/policy
10
+ Keywords: ai,coding-agent,developer-tools,sandbox
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development
21
+ Requires-Python: <3.14,>=3.11
22
+ Requires-Dist: httpx==0.28.1
23
+ Requires-Dist: keyring==25.7.0
24
+ Requires-Dist: openai==2.44.0
25
+ Requires-Dist: prompt-toolkit==3.0.52
26
+ Requires-Dist: python-dotenv==1.2.2
27
+ Requires-Dist: rich==15.0.0
28
+ Requires-Dist: typer==0.26.8
29
+ Requires-Dist: websockets==16.1
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Pulse
33
+
34
+ Pulse is a permissioned coding-agent CLI for working on software repositories.
35
+ It combines repository-aware planning, durable task state, explicit mutation
36
+ controls, sandboxed command execution, provider routing, audit trails, and cost
37
+ tracking in one Python package.
38
+
39
+ > **Public beta — 0.1.0:** Pulse is supported for controlled, local,
40
+ > single-user use. The remote worker and VS Code extension are included for
41
+ > evaluation and development, but they are not supported as multi-tenant or
42
+ > unattended production services.
43
+
44
+ ## Requirements
45
+
46
+ - Python 3.11, 3.12, or 3.13
47
+ - An API key for the model provider you choose
48
+ - Docker or Podman for local isolated execution, or access to a configured
49
+ Pulse remote worker
50
+
51
+ ## Install
52
+
53
+ Install the first beta from PyPI:
54
+
55
+ ```bash
56
+ uv tool install pulse-coding-agent==0.1.0
57
+ ```
58
+
59
+ Alternatively, use `pipx install pulse-coding-agent==0.1.0` or install it in a
60
+ dedicated virtual environment with `pip`.
61
+
62
+ ## Quick start
63
+
64
+ Run these commands from the repository you want Pulse to work on:
65
+
66
+ ```bash
67
+ pulse login
68
+ pulse doctor --production --target local
69
+ pulse ask "Explain this repository and identify the highest-risk missing test"
70
+ ```
71
+
72
+ After Google login, Pulse guides provider selection, model selection, and hidden
73
+ BYOK entry. New provider keys are stored in the native OS credential vault.
74
+ Credentials can also be supplied through environment variables such as `OPENAI_API_KEY`,
75
+ `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or `OPENROUTER_API_KEY`. Do not commit a
76
+ populated `.env` file.
77
+
78
+ To run commands without installing Docker on the client workstation, configure
79
+ a remote worker:
80
+
81
+ ```text
82
+ PULSE_REMOTE_URL=wss://sandbox.example.com
83
+ PULSE_REMOTE_TOKEN=<random token of at least 32 characters>
84
+ PULSE_TLS_CERT=/absolute/path/to/client.crt
85
+ PULSE_TLS_KEY=/absolute/path/to/client.key
86
+ PULSE_TLS_CA=/absolute/path/to/ca.crt
87
+ ```
88
+
89
+ When those variables are set, Pulse tries the remote sandbox first and uses a
90
+ local Docker/Podman engine only as a secure fallback. The remote worker host
91
+ still requires Docker or Podman; execution never silently falls back to the
92
+ client host.
93
+
94
+ Before allowing mutations or shell execution, review the proposed operation and
95
+ its permission prompt. Treat model output, tool arguments, and repository
96
+ content as untrusted input.
97
+
98
+ ## What the beta includes
99
+
100
+ - Repository indexing and context-aware conversations
101
+ - Durable plans, tasks, sessions, episodic memory, and recovery state
102
+ - Permission-gated file mutations with transactional rollback
103
+ - Host, Docker, Podman, and authenticated remote sandbox backends
104
+ - Filesystem, network, resource, timeout, and secret-redaction policies
105
+ - Multi-provider model routing and usage/cost accounting
106
+ - Loopback JSON-RPC integration through `pulse-rpc` or `pulse serve`
107
+ - Production preflight checks, structured audit events, and correlation IDs
108
+
109
+ The package installs three entry points:
110
+
111
+ ```text
112
+ pulse Interactive CLI
113
+ pulse-rpc Loopback JSON-RPC server
114
+ pulse-remote Evaluation-only remote sandbox worker
115
+ ```
116
+
117
+ Use `pulse --help` for the current command surface and command-specific help.
118
+ `pulse-rpc` and `pulse serve` require a strong `PULSE_RPC_TOKEN` bearer secret
119
+ and must stay bound to loopback.
120
+
121
+ ### Interactive shell
122
+
123
+ Run `pulse` without arguments for the responsive project shell. Natural-language
124
+ input goes to the agent; prefix any regular CLI command with `/` to run it in the
125
+ same session, such as `/status`, `/keys list`, or `/chat switch ID`. Completions
126
+ appear as you type and are always generated from the public CLI parser.
127
+
128
+ - `Tab` or `Ctrl-Space`: open/accept command completion
129
+ - `Up`/`Down`: navigate history; `Ctrl-R`: search history
130
+ - `Alt-Enter`: insert a newline; `Enter`: submit
131
+ - `Ctrl-C`: clear the current input; on an empty prompt, exit
132
+ - `/help`, `/clear`, and `/exit`: shell controls
133
+
134
+ History is stored locally in the Git-ignored `.pulse/history` file.
135
+
136
+ ### Account and provider keys
137
+
138
+ ```bash
139
+ pulse version
140
+ pulse login
141
+ pulse auth-status
142
+ pulse whoami
143
+ pulse logout
144
+ pulse keys
145
+ pulse keys list
146
+ pulse keys set openai
147
+ pulse keys rotate openai
148
+ pulse keys remove openai
149
+ ```
150
+
151
+ `pulse keys` opens the status and rotation manager. Set and rotate operations
152
+ prompt with hidden input; provider keys are never accepted as command-line
153
+ arguments or printed back to the terminal. New keys are stored in a
154
+ workspace-scoped entry in the native OS credential vault. Existing `.env` keys
155
+ remain readable for compatibility and are removed for that provider after a
156
+ successful vault-backed set or rotation. Environment variables and external
157
+ secret managers remain supported as fallback sources.
158
+
159
+ ## Supported boundary
160
+
161
+ The 0.1.0 beta supports the local CLI and loopback RPC server for one trusted
162
+ user on one workstation. Pulse does not claim a security boundary between
163
+ mutually untrusted tenants. Do not expose `pulse-rpc` or `pulse-remote` directly
164
+ to the public internet.
165
+
166
+ The remote worker requires authenticated transport, durable configuration, and
167
+ container isolation. It remains evaluation-only until tenant isolation,
168
+ centralized observability, load testing, disaster-recovery exercises, and an
169
+ independent security review are complete. The VS Code extension is source-only
170
+ and is not part of the Python distribution.
171
+
172
+ Pulse sends prompts and selected repository context to the configured model
173
+ provider. Data handling therefore also depends on that provider's terms and
174
+ settings. Pulse itself does not include product analytics or telemetry export
175
+ in this beta.
176
+
177
+ ## Development
178
+
179
+ Clone the repository and create the locked development environment:
180
+
181
+ ```bash
182
+ uv sync --locked
183
+ uv run pulse --help
184
+ ```
185
+
186
+ Run the local quality gates:
187
+
188
+ ```bash
189
+ uv run ruff check src tests scripts
190
+ uv run mypy
191
+ uv run pytest tests/ -k "not sandbox" --cov=pulse --cov-report=term-missing --cov-fail-under=54
192
+ uv build
193
+ uv run python scripts/verify_release_artifacts.py dist --expected-version 0.1.0
194
+ ```
195
+
196
+ Docker security tests require a working Docker daemon and are enforced by the
197
+ hosted release workflow. See [OPERATIONS.md](OPERATIONS.md) for release and
198
+ rollback procedures.
199
+
200
+ ## Documentation
201
+
202
+ - [Architecture](ARCHITECTURE.md)
203
+ - [Operations and releases](OPERATIONS.md)
204
+ - [Security policy](SECURITY.md)
205
+ - [Sandbox security boundary](src/pulse/sandbox/SECURITY.md)
206
+ - [Privacy policy](PRIVACY.md)
207
+ - [Changelog](CHANGELOG.md)
208
+
209
+ To report a vulnerability, use GitHub private vulnerability reporting instead
210
+ of a public issue. General defects and beta feedback belong in the
211
+ [issue tracker](https://github.com/Roastedpotato21/pulse/issues).