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.
- pulse_coding_agent-0.1.0/.env.example +39 -0
- pulse_coding_agent-0.1.0/.gitignore +82 -0
- pulse_coding_agent-0.1.0/ARCHITECTURE.md +119 -0
- pulse_coding_agent-0.1.0/CHANGELOG.md +52 -0
- pulse_coding_agent-0.1.0/OPERATIONS.md +161 -0
- pulse_coding_agent-0.1.0/PKG-INFO +211 -0
- pulse_coding_agent-0.1.0/PRIVACY.md +66 -0
- pulse_coding_agent-0.1.0/README.md +180 -0
- pulse_coding_agent-0.1.0/SECURITY.md +30 -0
- pulse_coding_agent-0.1.0/agent.config.json +25 -0
- pulse_coding_agent-0.1.0/evals/provider-live-v1.json +19 -0
- pulse_coding_agent-0.1.0/evals/release-v1.json +54 -0
- pulse_coding_agent-0.1.0/pyproject.toml +101 -0
- pulse_coding_agent-0.1.0/scripts/__init__.py +1 -0
- pulse_coding_agent-0.1.0/scripts/finalize_sbom.py +67 -0
- pulse_coding_agent-0.1.0/scripts/generate_release_metadata.py +88 -0
- pulse_coding_agent-0.1.0/scripts/run_docker_release_tests.py +69 -0
- pulse_coding_agent-0.1.0/scripts/run_provider_e2e.py +97 -0
- pulse_coding_agent-0.1.0/scripts/run_release_evals.py +87 -0
- pulse_coding_agent-0.1.0/scripts/verify_release_artifacts.py +191 -0
- pulse_coding_agent-0.1.0/src/pulse/__init__.py +5 -0
- pulse_coding_agent-0.1.0/src/pulse/__main__.py +4 -0
- pulse_coding_agent-0.1.0/src/pulse/agent.py +270 -0
- pulse_coding_agent-0.1.0/src/pulse/agent_manager.py +335 -0
- pulse_coding_agent-0.1.0/src/pulse/audit.py +70 -0
- pulse_coding_agent-0.1.0/src/pulse/auth.py +670 -0
- pulse_coding_agent-0.1.0/src/pulse/ci/github_client.py +66 -0
- pulse_coding_agent-0.1.0/src/pulse/ci/runner.py +28 -0
- pulse_coding_agent-0.1.0/src/pulse/cli.py +1075 -0
- pulse_coding_agent-0.1.0/src/pulse/cli_ui.py +977 -0
- pulse_coding_agent-0.1.0/src/pulse/config.py +167 -0
- pulse_coding_agent-0.1.0/src/pulse/context.py +960 -0
- pulse_coding_agent-0.1.0/src/pulse/conversations/__init__.py +8 -0
- pulse_coding_agent-0.1.0/src/pulse/conversations/manager.py +312 -0
- pulse_coding_agent-0.1.0/src/pulse/core/agent.py +188 -0
- pulse_coding_agent-0.1.0/src/pulse/core/planner.py +105 -0
- pulse_coding_agent-0.1.0/src/pulse/core/protocols.py +37 -0
- pulse_coding_agent-0.1.0/src/pulse/edits.py +65 -0
- pulse_coding_agent-0.1.0/src/pulse/episodic.py +93 -0
- pulse_coding_agent-0.1.0/src/pulse/eval/__init__.py +8 -0
- pulse_coding_agent-0.1.0/src/pulse/eval/trajectory_logger.py +91 -0
- pulse_coding_agent-0.1.0/src/pulse/eval/verifier.py +133 -0
- pulse_coding_agent-0.1.0/src/pulse/execution/__init__.py +5 -0
- pulse_coding_agent-0.1.0/src/pulse/execution/remote_task.py +76 -0
- pulse_coding_agent-0.1.0/src/pulse/git.py +162 -0
- pulse_coding_agent-0.1.0/src/pulse/interactive.py +234 -0
- pulse_coding_agent-0.1.0/src/pulse/mcp/__init__.py +4 -0
- pulse_coding_agent-0.1.0/src/pulse/mcp/client.py +215 -0
- pulse_coding_agent-0.1.0/src/pulse/mcp/local_tools.py +105 -0
- pulse_coding_agent-0.1.0/src/pulse/memory.py +212 -0
- pulse_coding_agent-0.1.0/src/pulse/mutations.py +283 -0
- pulse_coding_agent-0.1.0/src/pulse/orchestration/__init__.py +3 -0
- pulse_coding_agent-0.1.0/src/pulse/orchestration/orchestrator.py +162 -0
- pulse_coding_agent-0.1.0/src/pulse/patch.py +129 -0
- pulse_coding_agent-0.1.0/src/pulse/planner/__init__.py +3 -0
- pulse_coding_agent-0.1.0/src/pulse/planner/dag_planner.py +85 -0
- pulse_coding_agent-0.1.0/src/pulse/planner/execution_loop.py +159 -0
- pulse_coding_agent-0.1.0/src/pulse/production.py +235 -0
- pulse_coding_agent-0.1.0/src/pulse/provider.py +59 -0
- pulse_coding_agent-0.1.0/src/pulse/provider_keys.py +278 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/__init__.py +26 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/anthropic.py +65 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/base.py +251 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/deepseek.py +10 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/failover.py +32 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/gemini.py +66 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/groq.py +10 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/manager.py +262 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/openai.py +40 -0
- pulse_coding_agent-0.1.0/src/pulse/providers/openrouter.py +20 -0
- pulse_coding_agent-0.1.0/src/pulse/py.typed +1 -0
- pulse_coding_agent-0.1.0/src/pulse/reasoning.py +570 -0
- pulse_coding_agent-0.1.0/src/pulse/refactor/__init__.py +3 -0
- pulse_coding_agent-0.1.0/src/pulse/refactor/impact_analyzer.py +44 -0
- pulse_coding_agent-0.1.0/src/pulse/repository.py +209 -0
- pulse_coding_agent-0.1.0/src/pulse/rpc.py +249 -0
- pulse_coding_agent-0.1.0/src/pulse/rule_synthesizer.py +54 -0
- pulse_coding_agent-0.1.0/src/pulse/runtime.py +217 -0
- pulse_coding_agent-0.1.0/src/pulse/safety/__init__.py +3 -0
- pulse_coding_agent-0.1.0/src/pulse/safety/safety_manager.py +97 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/SECURITY.md +57 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/__init__.py +57 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/api.py +594 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/audit.py +153 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/__init__.py +7 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/base.py +72 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/docker.py +498 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/host.py +140 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/backend/remote.py +224 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/errors.py +106 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/filesystem.py +476 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/git_safe.py +50 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/lifecycle.py +88 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/network.py +205 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/path_validator.py +280 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/policy.py +209 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/process.py +331 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/project.py +158 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/python_safe.py +62 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/__init__.py +1 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/client.py +389 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/models.py +167 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/protocol.py +65 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/server.py +984 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/remote/worker.py +175 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/resources.py +236 -0
- pulse_coding_agent-0.1.0/src/pulse/sandbox/secrets.py +241 -0
- pulse_coding_agent-0.1.0/src/pulse/session_manager.py +365 -0
- pulse_coding_agent-0.1.0/src/pulse/software_engineer.py +189 -0
- pulse_coding_agent-0.1.0/src/pulse/storage.py +140 -0
- pulse_coding_agent-0.1.0/src/pulse/streaming.py +385 -0
- pulse_coding_agent-0.1.0/src/pulse/subprocesses.py +79 -0
- pulse_coding_agent-0.1.0/src/pulse/task_manager.py +2005 -0
- pulse_coding_agent-0.1.0/src/pulse/telemetry/__init__.py +25 -0
- pulse_coding_agent-0.1.0/src/pulse/telemetry/cost_tracker.py +95 -0
- pulse_coding_agent-0.1.0/src/pulse/telemetry/logger.py +110 -0
- pulse_coding_agent-0.1.0/src/pulse/tool_policy.py +197 -0
- pulse_coding_agent-0.1.0/src/pulse/tool_registry.py +163 -0
- pulse_coding_agent-0.1.0/src/pulse/tools.py +372 -0
- pulse_coding_agent-0.1.0/src/pulse/verification.py +118 -0
- pulse_coding_agent-0.1.0/tests/conftest.py +38 -0
- pulse_coding_agent-0.1.0/tests/test_agent_manager.py +173 -0
- pulse_coding_agent-0.1.0/tests/test_architecture_contracts.py +109 -0
- pulse_coding_agent-0.1.0/tests/test_auth.py +227 -0
- pulse_coding_agent-0.1.0/tests/test_ci.py +59 -0
- pulse_coding_agent-0.1.0/tests/test_cli_entrypoint.py +90 -0
- pulse_coding_agent-0.1.0/tests/test_cli_flow.py +139 -0
- pulse_coding_agent-0.1.0/tests/test_cli_ui.py +55 -0
- pulse_coding_agent-0.1.0/tests/test_context.py +458 -0
- pulse_coding_agent-0.1.0/tests/test_conversation_manager.py +287 -0
- pulse_coding_agent-0.1.0/tests/test_core_agent.py +56 -0
- pulse_coding_agent-0.1.0/tests/test_correlation.py +69 -0
- pulse_coding_agent-0.1.0/tests/test_dag_and_impact.py +88 -0
- pulse_coding_agent-0.1.0/tests/test_docker_release_gate.py +30 -0
- pulse_coding_agent-0.1.0/tests/test_edits.py +59 -0
- pulse_coding_agent-0.1.0/tests/test_episodic_rules.py +82 -0
- pulse_coding_agent-0.1.0/tests/test_eval_harness.py +90 -0
- pulse_coding_agent-0.1.0/tests/test_execution_loop_failover.py +65 -0
- pulse_coding_agent-0.1.0/tests/test_git.py +33 -0
- pulse_coding_agent-0.1.0/tests/test_interactive.py +158 -0
- pulse_coding_agent-0.1.0/tests/test_mcp.py +102 -0
- pulse_coding_agent-0.1.0/tests/test_memory.py +31 -0
- pulse_coding_agent-0.1.0/tests/test_mutations.py +40 -0
- pulse_coding_agent-0.1.0/tests/test_orchestrator_safety.py +43 -0
- pulse_coding_agent-0.1.0/tests/test_patch.py +96 -0
- pulse_coding_agent-0.1.0/tests/test_planner.py +86 -0
- pulse_coding_agent-0.1.0/tests/test_production.py +167 -0
- pulse_coding_agent-0.1.0/tests/test_provider.py +62 -0
- pulse_coding_agent-0.1.0/tests/test_provider_e2e.py +60 -0
- pulse_coding_agent-0.1.0/tests/test_provider_manager.py +142 -0
- pulse_coding_agent-0.1.0/tests/test_provider_system.py +58 -0
- pulse_coding_agent-0.1.0/tests/test_public_cli.py +274 -0
- pulse_coding_agent-0.1.0/tests/test_reasoning.py +222 -0
- pulse_coding_agent-0.1.0/tests/test_release_artifacts.py +75 -0
- pulse_coding_agent-0.1.0/tests/test_release_evals.py +57 -0
- pulse_coding_agent-0.1.0/tests/test_release_metadata.py +65 -0
- pulse_coding_agent-0.1.0/tests/test_release_workflows.py +42 -0
- pulse_coding_agent-0.1.0/tests/test_remote_reconciliation.py +143 -0
- pulse_coding_agent-0.1.0/tests/test_repository.py +50 -0
- pulse_coding_agent-0.1.0/tests/test_rpc.py +73 -0
- pulse_coding_agent-0.1.0/tests/test_runtime.py +49 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox.py +30 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_cow_adversarial.py +112 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_cow_crash.py +227 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_cow_hard_crash.py +160 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_lifecycle_recovery.py +143 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase1.py +171 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase2.py +85 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase3.py +151 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase4.py +72 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase5.py +103 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase7_network.py +219 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_phase8_secrets.py +241 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_r2_security.py +486 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_remote_auth.py +60 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_remote_security.py +36 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_resource_bombs.py +78 -0
- pulse_coding_agent-0.1.0/tests/test_sandbox_security.py +849 -0
- pulse_coding_agent-0.1.0/tests/test_sbom.py +54 -0
- pulse_coding_agent-0.1.0/tests/test_security_audit_regressions.py +324 -0
- pulse_coding_agent-0.1.0/tests/test_session_manager.py +125 -0
- pulse_coding_agent-0.1.0/tests/test_software_engineer.py +140 -0
- pulse_coding_agent-0.1.0/tests/test_storage.py +111 -0
- pulse_coding_agent-0.1.0/tests/test_streaming.py +199 -0
- pulse_coding_agent-0.1.0/tests/test_subprocesses.py +80 -0
- pulse_coding_agent-0.1.0/tests/test_task_execution_durability.py +194 -0
- pulse_coding_agent-0.1.0/tests/test_task_manager.py +238 -0
- pulse_coding_agent-0.1.0/tests/test_task_manager_concurrency.py +280 -0
- pulse_coding_agent-0.1.0/tests/test_task_manager_crash.py +253 -0
- pulse_coding_agent-0.1.0/tests/test_task_manager_lease_execution.py +507 -0
- pulse_coding_agent-0.1.0/tests/test_task_manager_migration.py +53 -0
- pulse_coding_agent-0.1.0/tests/test_telemetry.py +88 -0
- pulse_coding_agent-0.1.0/tests/test_tool_policy.py +134 -0
- pulse_coding_agent-0.1.0/tests/test_tool_registry.py +52 -0
- pulse_coding_agent-0.1.0/tests/test_verification.py +57 -0
- 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).
|