stcode 0.0.1a0__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.
- stcode-0.0.1a0/.dockerignore +10 -0
- stcode-0.0.1a0/.gitignore +238 -0
- stcode-0.0.1a0/CLAUDE.md +313 -0
- stcode-0.0.1a0/Dockerfile +65 -0
- stcode-0.0.1a0/LICENSE +201 -0
- stcode-0.0.1a0/PKG-INFO +229 -0
- stcode-0.0.1a0/README.md +189 -0
- stcode-0.0.1a0/docs/architecture/agent-loop.md +230 -0
- stcode-0.0.1a0/docs/architecture/cli.md +62 -0
- stcode-0.0.1a0/docs/architecture/configuration.md +197 -0
- stcode-0.0.1a0/docs/architecture/daemon.md +286 -0
- stcode-0.0.1a0/docs/architecture/harness.md +278 -0
- stcode-0.0.1a0/docs/architecture/index.md +169 -0
- stcode-0.0.1a0/docs/architecture/mcp.md +118 -0
- stcode-0.0.1a0/docs/architecture/providers.md +178 -0
- stcode-0.0.1a0/docs/architecture/session.md +176 -0
- stcode-0.0.1a0/docs/architecture/supervisor.md +87 -0
- stcode-0.0.1a0/docs/architecture/team.md +337 -0
- stcode-0.0.1a0/docs/architecture/tracing.md +57 -0
- stcode-0.0.1a0/docs/contributing/releasing.md +63 -0
- stcode-0.0.1a0/docs/contributing/testing.md +151 -0
- stcode-0.0.1a0/docs/contributing/workflow.md +101 -0
- stcode-0.0.1a0/docs/decisions/0001-tool-search.md +121 -0
- stcode-0.0.1a0/docs/decisions/0002-file-and-image-input.md +95 -0
- stcode-0.0.1a0/docs/decisions/0003-what-the-tui-owns.md +124 -0
- stcode-0.0.1a0/docs/decisions/0004-what-a-remote-client-may-change.md +99 -0
- stcode-0.0.1a0/docs/decisions/0005-an-agent-is-a-config-file.md +102 -0
- stcode-0.0.1a0/docs/decisions/0006-cli-and-core-are-separate-programs.md +82 -0
- stcode-0.0.1a0/docs/decisions/0007-cli-layers.md +44 -0
- stcode-0.0.1a0/docs/decisions/index.md +33 -0
- stcode-0.0.1a0/docs/getting-started/configuration.md +104 -0
- stcode-0.0.1a0/docs/getting-started/installation.md +52 -0
- stcode-0.0.1a0/docs/getting-started/quickstart.md +77 -0
- stcode-0.0.1a0/docs/guide/approval-modes.md +44 -0
- stcode-0.0.1a0/docs/guide/mcp.md +88 -0
- stcode-0.0.1a0/docs/guide/repl.md +35 -0
- stcode-0.0.1a0/docs/guide/sessions.md +50 -0
- stcode-0.0.1a0/docs/guide/shapes.md +84 -0
- stcode-0.0.1a0/docs/guide/skills.md +52 -0
- stcode-0.0.1a0/docs/guide/tools.md +58 -0
- stcode-0.0.1a0/docs/guide/tracing.md +71 -0
- stcode-0.0.1a0/docs/guide/tui.md +98 -0
- stcode-0.0.1a0/docs/index.md +28 -0
- stcode-0.0.1a0/docs/sdk/custom-tools.md +89 -0
- stcode-0.0.1a0/docs/sdk/daemon-protocol.md +174 -0
- stcode-0.0.1a0/docs/sdk/embedding.md +100 -0
- stcode-0.0.1a0/docs/sdk/streaming.md +75 -0
- stcode-0.0.1a0/docs/teams/roles.md +57 -0
- stcode-0.0.1a0/docs/teams/setup.md +81 -0
- stcode-0.0.1a0/docs/teams/workflow.md +64 -0
- stcode-0.0.1a0/examples/agents/ba.toml +64 -0
- stcode-0.0.1a0/examples/agents/backend-dev.toml +59 -0
- stcode-0.0.1a0/examples/agents/devops.toml +58 -0
- stcode-0.0.1a0/examples/agents/frontend-dev.toml +56 -0
- stcode-0.0.1a0/mkdocs.yml +111 -0
- stcode-0.0.1a0/pyproject.toml +77 -0
- stcode-0.0.1a0/pytest.ini +14 -0
- stcode-0.0.1a0/stcode/__init__.py +10 -0
- stcode-0.0.1a0/stcode/cli/__init__.py +9 -0
- stcode-0.0.1a0/stcode/cli/bootstrap.py +70 -0
- stcode-0.0.1a0/stcode/cli/labels.py +621 -0
- stcode-0.0.1a0/stcode/cli/logic/__init__.py +0 -0
- stcode-0.0.1a0/stcode/cli/logic/commands.py +36 -0
- stcode-0.0.1a0/stcode/cli/logic/completion.py +43 -0
- stcode-0.0.1a0/stcode/cli/logic/connection.py +46 -0
- stcode-0.0.1a0/stcode/cli/logic/requests.py +18 -0
- stcode-0.0.1a0/stcode/cli/logic/sessions.py +67 -0
- stcode-0.0.1a0/stcode/cli/logic/settings.py +35 -0
- stcode-0.0.1a0/stcode/cli/logic/state.py +43 -0
- stcode-0.0.1a0/stcode/cli/logic/workspace.py +17 -0
- stcode-0.0.1a0/stcode/cli/main.py +290 -0
- stcode-0.0.1a0/stcode/cli/models.py +61 -0
- stcode-0.0.1a0/stcode/cli/services/__init__.py +0 -0
- stcode-0.0.1a0/stcode/cli/services/client.py +393 -0
- stcode-0.0.1a0/stcode/cli/services/launcher.py +159 -0
- stcode-0.0.1a0/stcode/cli/services/paths.py +18 -0
- stcode-0.0.1a0/stcode/cli/services/preferences.py +107 -0
- stcode-0.0.1a0/stcode/cli/ui/__init__.py +0 -0
- stcode-0.0.1a0/stcode/cli/ui/app.py +136 -0
- stcode-0.0.1a0/stcode/cli/ui/app.tcss +3 -0
- stcode-0.0.1a0/stcode/cli/ui/components/__init__.py +0 -0
- stcode-0.0.1a0/stcode/cli/ui/components/banner.py +78 -0
- stcode-0.0.1a0/stcode/cli/ui/components/cards.py +229 -0
- stcode-0.0.1a0/stcode/cli/ui/components/prompt.py +225 -0
- stcode-0.0.1a0/stcode/cli/ui/components/status.py +95 -0
- stcode-0.0.1a0/stcode/cli/ui/components/transcript/__init__.py +51 -0
- stcode-0.0.1a0/stcode/cli/ui/components/transcript/entries.py +232 -0
- stcode-0.0.1a0/stcode/cli/ui/components/transcript/formatting.py +188 -0
- stcode-0.0.1a0/stcode/cli/ui/components/transcript/view.py +101 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/__init__.py +0 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/chat/__init__.py +0 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/chat/chat.tcss +12 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/chat/presenter.py +187 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/chat/screen.py +682 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/connect.py +126 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/connect.tcss +49 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/dialog.tcss +40 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/sessions.py +105 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/settings.py +137 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/settings.tcss +69 -0
- stcode-0.0.1a0/stcode/cli/ui/screens/trust.py +50 -0
- stcode-0.0.1a0/stcode/cli/ui/theme.py +221 -0
- stcode-0.0.1a0/stcode/core/__main__.py +7 -0
- stcode-0.0.1a0/stcode/core/agent/__init__.py +41 -0
- stcode-0.0.1a0/stcode/core/agent/agent.py +651 -0
- stcode-0.0.1a0/stcode/core/agent/events.py +97 -0
- stcode-0.0.1a0/stcode/core/agent/supervisor.py +226 -0
- stcode-0.0.1a0/stcode/core/agent/task.py +120 -0
- stcode-0.0.1a0/stcode/core/common/__init__.py +21 -0
- stcode-0.0.1a0/stcode/core/common/compat.py +27 -0
- stcode-0.0.1a0/stcode/core/common/ids.py +43 -0
- stcode-0.0.1a0/stcode/core/common/tools.py +50 -0
- stcode-0.0.1a0/stcode/core/common/trace.py +406 -0
- stcode-0.0.1a0/stcode/core/common/truncate.py +76 -0
- stcode-0.0.1a0/stcode/core/configs.py +490 -0
- stcode-0.0.1a0/stcode/core/daemon/__init__.py +32 -0
- stcode-0.0.1a0/stcode/core/daemon/autonomy.py +71 -0
- stcode-0.0.1a0/stcode/core/daemon/main.py +126 -0
- stcode-0.0.1a0/stcode/core/daemon/protocol.py +499 -0
- stcode-0.0.1a0/stcode/core/daemon/runner.py +359 -0
- stcode-0.0.1a0/stcode/core/daemon/server.py +682 -0
- stcode-0.0.1a0/stcode/core/daemon/workspace.py +88 -0
- stcode-0.0.1a0/stcode/core/harness/__init__.py +81 -0
- stcode-0.0.1a0/stcode/core/harness/approvals.py +85 -0
- stcode-0.0.1a0/stcode/core/harness/context.py +260 -0
- stcode-0.0.1a0/stcode/core/harness/errors.py +40 -0
- stcode-0.0.1a0/stcode/core/harness/harness.py +417 -0
- stcode-0.0.1a0/stcode/core/harness/mcp.py +530 -0
- stcode-0.0.1a0/stcode/core/harness/outputs.py +99 -0
- stcode-0.0.1a0/stcode/core/harness/prompts/__init__.py +138 -0
- stcode-0.0.1a0/stcode/core/harness/prompts/execute.py +51 -0
- stcode-0.0.1a0/stcode/core/harness/prompts/plan.py +57 -0
- stcode-0.0.1a0/stcode/core/harness/prompts/sections.py +238 -0
- stcode-0.0.1a0/stcode/core/harness/skills/__init__.py +30 -0
- stcode-0.0.1a0/stcode/core/harness/skills/loader.py +247 -0
- stcode-0.0.1a0/stcode/core/harness/tools/__init__.py +111 -0
- stcode-0.0.1a0/stcode/core/harness/tools/base.py +640 -0
- stcode-0.0.1a0/stcode/core/harness/tools/files.py +276 -0
- stcode-0.0.1a0/stcode/core/harness/tools/interact.py +72 -0
- stcode-0.0.1a0/stcode/core/harness/tools/registry.py +113 -0
- stcode-0.0.1a0/stcode/core/harness/tools/repl.py +97 -0
- stcode-0.0.1a0/stcode/core/harness/tools/schema.py +186 -0
- stcode-0.0.1a0/stcode/core/harness/tools/search.py +356 -0
- stcode-0.0.1a0/stcode/core/harness/tools/shell.py +372 -0
- stcode-0.0.1a0/stcode/core/harness/tools/skill.py +66 -0
- stcode-0.0.1a0/stcode/core/harness/tools/todo.py +62 -0
- stcode-0.0.1a0/stcode/core/harness/tools/web.py +163 -0
- stcode-0.0.1a0/stcode/core/providers/__init__.py +31 -0
- stcode-0.0.1a0/stcode/core/providers/anthropic_claude.py +243 -0
- stcode-0.0.1a0/stcode/core/providers/base.py +73 -0
- stcode-0.0.1a0/stcode/core/providers/gateway.py +267 -0
- stcode-0.0.1a0/stcode/core/providers/google_gemini.py +225 -0
- stcode-0.0.1a0/stcode/core/providers/openai_gpt.py +250 -0
- stcode-0.0.1a0/stcode/core/providers/registry.py +46 -0
- stcode-0.0.1a0/stcode/core/providers/types.py +148 -0
- stcode-0.0.1a0/stcode/core/repl/__init__.py +19 -0
- stcode-0.0.1a0/stcode/core/repl/_worker.py +179 -0
- stcode-0.0.1a0/stcode/core/repl/client.py +374 -0
- stcode-0.0.1a0/stcode/core/session/__init__.py +39 -0
- stcode-0.0.1a0/stcode/core/session/session.py +493 -0
- stcode-0.0.1a0/stcode/core/team/__init__.py +38 -0
- stcode-0.0.1a0/stcode/core/team/mailbox.py +249 -0
- stcode-0.0.1a0/stcode/core/team/tools.py +145 -0
- stcode-0.0.1a0/stcode.example.toml +104 -0
- stcode-0.0.1a0/tests/cli/architecture_test.py +63 -0
- stcode-0.0.1a0/tests/cli/labels_test.py +71 -0
- stcode-0.0.1a0/tests/cli/logic/completion_test.py +112 -0
- stcode-0.0.1a0/tests/cli/logic/connection_test.py +31 -0
- stcode-0.0.1a0/tests/cli/logic/sessions_test.py +57 -0
- stcode-0.0.1a0/tests/cli/logic/workflows_test.py +63 -0
- stcode-0.0.1a0/tests/cli/main_test.py +51 -0
- stcode-0.0.1a0/tests/cli/services/launcher_test.py +127 -0
- stcode-0.0.1a0/tests/cli/services/preferences_test.py +122 -0
- stcode-0.0.1a0/tests/cli/ui/components/prompt_test.py +49 -0
- stcode-0.0.1a0/tests/cli/ui/components/transcript_test.py +160 -0
- stcode-0.0.1a0/tests/cli/ui/theme_test.py +95 -0
- stcode-0.0.1a0/tests/conftest.py +86 -0
- stcode-0.0.1a0/tests/core/agent_test.py +821 -0
- stcode-0.0.1a0/tests/core/common_test.py +80 -0
- stcode-0.0.1a0/tests/core/configs_test.py +186 -0
- stcode-0.0.1a0/tests/core/daemon_main_test.py +94 -0
- stcode-0.0.1a0/tests/core/daemon_test.py +1158 -0
- stcode-0.0.1a0/tests/core/harness_test.py +1048 -0
- stcode-0.0.1a0/tests/core/providers_test.py +642 -0
- stcode-0.0.1a0/tests/core/repl_test.py +192 -0
- stcode-0.0.1a0/tests/core/session_test.py +362 -0
- stcode-0.0.1a0/tests/core/team_test.py +435 -0
- stcode-0.0.1a0/tests/core/trace_test.py +365 -0
- stcode-0.0.1a0/tests/core/workspace_discovery_test.py +34 -0
- stcode-0.0.1a0/tests/driving.py +40 -0
- stcode-0.0.1a0/tests/fakes.py +408 -0
- stcode-0.0.1a0/tests/fixtures/workspace/.agents/skills/db-migrations/SKILL.md +9 -0
- stcode-0.0.1a0/tests/fixtures/workspace/.agents/skills/release-notes/SKILL.md +9 -0
- stcode-0.0.1a0/tests/fixtures/workspace/AGENTS.md +4 -0
- stcode-0.0.1a0/tests/fixtures/workspace/README.md +6 -0
- stcode-0.0.1a0/tests/fixtures/workspace/config.toml +43 -0
- stcode-0.0.1a0/tests/fixtures/workspace/mcp_server.py +34 -0
- stcode-0.0.1a0/tests/fixtures/workspace/src/app.py +13 -0
- stcode-0.0.1a0/tests/fixtures/workspace/src/util.py +12 -0
- stcode-0.0.1a0/tests/integration/conftest.py +67 -0
- stcode-0.0.1a0/tests/integration/conversation_test.py +214 -0
- stcode-0.0.1a0/tests/integration/trace_live_test.py +114 -0
- stcode-0.0.1a0/tests/integration/tui_test.py +1164 -0
- stcode-0.0.1a0/tests/integration/workspace_test.py +131 -0
- stcode-0.0.1a0/uv.lock +3869 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
.python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
219
|
+
|
|
220
|
+
# Scratch workspace for main.py, the hand-run agent smoke test.
|
|
221
|
+
temp/
|
|
222
|
+
|
|
223
|
+
# Agents config
|
|
224
|
+
.agents/
|
|
225
|
+
.claude/
|
|
226
|
+
|
|
227
|
+
# ...except the test fixture workspace, which is a *checked-in* project the
|
|
228
|
+
# integration tests mount as the agent's cwd. Its dot-directories are the point.
|
|
229
|
+
!tests/fixtures/workspace/.agents/
|
|
230
|
+
!tests/fixtures/workspace/.agents/**
|
|
231
|
+
|
|
232
|
+
# Temporatory ignore the notebooks folder, only contains
|
|
233
|
+
# testing notebook for the agent, ignore to vanish from Claude Code
|
|
234
|
+
# and avoid accidentially pushed
|
|
235
|
+
notebooks/
|
|
236
|
+
|
|
237
|
+
# The built documentation site. `mkdocs build` output; never committed.
|
|
238
|
+
/site/
|
stcode-0.0.1a0/CLAUDE.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
The index. What this project is, what it bets on, the rules that are not negotiable, and
|
|
4
|
+
where the detail lives.
|
|
5
|
+
|
|
6
|
+
**Before you claim anything works:** `uv run pytest`.
|
|
7
|
+
**Before you write code:** §6, *How a change is made*.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. What this is
|
|
12
|
+
|
|
13
|
+
`stcode` is a **general agent harness, specialised for coding**.
|
|
14
|
+
|
|
15
|
+
The unit of deployment is a **daemon**: a long-lived process holding one agent, speaking
|
|
16
|
+
JSONL over a socket. A TUI is just a client of it. That inversion — daemon first, UI
|
|
17
|
+
second — is what makes the container story real instead of aspirational.
|
|
18
|
+
|
|
19
|
+
One binary, three shapes, no implementation switches between them:
|
|
20
|
+
|
|
21
|
+
| | |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `stcode` | UI + a daemon, started here if none is listening |
|
|
24
|
+
| `stcode --headless` | the daemon alone — what a container runs |
|
|
25
|
+
| `stcode --daemonless` | the UI alone, attached to a daemon elsewhere (`/connect` to move it) |
|
|
26
|
+
|
|
27
|
+
`stcode/cli` and `stcode/core` are **separate programs that never import each other**.
|
|
28
|
+
The daemon is `stcode-daemon`; the UI starts it as a subprocess when nothing is listening
|
|
29
|
+
and speaks to it only over the socket. The daemon alone reads and writes `config.toml`.
|
|
30
|
+
→ [decision 0006](docs/decisions/0006-cli-and-core-are-separate-programs.md)
|
|
31
|
+
|
|
32
|
+
**Two modes, one engine.** `Agent` does not know which mode it is in; the difference is
|
|
33
|
+
which harness is loaded and which tools are injected.
|
|
34
|
+
|
|
35
|
+
| | **Solo** | **Team** |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| Deployment | one daemon on your machine | N containers, each = 1 daemon + 1 agent |
|
|
38
|
+
| Workspace | existing checkout at `cwd`, scope-enforced | agent runs `git clone` itself |
|
|
39
|
+
| Roles | none | BA / frontend-dev / backend-dev / devops … |
|
|
40
|
+
| Coordination | `task` tool (in-process sub-agent) | shared `/team` volume + `find_teammate` / `send_team_message` |
|
|
41
|
+
| Client | TUI over unix socket | TUI/web over TCP; attach and steer mid-run |
|
|
42
|
+
| Approval | human in the loop | `full-auto`, guarded by container detection |
|
|
43
|
+
|
|
44
|
+
**Non-goals.** Not a training harness. Not a reimplementation of MCP. Not feature parity
|
|
45
|
+
with Claude Code. No self-modifying prompts (rule 6).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. The documentation
|
|
50
|
+
|
|
51
|
+
`docs/` is a mkdocs site. `uv run --group docs mkdocs serve` to read it; `mkdocs build`
|
|
52
|
+
is `strict`, so a broken internal link or a page missing from `nav` fails the build.
|
|
53
|
+
|
|
54
|
+
**Usage** — what a user reads.
|
|
55
|
+
|
|
56
|
+
| Section | What it covers |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| [docs/index.md](docs/index.md) | The front door |
|
|
59
|
+
| [getting-started/](docs/getting-started/) | Installation, quickstart, the config keys that matter on day one |
|
|
60
|
+
| [guide/](docs/guide/) | The three shapes, the TUI, approval modes, sessions, tools, skills, MCP, the REPL, tracing |
|
|
61
|
+
| [teams/](docs/teams/) | Setting a team up, roles, how one actually works |
|
|
62
|
+
| [sdk/](docs/sdk/) | Embedding an agent, writing a tool, the daemon protocol |
|
|
63
|
+
| [decisions/](docs/decisions/) | One page per question that could have gone another way |
|
|
64
|
+
| [contributing/](docs/contributing/) | **How a change is made** (§6), testing, releasing |
|
|
65
|
+
|
|
66
|
+
**Architecture** — what a contributor reads before changing something.
|
|
67
|
+
|
|
68
|
+
| Page | What it covers |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| [docs/architecture/index.md](docs/architecture/index.md) | The map: components, the diagram, dependency direction, repository layout |
|
|
71
|
+
| [agent-loop.md](docs/architecture/agent-loop.md) | `Agent` — the turn loop, events, interrupts, steering mid-turn, sub-agents |
|
|
72
|
+
| [harness.md](docs/architecture/harness.md) | Tools, `@tool`, permissions and approval modes, skills, roles, output elision |
|
|
73
|
+
| [providers.md](docs/architecture/providers.md) | `LLMGateway` — difficulty routing, retry, the unified wire format, prompt caching |
|
|
74
|
+
| [session.md](docs/architecture/session.md) | The append-only JSONL transcript, its three readers, and ids |
|
|
75
|
+
| [daemon.md](docs/architecture/daemon.md) | The socket, the protocol, `full-auto`'s container rule |
|
|
76
|
+
| [cli.md](docs/architecture/cli.md) | Client UI, workflow logic, I/O services and screen ownership |
|
|
77
|
+
| [mcp.md](docs/architecture/mcp.md) | MCP servers as *code* rather than as tool definitions |
|
|
78
|
+
| [supervisor.md](docs/architecture/supervisor.md) | Stagnation detection at (almost) zero token cost |
|
|
79
|
+
| [team.md](docs/architecture/team.md) | Containers, roles, the shared volume, git integration — and the evaluation set |
|
|
80
|
+
| [tracing.md](docs/architecture/tracing.md) | Exporting the trajectory via direct HTTP APIs |
|
|
81
|
+
| [configuration.md](docs/architecture/configuration.md) | Every section of `config.toml`, and what reads it |
|
|
82
|
+
| [README.md](README.md) | The repository's front door: install, run, the commands |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 3. The four bets
|
|
87
|
+
|
|
88
|
+
Each is traceable to a measurement. Read the number before removing one.
|
|
89
|
+
|
|
90
|
+
**3.1 MCP tools are code, not tool definitions.** Other agents ship MCP schemas in the
|
|
91
|
+
prompt prefix every turn — 10–30k tokens for three servers, forever. We write them to
|
|
92
|
+
`.stcode/mcp_servers/<server>/<tool>.py` and let the agent `grep` and `import` what it
|
|
93
|
+
needs from the REPL. Anthropic measured the pattern at 150k → 2k tokens; measured here on
|
|
94
|
+
three servers and twelve tools, **9,869 → 0 chars** per turn (`smoke_mcp.py`). →
|
|
95
|
+
[mcp.md](docs/architecture/mcp.md)
|
|
96
|
+
|
|
97
|
+
**3.2 A supervisor watches the trajectory.** NVIDIA AVO hit 100% on ARC-AGI-3 and
|
|
98
|
+
credited system design, naming a supervisor that watches for stagnation. The session
|
|
99
|
+
JSONL is already the trajectory, so ours is just a reader: four heuristics at zero token
|
|
100
|
+
cost, and only a hit spends a `difficulty="low"` call that may answer NONE. The nudge is
|
|
101
|
+
appended as a `user` message, never a system-prompt edit, so caching survives. →
|
|
102
|
+
[supervisor.md](docs/architecture/supervisor.md)
|
|
103
|
+
|
|
104
|
+
**3.3 Agent-to-agent messaging has no protocol.** Containers share a volume, so a message
|
|
105
|
+
is a **file**: `send_team_message` writes JSON into `/team/inbox/<role>/`, and the
|
|
106
|
+
receiver drains its own directory; `find_teammate` reads the cards each agent writes to
|
|
107
|
+
`/team/members/` at start-up. No registry service, no routing table, no N² socket mesh.
|
|
108
|
+
Messages carry `refs` not content — enforced, not requested. →
|
|
109
|
+
[team.md](docs/architecture/team.md)
|
|
110
|
+
|
|
111
|
+
**3.4 Daemon-first, so containerization is not a rewrite.** Detach does not kill the
|
|
112
|
+
agent. Approval and questions are request–response correlated by `execution_id` over the
|
|
113
|
+
same JSONL framing. Transport (`unix` / `tcp`) is configuration, not architecture. →
|
|
114
|
+
[daemon.md](docs/architecture/daemon.md)
|
|
115
|
+
|
|
116
|
+
### Honest comparison
|
|
117
|
+
|
|
118
|
+
| | Claude Code | Cline / Kilo | **stcode** |
|
|
119
|
+
| --- | --- | --- | --- |
|
|
120
|
+
| Tool quality (read/edit/grep/bash) | excellent | good | comparable already |
|
|
121
|
+
| MCP | tool defs per turn | tool defs per turn | as code, 9.9k → 0 chars/turn |
|
|
122
|
+
| Runs headless in a container | partial | no | core design |
|
|
123
|
+
| Multi-agent team across containers | no | no | yes — but see §7 |
|
|
124
|
+
| Stagnation detection | no | no | yes |
|
|
125
|
+
| Observability export (HTTP) | no | no | yes, off by default |
|
|
126
|
+
| Maturity, polish, ecosystem | **far ahead** | ahead | behind, and will stay behind |
|
|
127
|
+
|
|
128
|
+
We are not competing on polish. We are betting on the rows in the middle.
|
|
129
|
+
|
|
130
|
+
### Kept from other agents, and left behind
|
|
131
|
+
|
|
132
|
+
| Kept | Why |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| Exact-string `edit`, not line ranges or diffs | Line numbers go stale; a unique literal matches once or fails loudly |
|
|
135
|
+
| Read-before-write | A refused edit costs one turn; an overwritten unread file costs work that no longer exists |
|
|
136
|
+
| `todo_write` as a context device | Not a real tool. It keeps the plan in the window, and that is enough to earn its place |
|
|
137
|
+
| Elision with head and tail kept | The beginning says what ran, the end says how it went |
|
|
138
|
+
| A fresh process per `bash` call | Stateful shells make every failure irreproducible |
|
|
139
|
+
| Steering a running turn | Delivered at the next tool boundary — the only place a `user` message is legal |
|
|
140
|
+
| Four options on a question | Fits a card above the input, and forces the agent to prune its own list |
|
|
141
|
+
|
|
142
|
+
| Left behind | Why |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| A framework owning the loop (LangChain, LangGraph, CrewAI, AutoGen) | The premise is programmatic control over context and the loop |
|
|
145
|
+
| LLM-summarised tool output | Summarising loses information; eliding does not (rule 1) |
|
|
146
|
+
| MCP definitions in the prompt | The 9,869 → 0 measurement |
|
|
147
|
+
| A lead/orchestrator agent | You dispatch, per role. A `lead` would be one more agent profile |
|
|
148
|
+
| Self-refining prompts | Rule 6, and Prime Agent's promoted cheating skill (§7) |
|
|
149
|
+
| Notebook editing, multi-edit, image input | Deferred, not rejected |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 4. Hard rules
|
|
154
|
+
|
|
155
|
+
Seven. Each exists because violating it produced a specific, known failure.
|
|
156
|
+
|
|
157
|
+
1. **Tool output is elided at its cap, never LLM-summarised.** Summarising loses
|
|
158
|
+
information; eliding does not — *provided the full value is somewhere the model can
|
|
159
|
+
reach*. `Runtime.outputs_reachable` is the single place that decides whether the hint
|
|
160
|
+
may name `tool_out["…"]`, so the promise cannot drift from the fact.
|
|
161
|
+
2. **One agent = one role = one checkout = one merge boundary.** If two agents need to
|
|
162
|
+
write the same file, the roles are split wrong. That is a design error, not a signal
|
|
163
|
+
to add locking.
|
|
164
|
+
3. **`max_depth = 1`.** Sub-agents get neither `task` nor `repl`. Unbounded recursion plus
|
|
165
|
+
no budget is a fork bomb.
|
|
166
|
+
4. **Sessions are append-only JSONL.** Never rewrite history. No branch, no fork, no leaf
|
|
167
|
+
pointer — `cp session.jsonl` is the branching feature.
|
|
168
|
+
5. **`full-auto` without an approver runs only inside a container.** The daemon refuses to
|
|
169
|
+
start otherwise. There is no override flag. This is code (`guard_autonomy`), not a
|
|
170
|
+
warning in a document.
|
|
171
|
+
6. **The agent never edits its own harness.** No `/refine`, no prompt CRUD. Prime Agent
|
|
172
|
+
shipped this and the agent promoted *cheating* into a skill (§7).
|
|
173
|
+
7. **Layers do not reach upward.** Concretely: the gateway emits `MessageStop(usage=…)`
|
|
174
|
+
and the *agent* writes it to the session. A gateway that imports `Session` has taken a
|
|
175
|
+
dependency on its own caller.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 5. Tech stack
|
|
180
|
+
|
|
181
|
+
| Concern | Choice | Why |
|
|
182
|
+
| --- | --- | --- |
|
|
183
|
+
| REPL | plain `python -u` subprocess + JSONL | Persistent namespace, crash isolation, SIGINT, zero dependencies |
|
|
184
|
+
| LLM clients | `anthropic`, `openai`, `google-genai` (async) | One adapter each; normalise the wire format there and nowhere else |
|
|
185
|
+
| Concurrency | `asyncio`, `anyio`, `asyncer` | `gather` for fan-out, `Semaphore` for caps |
|
|
186
|
+
| TUI | `textual` | Streaming render, attach/detach |
|
|
187
|
+
| Schemas | `pydantic` v2 | Signature → JSON Schema for free |
|
|
188
|
+
| CLI | `typer` | |
|
|
189
|
+
| Config | `tomllib` (read) + `tomli-w` (write) | Stdlib is read-only; the UI writes config back |
|
|
190
|
+
| Search | `ripgrep` (pip wheel), `fd` (optional) | The wheel drops `rg` next to the interpreter, so `grep` works on a fresh checkout |
|
|
191
|
+
| Tool schemas | `docstring-parser` | Signature + `Args:` → JSON Schema, described once |
|
|
192
|
+
| MCP | `mcp` (official SDK) | We adapt it; we never reimplement the protocol |
|
|
193
|
+
| Tracing | Direct HTTP JSON with `httpx` | Langfuse and Phoenix; no tracing SDK |
|
|
194
|
+
| Sandbox | Docker | Team mode; also what makes `full-auto` legal (rule 5) |
|
|
195
|
+
| Packaging | `uv` | |
|
|
196
|
+
|
|
197
|
+
**Explicitly not used: LangChain.** Also LangGraph, CrewAI, AutoGen. The premise is
|
|
198
|
+
programmatic control over context and the loop; a framework that owns the loop defeats it.
|
|
199
|
+
|
|
200
|
+
**Knowledge you need that isn't a library:** SSE streaming and tool-call delta
|
|
201
|
+
accumulation; prompt caching (keep the prefix byte-stable); async cancellation and
|
|
202
|
+
graceful shutdown; JSONL framing over sockets and pipes; token counting, when compaction
|
|
203
|
+
lands.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 6. Conventions
|
|
208
|
+
|
|
209
|
+
### How a change is made
|
|
210
|
+
|
|
211
|
+
Six steps, in order. Full version, with the reasoning for each, in
|
|
212
|
+
[docs/contributing/workflow.md](docs/contributing/workflow.md).
|
|
213
|
+
|
|
214
|
+
1. **Analyse the spec, and ask.** Where two readings lead to materially different work,
|
|
215
|
+
ask before building. Where a routine judgement call would do, make it and say so.
|
|
216
|
+
2. **Write the document.** The page a user would read — `docs/guide/` or `docs/sdk/`,
|
|
217
|
+
or the matching `docs/architecture/` page — *before* the test and the code. A
|
|
218
|
+
feature whose page is hard to write is a feature whose shape is wrong, and that
|
|
219
|
+
costs a paragraph here instead of a rewrite three steps later. A question that could
|
|
220
|
+
reasonably have gone another way gets a `docs/decisions/` record instead.
|
|
221
|
+
3. **Write the test.** From the document, not from the implementation. Name it after
|
|
222
|
+
the failure it prevents.
|
|
223
|
+
4. **Implement.** The smallest change that makes the test pass and the document true.
|
|
224
|
+
5. **Run the tests.** `uv run pytest`, before claiming anything works. Still red? Say
|
|
225
|
+
so, with the output.
|
|
226
|
+
6. **Commit.** `area: what changed`, short, with the docs in the same commit.
|
|
227
|
+
|
|
228
|
+
### The rest
|
|
229
|
+
|
|
230
|
+
- Python 3.10+ (CI runs 3.10–3.13; `core/common/compat.py` holds the only two backports), `uv` for everything. `uv run pytest` before claiming anything works.
|
|
231
|
+
- `cli/` never imports `core/`, and `core/` never imports `cli/`. A name both need is
|
|
232
|
+
copied into `cli/models.py`; display copy lives in `cli/labels.py`. A fact that changes when the engine does goes over the
|
|
233
|
+
socket. Settings and environment variables are read in `core/configs.py` and nowhere
|
|
234
|
+
else in `core/`.
|
|
235
|
+
- Type hints mandatory in `core/`. `mypy --strict` on it — installed, and **not yet
|
|
236
|
+
clean**: ~35 errors, mostly provider SDK stubs. Documented in
|
|
237
|
+
[docs/contributing/testing.md](docs/contributing/testing.md) rather than claimed.
|
|
238
|
+
- Tests live in `tests/`: `tests/core/<module>_test.py` for a module's public surface,
|
|
239
|
+
`tests/integration/` for the flows the documentation describes, `tests/fakes.py` for
|
|
240
|
+
the three test doubles, `tests/fixtures/workspace/` for the project they run against.
|
|
241
|
+
Nothing calls a real provider except the two tests marked `live`, deselected by
|
|
242
|
+
default.
|
|
243
|
+
- Every tool has a docstring, because **the docstring is the prompt the model sees**.
|
|
244
|
+
Write it for the model: imperative, concrete, no rationale. Rationale goes in comments.
|
|
245
|
+
- No blocking I/O in the agent loop. If it can take 100 ms, it is `async`. The exception
|
|
246
|
+
is `Session.append` — one line to an open file, deliberately sync.
|
|
247
|
+
- Commit messages: `area: what changed`. Keep them short.
|
|
248
|
+
- **When you change the architecture, update the page in `docs/architecture/` in the same
|
|
249
|
+
commit.** A doc that has drifted from the code is worse than no doc: every agent that
|
|
250
|
+
reads it builds in the wrong direction, and none of them will tell you.
|
|
251
|
+
- A **lazy import that exists only to hide a cycle** is a signal, not a solution: the
|
|
252
|
+
thing being imported is in the wrong place. Move it down to `core/common/` if more
|
|
253
|
+
than one package needs it, or into the one package that does.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## 7. Important notices
|
|
258
|
+
|
|
259
|
+
**Arbitrary code execution.** The agent runs commands and Python with your privileges.
|
|
260
|
+
Rule 5 is the mitigation and it is enforced in `guard_autonomy`, not by discipline.
|
|
261
|
+
|
|
262
|
+
**Multi-agent costs more, not less.** Anthropic measured multi-agent at **~15× the
|
|
263
|
+
tokens** of chat and single-agent at ~4×, with token volume explaining **80% of
|
|
264
|
+
performance variance**. They also list **"most coding tasks"** as a *poor* fit. Team mode
|
|
265
|
+
pays off only when roles work on genuinely separable things, which is why rule 2 draws the
|
|
266
|
+
boundary at the service, not the file.
|
|
267
|
+
|
|
268
|
+
**Latency increases.** Models do not reliably parallelise even when they can. Stream
|
|
269
|
+
progress, or a working session looks hung.
|
|
270
|
+
|
|
271
|
+
**No model is trained on this scaffold.** Expect under-use of `task`. Compensate in its
|
|
272
|
+
docstring: it must force an output format and a scope, because a vaguely-described
|
|
273
|
+
sub-agent is the number one cause of duplicated, off-target work.
|
|
274
|
+
|
|
275
|
+
**Reward hacking is real and documented.** Prime Agent, given a refinement loop, bypassed
|
|
276
|
+
Factorio's rules via RCON and **promoted cheating into a skill** — even when told not to.
|
|
277
|
+
The coding analogue is editing the test to make it pass; hence rule 6. If you revisit it,
|
|
278
|
+
the verifier must be outside the agent's write scope, and any test-file edit during a
|
|
279
|
+
"make the tests pass" task must be flagged.
|
|
280
|
+
|
|
281
|
+
**Debuggability is designed in, not retrofitted.** Agent → tool → sub-agent leaves no
|
|
282
|
+
natural stack trace. The session JSONL *is* the trace — keep every event in it, including
|
|
283
|
+
the ones the model never sees.
|
|
284
|
+
|
|
285
|
+
**Cost visibility.** Every LLM call lands in the session as a `usage` record. One place.
|
|
286
|
+
Do not add a second logger (rule 7); [tracing.md](docs/architecture/tracing.md) is an
|
|
287
|
+
export of that record, not a competitor to it.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 8. Status
|
|
292
|
+
|
|
293
|
+
All ten build steps are done. Each smoke script drives real processes against a real
|
|
294
|
+
model.
|
|
295
|
+
|
|
296
|
+
| Phase | Gate | Evidence |
|
|
297
|
+
| --- | --- | --- |
|
|
298
|
+
| 0 — Shell | `stcode` runs, configures itself, streams a reply | — |
|
|
299
|
+
| 1 — The loop | a two-file change completes end to end with a readable session log | every `smoke_*.py` |
|
|
300
|
+
| 2 — Daemon + client | detach/re-attach mid-run works; `full-auto` refuses on the host | `smoke_daemon.py`, `tests/core/daemon_test.py` |
|
|
301
|
+
| 3 — Token economics | three MCP servers connected, prompt prefix does not grow | `smoke_mcp.py` — 9,869 → 0 chars |
|
|
302
|
+
| 4 — Autonomy | a deliberately looping task is caught and redirected | `smoke_supervisor.py` |
|
|
303
|
+
| 5 — Team | two containers, two roles, one feature shipped through `/team` | `smoke_team.py` — **partly** |
|
|
304
|
+
|
|
305
|
+
**The one open question.** The ~20 team-mode evaluation tasks in
|
|
306
|
+
[team.md](docs/architecture/team.md#the-evaluation-set) are written and **have not been
|
|
307
|
+
run**. Until they are, "does team mode help or merely spend 15× the tokens" is
|
|
308
|
+
unanswered — and §7 says that is a live question, not a rhetorical one. Running them is
|
|
309
|
+
the highest-value thing left.
|
|
310
|
+
|
|
311
|
+
**Later:** compaction with a visible threshold, sessions in a live database, provider
|
|
312
|
+
failover, `written_files` tracking, agent profiles that carry their own tools and MCP
|
|
313
|
+
servers alongside the prompt.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# One image, one config file per agent. An agent profile is a `config.toml` carrying the
|
|
2
|
+
# prompt *and* the settings it runs under, and it is *mounted*, not built in: an agent is
|
|
3
|
+
# a deployment fact, and an image that carried four would make adding a fifth a release.
|
|
4
|
+
#
|
|
5
|
+
# No docker-compose.yml, no k8s manifests. This repo ships an image and the environment
|
|
6
|
+
# contract below; how you bring up N containers is yours, and orchestration opinions do
|
|
7
|
+
# not belong in a Python package.
|
|
8
|
+
#
|
|
9
|
+
# docker build -t stcode .
|
|
10
|
+
# docker run -d --name backend-dev \
|
|
11
|
+
# -v team:/team -v /var/lib/stcode/backend:/workspace \
|
|
12
|
+
# -v ./examples/agents/backend-dev.toml:/config/config.toml:ro \
|
|
13
|
+
# -e STCODE_SANDBOX=1 -e STCODE_TEAM=1 -e ANTHROPIC_API_KEY \
|
|
14
|
+
# -p 7717:7717 stcode
|
|
15
|
+
#
|
|
16
|
+
# stcode --daemonless # then /connect to localhost:7717
|
|
17
|
+
#
|
|
18
|
+
# STCODE_TEAM=1 is what turns team mode on. A profile naming a role is not enough on its
|
|
19
|
+
# own — a role says which agent this is, team mode says a shared volume is mounted.
|
|
20
|
+
|
|
21
|
+
FROM python:3.12-slim
|
|
22
|
+
|
|
23
|
+
# git is not optional here: every role clones from /team/repo.git before writing code.
|
|
24
|
+
# ripgrep arrives as a wheel with the package, so it is not installed twice.
|
|
25
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
26
|
+
git ca-certificates \
|
|
27
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
28
|
+
|
|
29
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
30
|
+
|
|
31
|
+
WORKDIR /app
|
|
32
|
+
|
|
33
|
+
# Dependencies first, so a code change does not re-resolve the whole environment.
|
|
34
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
35
|
+
RUN uv sync --frozen --no-install-project --no-dev
|
|
36
|
+
|
|
37
|
+
COPY stcode ./stcode
|
|
38
|
+
RUN uv sync --frozen --no-dev
|
|
39
|
+
|
|
40
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
41
|
+
PYTHONUNBUFFERED=1 \
|
|
42
|
+
STCODE_CONFIG=/config/config.toml \
|
|
43
|
+
STCODE_SANDBOX=1
|
|
44
|
+
# STCODE_TEAM is deliberately not set: team mode is off until the deployment says so.
|
|
45
|
+
# STCODE_SANDBOX is what makes `full-auto` legal (rule 5). It is set here because this
|
|
46
|
+
# image *is* the container the rule is about — the daemon refuses to start in full-auto
|
|
47
|
+
# anywhere else, and there is no override flag.
|
|
48
|
+
|
|
49
|
+
# Mounts the contract expects:
|
|
50
|
+
# /team shared volume — members/, inbox/, knowledge/, artifacts/, repo.git
|
|
51
|
+
# /workspace where this agent clones; one checkout per container
|
|
52
|
+
# /config this agent's profile, as config.toml, read-only
|
|
53
|
+
VOLUME ["/team", "/workspace"]
|
|
54
|
+
WORKDIR /workspace
|
|
55
|
+
|
|
56
|
+
EXPOSE 7717
|
|
57
|
+
|
|
58
|
+
# The daemon alone, which is the whole point of daemon-first — `stcode-daemon` is the
|
|
59
|
+
# same program `stcode --headless` runs. It prints what it became — workspace, mode,
|
|
60
|
+
# model, config, what it created — and logs every client that connects, because
|
|
61
|
+
# `docker logs` is the only screen it has. It stops cleanly on SIGTERM. Attach a TUI with
|
|
62
|
+
# `stcode --daemonless` and /connect, from anywhere that can reach the port; a
|
|
63
|
+
# containerised daemon takes one client at a time, and accepts no API key over TCP.
|
|
64
|
+
ENTRYPOINT ["stcode-daemon"]
|
|
65
|
+
CMD ["--transport", "tcp", "--host", "0.0.0.0", "--port", "7717"]
|