Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1d5ae23
chore: project capobara from Mono 8420a1f8c5fd
Sep 20, 2026
6074d45
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 20, 2026
47cbca1
chore: project capobara from Mono e123b3f67c39
Sep 20, 2026
fb02b9f
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 21, 2026
d3323f7
chore: project capobara from Mono 9b559bc70e7d
Sep 21, 2026
dc0f419
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 21, 2026
93ea333
chore: project capobara from Mono 9a003786d767
Sep 21, 2026
734bf4b
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 21, 2026
c6a4c21
chore: project capobara from Mono 511bd2305f5a
Sep 21, 2026
bcf50cb
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 21, 2026
d4e6463
chore: project capobara from Mono ad7b9df0b712
Sep 21, 2026
e486fa5
chore: project capobara from Mono 4ab4845398fd
Sep 21, 2026
55bad97
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 22, 2026
93b199e
chore: project capobara from Mono 2df44a8283c0
Sep 22, 2026
9faef24
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 23, 2026
a715fce
chore: project capobara from Mono 3ccfbea716d8
Sep 23, 2026
58daea2
Merge remote-tracking branch 'origin/main' into sync/mono-projection
github-actions[bot] Sep 24, 2026
4404518
chore: project capobara from Mono a971433d12b4
Sep 24, 2026
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
8 changes: 4 additions & 4 deletions .repository-projection.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"projection": "capobara",
"projectionSchemaVersion": 1,
"sourceRepository": "dx-corp/mono",
"sourceSha": "3ccfbea716d8d52596980ca1f1f3b62166e7849d",
"sourceSha": "a971433d12b40d9042b3a64c2c074fa8fc398e69",
"destinationRepository": "dx-corp/capobara",
"priorProjectedBase": "72796ef8e718acb181dbf0e101fe4b0af45b62e9",
"priorProjectedBase": "307384e1e96bf2ec22f2821e327f503ba226e9af",
"definitionDigest": "7826c75cbd356dad6c867f2606ebde8b79ef4361353908cf33ada720034ec488",
"toolDigest": "898e8657d9153a2a51d7c283bf83bb3350b5d1e6",
"contentDigest": "e885e1248460736b96bfc794621e93051f8756668175e264adc51b6ce53ed7e3",
"toolDigest": "ff02edcbb40b0028af10ab01a101e918341f157a",
"contentDigest": "6a37cb0856ce05d920e8371504af2f233bfbdce0bf000d0c1e1ad1acfa90f07e",
"publicationEligible": true
}
22 changes: 22 additions & 0 deletions src/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,28 @@ fn validate_definition_value(
});
}

if name == "api" {
for (source, expected) in [
("proto", "deixicpublic/v1/sdk.proto"),
("gen/openapi", "deixicpublic/v1/sdk.openapi.yaml"),
] {
invalid(
mapping_fields
.iter()
.filter(|mapping| mapping.source == source)
.count()
== 1
&& mapping_fields.iter().any(|mapping| {
mapping.source == source
&& mapping.include.len() == 1
&& mapping.include[0] == expected
&& mapping.exclude.is_empty()
}),
format!("Public API {source} projection must contain only {expected}"),
)?;
}
}

if mode == "sdk-assembly-v1" {
// Rule 10
let policy_inputs = sdk_inputs(name);
Expand Down
81 changes: 23 additions & 58 deletions src/modes/sdk_assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,11 @@ fn apply_transform(transform: Option<Transform>, content: &[u8]) -> Result<Vec<u
let text = String::from_utf8_lossy(content).into_owned();
match transform {
Transform::PythonPyproject => {
static DEPENDENCY: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#"(?m)^ "evalops-sdk[^"]+",\n"#).expect("static regex is valid")
});
contract(
DEPENDENCY.find_iter(&text).count() == 1,
"Python generated dependency declaration changed",
!text.contains("\"evalops-sdk"),
"Python package must not depend on the internal generated SDK",
)?;
let without_dependency = DEPENDENCY.replace(&text, "");
Ok(without_dependency
Ok(text
.replace(
"https://github.com/dx-corp/mono",
"https://github.com/dx-corp/deixic-python",
Expand Down Expand Up @@ -156,49 +152,25 @@ fn validate_closure(policy: &Policy, source_entries: &HashMap<String, Entry>) ->
}

fn validate_python_closure(source_entries: &HashMap<String, Entry>) -> Result<()> {
let protocol = source_text(
source_entries,
"sdk/deixic/python/src/deixicpublic/v1/sdk_pb2.py",
)?;
contract(
protocol.contains("deixicpublic.v1"),
"Python public protocol missing",
)?;
static IMPORT: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"(?m)^from ([A-Za-z0-9_.]+) import ([A-Za-z0-9_]+_pb2)\b")
Regex::new(r"(?m)^from ([A-Za-z_][A-Za-z0-9_.]*) import .*_pb2")
.expect("static regex is valid")
});
const PREFIX: &str = "gen/python/";
let allowed: HashSet<String> = policies::PYTHON_GENERATED_FILES
.iter()
.map(|path| format!("{PREFIX}{path}"))
.collect();
let mut visited: HashSet<String> = HashSet::new();
let mut queue: Vec<String> = vec![format!("{PREFIX}console/v1/console_pb2.py")];
while let Some(path) = queue.pop() {
if visited.contains(&path) {
continue;
}
for caps in IMPORT.captures_iter(&protocol) {
contract(
allowed.contains(&path),
format!("Python generated import escapes reviewed closure: {path}"),
caps[1].starts_with("google.protobuf"),
"Python protocol imports an unreviewed generated module",
)?;
visited.insert(path.clone());
let text = source_text(source_entries, &path)?;
for caps in IMPORT.captures_iter(&text) {
let package_name = &caps[1];
let module_name = &caps[2];
if package_name.starts_with("google.protobuf") {
continue;
}
let imported = format!(
"{PREFIX}{}/{module_name}.py",
package_name.replace('.', "/")
);
contract(
allowed.contains(&imported),
format!("Python generated import escapes reviewed closure: {imported}"),
)?;
queue.push(imported);
}
}
require_same_set(
&visited.into_iter().collect::<Vec<_>>(),
&allowed.into_iter().collect::<Vec<_>>(),
"Python generated dependency closure",
)
Ok(())
}

fn validate_typescript_closure(source_entries: &HashMap<String, Entry>) -> Result<()> {
Expand All @@ -209,18 +181,11 @@ fn validate_typescript_closure(source_entries: &HashMap<String, Entry>) -> Resul
"sdk/deixic/typescript/src/index.ts".to_string(),
"sdk/deixic/typescript/src/tasks.ts".to_string(),
];
let mut allowed: HashSet<String> = build_roots.iter().cloned().collect();
allowed.extend(
policies::NODE_SHARED_FILES
.iter()
.filter(|path| path.ends_with(".ts"))
.map(|path| (*path).to_string()),
);
allowed.extend(
policies::TYPESCRIPT_GENERATED_FILES
.iter()
.map(|path| format!("gen/ts/{path}")),
);
let allowed: HashSet<String> = policies::NODE_PACKAGE_FILES
.iter()
.filter(|path| path.starts_with("src/"))
.map(|path| format!("sdk/deixic/typescript/{path}"))
.collect();
let mut visited: HashSet<String> = HashSet::new();
let mut queue: Vec<String> = build_roots.to_vec();
while let Some(path) = queue.pop() {
Expand Down Expand Up @@ -283,8 +248,8 @@ fn validate_go_closure(source_entries: &HashMap<String, Entry>) -> Result<()> {
let mut visited_files: HashSet<String> = HashSet::new();
let mut visited_packages: HashSet<String> = HashSet::new();
let mut queue: Vec<String> = vec![
"deixic/v1".to_string(),
"deixic/v1/deixicv1connect".to_string(),
"deixicpublic/v1".to_string(),
"deixicpublic/v1/deixicpublicv1connect".to_string(),
];
while let Some(package_path) = queue.pop() {
if visited_packages.contains(&package_path) {
Expand Down
152 changes: 18 additions & 134 deletions src/modes/sdk_assembly/policies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub const PYTHON_SDK_FILES: &[&str] = &[
"src/deixic/examples/task_result.py",
"src/deixic/examples/verify_test_journey.py",
"src/deixic/py.typed",
"src/deixic/protocol.py",
"src/deixicpublic/__init__.py",
"src/deixicpublic/v1/__init__.py",
"src/deixicpublic/v1/sdk_pb2.py",
"src/deixic/tasks.py",
"src/deixic/transport.py",
"tests/test_account_brief.py",
Expand All @@ -37,33 +41,6 @@ pub const PYTHON_SDK_FILES: &[&str] = &[

// Generated protobuf/gRPC Python modules under `gen/python/`, copied into
// `src/` (mirrors `PYTHON_GENERATED_FILES`).
pub const PYTHON_GENERATED_FILES: &[&str] = &[
"agentruntime/v1/runtime_pb2.py",
"agents/v1/agents_pb2.py",
"buf/validate/validate_pb2.py",
"codex/v1/codex_pb2.py",
"common/v1/analytics_pb2.py",
"common/v1/authz_pb2.py",
"common/v1/classification_pb2.py",
"common/v1/delivery_pb2.py",
"common/v1/entity_pb2.py",
"common/v1/risk_pb2.py",
"common/v1/surface_pb2.py",
"connectors/v1/connectors_pb2.py",
"console/v1/console_pb2.py",
"evalops_platform/v1/platform_pb2.py",
"google/api/annotations_pb2.py",
"google/api/http_pb2.py",
"memory/v1/memory_pb2.py",
"meter/v1/meter_pb2.py",
"objectives/v1/objectives_pb2.py",
"orbcontrol/v1/orb_control_pb2.py",
"remoterunner/v1/remoterunner_pb2.py",
"toolexecution/v1/toolexecution_pb2.py",
"traces/v1/traces_pb2.py",
"vfs/v1/filesystem_pb2.py",
];

// The reviewed Deixic Node package's own files (mirrors `NODE_PACKAGE_FILES`).
pub const NODE_PACKAGE_FILES: &[&str] = &[
"CHANGELOG.md",
Expand All @@ -78,79 +55,21 @@ pub const NODE_PACKAGE_FILES: &[&str] = &[
"scripts/smoke-packed-package.mjs",
"src/index.ts",
"src/tasks.ts",
"src/client.ts",
"src/errors.ts",
"src/accepted-turn.ts",
"src/app-context.ts",
"src/protocol.ts",
"test/account-brief-result.test.mjs",
"test/account-brief.test.mjs",
"test/client.test.mjs",
"test/tasks.test.mjs",
"tsconfig.json",
];

// index.ts is intentionally absent: the Deixic package imports this smaller
// reviewed helper closure directly instead of projecting the Maestro SDK.
pub const NODE_SHARED_FILES: &[&str] = &[
"sdk/maestro/typescript/scripts/verify-descriptor-sources.mjs",
"sdk/maestro/typescript/src/accepted-turn.ts",
"sdk/maestro/typescript/src/app-context.ts",
"sdk/maestro/typescript/src/client.ts",
"sdk/maestro/typescript/src/errors.ts",
];

// Generated protobuf/gRPC TypeScript modules under `gen/ts/`, copied into
// place under the same relative path (mirrors `TYPESCRIPT_GENERATED_FILES`).
pub const TYPESCRIPT_GENERATED_FILES: &[&str] = &[
"agentruntime/v1/runtime_pb.ts",
"agents/v1/agents_pb.ts",
"buf/validate/validate_pb.ts",
"codex/v1/codex_pb.ts",
"common/v1/analytics_pb.ts",
"common/v1/authz_pb.ts",
"common/v1/classification_pb.ts",
"common/v1/delivery_pb.ts",
"common/v1/entity_pb.ts",
"common/v1/risk_pb.ts",
"common/v1/surface_pb.ts",
"connectors/v1/connectors_pb.ts",
"console/v1/console_pb.ts",
"deixic/v1/deixic_pb.ts",
"google/api/annotations_pb.ts",
"google/api/http_pb.ts",
"memory/v1/memory_pb.ts",
"meter/v1/meter_pb.ts",
"objectives/v1/objectives_pb.ts",
"orbcontrol/v1/orb_control_pb.ts",
"platform/v1/platform_pb.ts",
"remoterunner/v1/remoterunner_pb.ts",
"toolexecution/v1/toolexecution_pb.ts",
"traces/v1/traces_pb.ts",
"vfs/v1/filesystem_pb.ts",
];

// Generated protobuf/gRPC Go modules under `gen/go/`, copied into place under
// the same relative path (mirrors `GO_GENERATED_FILES`).
pub const GO_GENERATED_FILES: &[&str] = &[
"agentruntime/v1/runtime.pb.go",
"agents/v1/agents.pb.go",
"codex/v1/codex.pb.go",
"common/v1/analytics.pb.go",
"common/v1/authz.pb.go",
"common/v1/classification.pb.go",
"common/v1/delivery.pb.go",
"common/v1/entity.pb.go",
"common/v1/risk.pb.go",
"common/v1/surface.pb.go",
"connectors/v1/connectors.pb.go",
"console/v1/console.pb.go",
"deixic/v1/deixic.pb.go",
"deixic/v1/deixicv1connect/deixic.connect.go",
"memory/v1/memory.pb.go",
"meter/v1/meter.pb.go",
"objectives/v1/objectives.pb.go",
"orbcontrol/v1/orb_control.pb.go",
"platform/v1/platform.pb.go",
"remoterunner/v1/remoterunner.pb.go",
"toolexecution/v1/toolexecution.pb.go",
"traces/v1/traces.pb.go",
"vfs/v1/filesystem.pb.go",
"deixicpublic/v1/sdk.pb.go",
"deixicpublic/v1/deixicpublicv1connect/sdk.connect.go",
];

/// A byte-for-byte transform applied to one copy's content, keyed by the
Expand Down Expand Up @@ -208,7 +127,7 @@ fn copy(
}

fn python_copies() -> Vec<Copy> {
let mut copies: Vec<Copy> = PYTHON_SDK_FILES
let copies: Vec<Copy> = PYTHON_SDK_FILES
.iter()
.map(|path| {
copy(
Expand All @@ -218,16 +137,11 @@ fn python_copies() -> Vec<Copy> {
)
})
.collect();
copies.extend(
PYTHON_GENERATED_FILES
.iter()
.map(|path| copy(format!("gen/python/{path}"), format!("src/{path}"), None)),
);
copies
}

fn node_copies() -> Vec<Copy> {
let mut copies: Vec<Copy> = NODE_PACKAGE_FILES
let copies: Vec<Copy> = NODE_PACKAGE_FILES
.iter()
.map(|path| {
let full = format!("sdk/deixic/typescript/{path}");
Expand All @@ -238,15 +152,6 @@ fn node_copies() -> Vec<Copy> {
)
})
.collect();
copies.extend(
NODE_SHARED_FILES
.iter()
.map(|path| copy((*path).to_string(), (*path).to_string(), None)),
);
copies.extend(TYPESCRIPT_GENERATED_FILES.iter().map(|path| {
let full = format!("gen/ts/{path}");
copy(full.clone(), full, None)
}));
copies
}

Expand All @@ -256,12 +161,11 @@ fn go_copies() -> Vec<Copy> {
copy("sdk/deixic/python/LICENSE", "LICENSE", None),
copy(
"sdk/deixic/go/deixic_connect_test.go.in",
"deixic/v1/deixicv1connect/projection_test.go",
"deixicpublic/v1/deixicpublicv1connect/projection_test.go",
None,
),
copy("gen/go/CHANGELOG.md", "CHANGELOG.md", None),
copy("gen/go/go.mod", "go.mod", Some(Transform::GoModule)),
copy("gen/go/go.sum", "go.sum", None),
copy("sdk/deixic/go/go.mod", "go.mod", None),
copy("sdk/deixic/go/go.sum", "go.sum", None),
];
copies.extend(GO_GENERATED_FILES.iter().map(|path| {
copy(
Expand Down Expand Up @@ -314,12 +218,7 @@ static POLICIES: LazyLock<Vec<Policy>> = LazyLock::new(|| {
"deixic-node",
node_copies(),
Closure::TypescriptCompiledImportsV1,
&[
"gen/ts/**",
"sdk/deixic/typescript/**",
"sdk/maestro/typescript/scripts/verify-descriptor-sources.mjs",
"sdk/maestro/typescript/src/**",
],
&["sdk/deixic/typescript/**"],
),
make_policy(
"deixic-go",
Expand All @@ -329,24 +228,9 @@ static POLICIES: LazyLock<Vec<Policy>> = LazyLock::new(|| {
"CHANGELOG.md",
"LICENSE",
"README.md",
"agentruntime/**",
"agents/**",
"codex/**",
"common/**",
"connectors/**",
"console/**",
"deixic/**",
"deixicpublic/**",
"go.mod",
"go.sum",
"memory/**",
"meter/**",
"objectives/**",
"orbcontrol/**",
"platform/**",
"remoterunner/**",
"toolexecution/**",
"traces/**",
"vfs/**",
],
),
]
Expand Down
Loading