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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions PROJECT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ one.
| Multi-need and structured MCP | Sequential and steer delivery, bounded ledger, structured JSON tools, cancellation, shared resolver | App Server simulator and one structured MCP cache-hit observation | **Implemented; offline validated; live calibration** |
| Claim-level reuse | Validator-extracted claims, claim proofs, mixed planning, and bounded authoritative location, runtime-flow, and focused-test claims | Deterministic freshness, mutation, negative, projection, economics, and performance cases | **Implemented; offline validated** |
| Verified changes | Isolated patch preparation, independent verifier, one repair, explicit journaled apply | Simulator and focused persistence, isolation, drift, and recovery tests | **Implemented; offline validated** |
| Codex role-profile control plane | Canonical Codex role definitions, bounded policies, immutable revisions, state-digest CAS, SQLite V14 persistence, audit records, and explicit WorkerProfile projection | Focused deterministic needle-core and needle-runtime offline tests; editor, session binding, and lifecycle integration remain pending | **Implemented; offline validated** |
| Codex role-profile control plane | Canonical Codex role definitions, bounded policies, immutable revisions, state-digest CAS, SQLite V14 persistence, audit records, explicit WorkerProfile projection, bounded digest-bound HTTP API, and local editor | Focused deterministic Rust and frontend tests; configuration-only boundary (no worker/session binding or lifecycle execution) | **Implemented; offline validated** |
| Codex development lifecycle orchestration | Evidence, patch, test, verification, approval, and apply primitives exist; the configurable parent-owned role lifecycle is not integrated | Component-level offline evidence only | **Pending** |
| Other-host subagent configuration | Configuration-only interoperability is planned for Claude Code and Cursor, followed by OpenCode and Antigravity | Not available | **Pending** |
| Multi-host orchestration | Execution remains Codex-only; non-Codex execution follows configuration interoperability, a host contract, and conformance evidence | Not available | **Pending** |
Expand Down Expand Up @@ -61,7 +61,8 @@ provider-backed claim-authority observation exists.
| Embedded React control plane | **Implemented; frontend and local end-to-end validation** |
| Needs, proofs, claims, changes, runs, models, cache, settings, approvals | **Implemented; development interface** |
| Canonical named Codex role-profile domain and revision store | **Implemented; offline validated** |
| Named role-profile HTTP/editor, session binding, and lifecycle integration | **Pending; Codex-first** |
| Named role-profile HTTP/editor | **Implemented; offline validated; configuration-only** |
| Role-profile session binding and lifecycle integration | **Pending; Codex-first** |
| Non-Codex subagent configuration | **Pending; configuration only before execution** |
| Non-Codex execution and orchestration | **Pending; later milestone** |
| Stable public API or configuration compatibility | **Pending** |
Expand Down Expand Up @@ -123,9 +124,10 @@ validation.
- Claim authority is deliberately narrow, defaults to `Shadow`, and has no
provider-backed evidence.
- Verified changes have no provider-backed patcher or verifier observation.
- Canonical role-profile definitions and revision persistence are implemented
and offline validated, but there is no HTTP/editor UI, session or worker
binding, lifecycle executor, or automatic profile activation yet.
- Canonical role-profile definitions, revision persistence, bounded HTTP/editor
flows, and request-time preflight are implemented and offline validated.
They do not provide session or worker binding, a lifecycle executor, or
automatic profile activation; activation is an explicit configuration change.
- The verifier handles a deterministic serial set of up to four distinct
associated certified test plans; exact duplicates collapse to one execution,
while over-cap and unavailable plans fail closed. This behavior is offline
Expand Down
3 changes: 3 additions & 0 deletions crates/needle-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ thiserror.workspace = true
tokio = { version = "1.47", features = ["io-util", "macros", "net", "rt-multi-thread", "signal", "sync", "time"] }
toml.workspace = true
rust-embed = "8"

[dev-dependencies]
tower = "0.5"
11 changes: 10 additions & 1 deletion crates/needle-app/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ use std::time::Duration;

use crate::runtime_instance::InstanceGuard;

#[path = "server/role_profiles.rs"]
mod role_profiles;

#[derive(RustEmbed)]
#[folder = "web/dist"]
struct WebAssets;
Expand Down Expand Up @@ -217,7 +220,8 @@ pub(crate) fn run(data_directory: PathBuf, repository_root: PathBuf) -> Result<(
.route("/api/v1/changes/{id}", get(get_change))
.route("/api/v1/changes/{id}/diff", get(get_change_diff))
.route("/api/v1/changes/{id}/apply", post(apply_change))
.route("/api/v1/control-plane", get(control_plane))
.route("/api/v1/control-plane", get(control_plane));
let app = role_profiles::routes(app)
.fallback(get(static_asset))
.with_state(state.clone())
.layer(middleware::from_fn_with_state(state.clone(), security));
Expand Down Expand Up @@ -337,6 +341,10 @@ async fn control_plane(State(state): State<AppState>) -> Response {
let model_policy = state.store.model_policy().ok();
let model_policy_digest =
model_policy.as_ref().and_then(|value| configuration_digest(value).ok());
let role_profiles = match role_profiles::control_plane_envelope(&state.store) {
Ok(role_profiles) => role_profiles,
Err(error) => return api_error(StatusCode::INTERNAL_SERVER_ERROR, &error.to_string()),
};
let route_promotions = state.store.route_promotions().unwrap_or_default();
let change_records = match state.store.changes(50) {
Ok(changes) => changes,
Expand Down Expand Up @@ -478,6 +486,7 @@ async fn control_plane(State(state): State<AppState>) -> Response {
"pending_approvals": approvals.len(),
"model_policy": model_policy,
"model_policy_digest": model_policy_digest,
"role_profiles": role_profiles,
"route_promotions": route_promotions,
"changes": change_workflows,
"semantic": {
Expand Down
Loading