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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ databases, credentials and migrations. The product uses Core exclusively; it has
Core handlers, storage or scheduling. Qualify public workflows through the same
shared chain; direct native probes establish feasibility only.
- Keep engine-specific types, process management and protocol translation inside
execution adapters. The public API and persistence/application core must not
execution adapters. Native workspace execution must use the declared Environment
directory; a separate native history/configuration directory is not a workspace.
The public API and persistence/application core must not
interpret Parsar product payloads or depend on one engine's native item types.
Prefer maintained upstream SDKs and native execution protocols over a second
hand-written model/tool loop or a general-purpose compatibility framework.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func TestEnvironmentMCPUsesFixedLauncherForNewAndLoadedSessions(t *testing.T) {
}
var params struct {
SessionID string `json:"sessionId"`
Cwd string `json:"cwd"`
MCP []struct {
Name, Command string
Args []string
Expand All @@ -52,6 +53,11 @@ func TestEnvironmentMCPUsesFixedLauncherForNewAndLoadedSessions(t *testing.T) {
if json.Unmarshal(raw, &params) != nil || len(params.MCP) != 2 || params.MCP[0].Name != "oac_workspace" {
t.Fatal("environment MCP displaced workspace tools")
}
cwd, err := os.ReadFile(record + ".cwd")
workspace, pathErr := filepath.EvalSymlinks(req.WorkDir)
if err != nil || pathErr != nil || string(cwd) != workspace || params.Cwd != req.WorkDir {
t.Fatalf("native process and ACP Session must use the declared workspace: process=%q ACP=%q", cwd, params.Cwd)
}
server := params.MCP[1]
executable, _ := os.Executable()
if server.Name != "proof.server" || server.Command != executable || server.Env == nil || len(server.Env) != 0 ||
Expand Down
4 changes: 2 additions & 2 deletions apps/parsar-daemon/internal/agent/mcode/preparation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ func TestPreparedWorkspaceHasOneInputAndOutputOwner(t *testing.T) {
if err != nil || strings.Contains(string(raw), "session/prompt") {
t.Fatalf("preparation consumed input: %q %v", raw, err)
}
if p.session.opts.Dir == r.WorkDir || !strings.HasPrefix(p.session.opts.Dir, p.session.opts.DataDir+string(filepath.Separator)) {
t.Fatal("native cwd is not private")
if p.session.opts.Dir != r.WorkDir || p.session.opts.DataDir == r.WorkDir {
t.Fatal("native cwd must use the workspace without moving Session state")
}
out := make(chan proto.Envelope)
var wg sync.WaitGroup
Expand Down
4 changes: 4 additions & 0 deletions apps/parsar-daemon/internal/agent/mcode/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ func TestMCodeProcess(t *testing.T) {
_, _ = f.WriteString(frame.Method + "\n")
_ = f.Close()
if frame.Method == "session/new" || frame.Method == "session/load" {
cwd, err := os.Getwd()
if err != nil || os.WriteFile(record+".cwd", []byte(cwd), 0600) != nil {
os.Exit(11)
}
if os.WriteFile(record+".session", frame.Params, 0600) != nil {
os.Exit(11)
}
Expand Down
5 changes: 3 additions & 2 deletions apps/parsar-daemon/internal/agent/mcode/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ func prepareWorkspaceOptions(ctx context.Context, c WorkspaceConfig, req proto.P
if err != nil {
return launchOptions{}, err
}
// Reuse public option validation and private Session state provisioning. Native
// cwd remains private; only the internal MCP worker receives the public workspace.
// Reuse public option validation and private Session state provisioning.
// The native process, ACP Session and workspace tools share the declared cwd.
private := req
private.LocalEnvironment, private.WorkDir, private.DisableExecutionEnvironment = nil, "", true
opts, err := prepareOptionsWithSkills(ctx, private, false)
if err != nil {
return opts, err
}
opts.Dir = c.Directory
if len(req.LocalEnvironment.Skills) > 0 {
root := filepath.Join(opts.DataDir, "skills")
if err := os.MkdirAll(root, 0700); err != nil {
Expand Down
98 changes: 52 additions & 46 deletions services/agents-api/deploy/mcode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,18 @@ enrollment and the public protocol remain shared. The image supplies the private
`OAC_RUNTIME_MCODE_WORKSPACE=managed` and companion paths; caller Agent options cannot
change them. Public Files and Artifacts use the common bound workspace helpers.

The native process and ACP Session use a private control directory, while six
original native tools execute against `/workspace` through one trusted MCP bridge
with the daemon user's ordinary permissions and no inner sandbox. MCP is internal
transport here; its presence alone does not enable caller-supplied public MCP servers. Project instructions must be read through the
workspace tools. Native automatic project configuration and diff/undo capture do
not apply to this adapter tool path. Exact native-ID continuation remains
required; recovery without a recorded ID fails closed. Native Bash observations
become public `command_execution` items after command arguments arrive. Their
text output and status are retained; absent native exit code/duration stay unknown.
The private MCP server and file/skill/task utilities are not invented public MCP
or function calls.
The native process, ACP Session and six original native tools use the declared
Environment workspace (`/workspace` in the Docker image). The tools connect
through one trusted MCP bridge with the daemon user's ordinary permissions and
no inner sandbox. MCP is internal transport here; its presence alone does not
enable caller-supplied public MCP servers. Native project discovery uses that
same workspace; adapter-owned configuration and history remain in the private
Session data directory. Exact native-ID continuation remains required; recovery
without a recorded ID fails closed. Native Bash observations become public
`command_execution` items after command arguments arrive. Their text output and
status are retained; absent native exit code/duration stay unknown. The private
MCP server and file/skill/task utilities are not invented public MCP or function
calls.

## Provider configuration

Expand Down Expand Up @@ -87,14 +88,16 @@ mapping; only actual Bash calls become `command_execution`.

## Execution boundaries

Each API Session uses a separate native state directory and cwd. The execution
child inherits only process and model-network essentials; it does not inherit
Core/daemon tokens or arbitrary Node startup configuration. The adapter owns its
native config, instructions and home and disables external skills, delegated work,
web search, builtin file/shell tools, browser tools, mcode-tools and native goals.
The workspace profile uses its tool bridge without sandbox isolation. Tools can
read any local state available to the launching user. The outer Environment owns
managed isolation; daemon network modes do not add another network boundary.
Each API Session uses a separate native state directory. Workspace execution
uses the declared Environment directory; text-only execution uses a private cwd.
The execution child inherits only process and model-network essentials; it does
not inherit Core/daemon tokens or arbitrary Node startup configuration. The
adapter owns its native config, instructions and home and disables external
skills, delegated work, web search, builtin file/shell tools, browser tools,
mcode-tools and native goals. The workspace profile uses its tool bridge without
sandbox isolation. Tools can read any local state available to the launching
user. The outer Environment owns managed isolation; daemon network modes do not
add another network boundary.

Provide system dependencies at image/template build time or on the self-hosted
machine before execution. Runtime does not run apt or sudo or elevate daemon
Expand All @@ -116,9 +119,10 @@ Cancellation waits for process-group exit and output settlement. Public slash
text remains a model message instead of invoking native ACP operator commands.

Cold continuation requires the exact persisted native Session ID and matching
private cwd. Missing/foreign history fails; recovery by guessing an ID from native
session listings is not qualified. Public usage breakdown is unavailable because
native ACP context occupancy and cumulative cost are not per-Turn usage.
workspace cwd (or private cwd for text-only execution). Missing/foreign history
fails; recovery by guessing an ID from native session listings is not qualified.
Public usage breakdown is unavailable because native ACP context occupancy and
cumulative cost are not per-Turn usage.

### Adapter rules

Expand All @@ -144,32 +148,34 @@ later work recovers the same native history in a new owner without replay.
The MiniMax workspace profile builds one CLI from the fixed upstream source and
lockfile through the existing companion packaging path, and connects native
workspace tools through its standard MCP client. The process and native Session
share one private control directory; public workspace files cannot configure that
process or become privileged project instructions. A trusted adapter-owned bridge
runs the original six tool implementations with the launching user's ordinary
permissions. It adds no inner sandbox on any platform. Keep native history bound
to the control directory and Files/Artifacts bound to the public workspace. Core and shared file helpers remain engine
neutral. This internal MCP transport does not admit public MCP configuration.
Record the upstream revision, native admission patch hashes and worker-source
provenance. The bounded patch checks the shared descendant-task limit inside the
existing native SQLite admission transaction before start, without another
scheduler. ACP initialization must acknowledge the applied limit before input.
The native tool catalog selects the same admitted workspace tools for every child,
not only the root's configured profile; this is tool selection, not filesystem
isolation. Only the Session's authorized internal
share the declared workspace directory, including for cold continuation. A
trusted adapter-owned bridge runs the original six tool implementations with the
launching user's ordinary permissions. It adds no inner sandbox on any platform.
Keep native history in the Session data directory and native execution and
Files/Artifacts bound to the same Environment workspace. Core and shared file
helpers remain engine neutral. This internal MCP transport does not admit public
MCP configuration. Record the upstream revision, native admission patch hashes
and worker-source provenance. The bounded patch checks the shared
descendant-task limit inside the existing native SQLite admission transaction
before start, without another scheduler. ACP initialization must acknowledge the
applied limit before input. The native tool catalog selects the same admitted
workspace tools for every child, not only the root's configured profile; this is
tool selection, not filesystem isolation. Only the Session's authorized internal
workspace MCP entry crosses the native child selector; this does not grant
external MCP access. Initialization must acknowledge the admitted tool inventory
before input as well. Subagent reads use the Session's native database; the daemon
does not protect it from other tools running as the same user. Multi-agent
workspace execution installs only the existing authorized workspace MCP entry in
that private native configuration so children inherit the same tools; public MCP
and Environment-origin MCP combinations remain separately qualified. Complete the hosted
[acceptance checklist](../../../../contracts/agents-api/harnesses.md#acceptance-checklist) before enabling
hosted execution. The standalone companion uses its own npm lock; `make check`
runs its lifecycle tests and script checks, while its exact-source Linux build and
native qualification for the actual supported platform and outer deployment
are required when the companion changes. Historical tests of both inner network
policies do not qualify the current bypass implementation.
before input as well. Subagent reads use the Session's native database; the
daemon does not protect it from other tools running as the same user.
Multi-agent workspace execution installs only the existing authorized workspace
MCP entry in that private native configuration so children inherit the same
tools; public MCP and Environment-origin MCP combinations remain separately
qualified. Complete the hosted [acceptance
checklist](../../../../contracts/agents-api/harnesses.md#acceptance-checklist)
before enabling hosted execution. The standalone companion uses its own npm
lock; `make check` runs its lifecycle tests and script checks, while its
exact-source Linux build and native qualification for the actual supported
platform and outer deployment are required when the companion changes.
Historical tests of both inner network policies do not qualify the current
bypass implementation.

## Acceptance

Expand Down
Loading