Revert the agent-facing additions, keep the review work
commit
91a009cRevert the agent-facing additions, keep the review work
Back out the two agent-feature commits — the auto/manual review-policy descriptions (e3bf42f) and the forge-wide agent provider + default model config (82769e7) — since we’re not expanding the agent-sessions feature yet. The review withdraw state (fc942bc) and the issue-shaped review detail page (a151c6e) stay; they’re a separate, wanted improvement.
The reverted work remains in history (merged at 680d07c, and on the worktree-agent-sessions branch) to restore later by reverting this commit.
This reverts commit 82769e7ec and commit e3bf42f.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
crates/cli/git-ents/src/cli.rs
@@ -102,17 +102,6 @@
#[facet(args::subcommand)]
action: AccountAction,
},
- /// Manage this repository's forge-wide configuration at
- /// `refs/meta/config`: today, non-secret agent-runtime defaults (a
- /// provider name, a default model id) alongside the gate's own
- /// `epoch`/`workers` fields. The API token is never here; it lives in
- /// the deployment-time credential seam
- /// (`GIT_ENTS_CREDENTIALS_FILE`), never in a signed, replicated tree.
- Config {
- /// The config action to run.
- #[facet(args::subcommand)]
- action: ConfigAction,
- },
/// Manage the configured effects at `refs/meta/effects/<name>` and run
/// them locally.
Effect {
@@ -328,32 +317,6 @@
},
}
-/// `git ents config` actions.
-#[derive(Facet)]
-#[repr(u8)]
-pub enum ConfigAction {
- /// Show this repository's current forge-wide configuration.
- Show,
- /// Narrow the agent-runtime defaults. Each flag is independent: omit
- /// one to leave whatever it currently holds untouched rather than
- /// clearing it.
- Set {
- /// The agent runtime's provider name (e.g. `anthropic`);
- /// non-secret -- the API token itself is never a flag here, only
- /// `git-ents`'s own `GIT_ENTS_CREDENTIALS_FILE` seam.
- #[facet(args::named)]
- agent_provider: Option<String>,
- /// The agent runtime's default model id (e.g.
- /// `claude-sonnet-5`), used whenever a session start omits its
- /// own `--model`.
- #[facet(args::named)]
- agent_default_model: Option<String>,
- /// Key to sign with; defaults to `user.signingkey`.
- #[facet(args::named)]
- key: Option<PathBuf>,
- },
-}
-
/// `git ents effect` actions.
#[derive(Facet)]
#[repr(u8)]
crates/cli/git-ents/src/exe.rs
@@ -8,8 +8,8 @@
)]
use crate::cli::{
- AccountAction, AgentAction, Cli, CommentAction, ConfigAction, EffectAction, HookAction,
- InboxAction, IssueAction, MembersAction, RedactAction, ReviewAction, ToolchainAction, Top,
+ AccountAction, AgentAction, Cli, CommentAction, EffectAction, HookAction, InboxAction,
+ IssueAction, MembersAction, RedactAction, ReviewAction, ToolchainAction, Top,
};
use crate::commands;
use crate::error::Result;
@@ -69,7 +69,6 @@
}
Top::Members { action } => run_members(action, out),
Top::Account { action } => run_account(action, out),
- Top::Config { action } => run_config(action, out),
Top::Effect { action } => run_effect(action, out),
Top::Toolchain { action } => run_toolchain(action, out),
Top::Comment { action } => run_comment(action, out),
@@ -173,34 +172,6 @@
Ok(())
}
-fn run_config(action: ConfigAction, out: &mut impl std::io::Write) -> Result<()> {
- let root = LocalRoot::discover(".")?;
- match action {
- ConfigAction::Show => {
- let config = commands::config::show(&root)?;
- let _ = writeln!(
- out,
- "agent_provider: {}",
- config.agent_provider.as_deref().unwrap_or("(unset)")
- );
- let _ = writeln!(
- out,
- "agent_default_model: {}",
- config.agent_default_model.as_deref().unwrap_or("(unset)")
- );
- }
- ConfigAction::Set {
- agent_provider,
- agent_default_model,
- key,
- } => {
- commands::config::set(&root, agent_provider, agent_default_model, key)?;
- let _ = writeln!(out, "config updated");
- }
- }
- Ok(())
-}
-
fn run_effect(action: EffectAction, out: &mut impl std::io::Write) -> Result<()> {
let root = LocalRoot::discover(".")?;
match action {
crates/kernel/ents-gate/src/config.rs
@@ -23,14 +23,11 @@
///
/// `model.sdoc` defines no Config entity yet, so this struct is the
/// first (and currently only) definition of the config tree's shape; it
-/// lives here rather than in `ents-model` because these were, until now,
-/// the only fields any crate reads. `agent_provider`/`agent_default_model`
-/// (below) are the first fields this crate itself has no use for — they
-/// exist purely for other crates (`ents-web`'s new-session form) to read
-/// — but they stay here rather than moving to `ents-model` today: that
-/// move is still deferred until configuration grows enough non-gate
-/// fields to justify the storage migration (`meta-ref.migration`) in one
-/// pass, rather than one field at a time.
+/// lives here rather than in `ents-model` because these are the only
+/// fields any crate reads today. When configuration grows non-gate fields
+/// (description, role rules, ...), the entity moves to `ents-model` and
+/// that change is a storage migration like any other struct change
+/// (`meta-ref.migration`).
///
/// `epoch` is `None` on a config written before verification was turned
/// on. Once it is `Some`, the gate applies the tip invariant to every
@@ -64,21 +61,6 @@
/// narrowing lands. Empty by default: no worker is designated until a
/// signed config write adds one.
pub workers: Vec<MemberId>,
- /// The agent runtime's provider name (e.g. `"anthropic"`), forge-wide;
- /// `None` until a signed config write sets one. Non-secret by
- /// construction — the credential that authenticates to the provider
- /// never lives here or anywhere in `refs/meta/*`, only in the
- /// deployment-time seam (`git-ents`'s `credentials.rs`,
- /// `GIT_ENTS_CREDENTIALS_FILE`). The agent runtime that would consume
- /// this is not built yet; storing and reading it is this field's
- /// entire job for now.
- pub agent_provider: Option<String>,
- /// The agent runtime's default model id (e.g. `"claude-sonnet-5"`),
- /// forge-wide; `None` until a signed config write sets one. Read as a
- /// fallback ahead of any hardcoded default a caller carries — today,
- /// `ents-web`'s new-agent-session form falls back to it before its own
- /// compiled-in constant.
- pub agent_default_model: Option<String>,
}
/// The config recorded by the tree of the commit at `oid`, or an
@@ -137,21 +119,3 @@
) -> Result<Vec<MemberId>> {
Ok(current_config(refs, objects)?.workers)
}
-
-/// The forge-wide agent provider name currently in force, read from
-/// `refs/meta/config`'s tip; `None` when the config ref does not exist or
-/// names no provider. Public (unlike [`designated_workers`], which only
-/// this crate's gate consults) because the only consumer today, an agent
-/// runtime, does not live in this crate.
-pub fn agent_provider(refs: &dyn RefStoreRead, objects: &dyn Find) -> Result<Option<String>> {
- Ok(current_config(refs, objects)?.agent_provider)
-}
-
-/// The forge-wide default agent model id currently in force, read from
-/// `refs/meta/config`'s tip; `None` when the config ref does not exist or
-/// names no default — callers fall back to their own compiled-in default
-/// (`ents-web`'s new-agent-session form, today) rather than treating
-/// `None` as an error.
-pub fn agent_default_model(refs: &dyn RefStoreRead, objects: &dyn Find) -> Result<Option<String>> {
- Ok(current_config(refs, objects)?.agent_default_model)
-}
crates/kernel/ents-gate/src/lib.rs
@@ -155,7 +155,7 @@
mod verdict;
mod verify;
-pub use config::{Config, agent_default_model, agent_provider};
+pub use config::Config;
pub use error::{Error, Result};
pub use verdict::{Admission, AdmissionKind, Refusal, Requirement, Verdict};
pub use verify::{Update, verify};
crates/kernel/ents-gate/tests/gate.rs
@@ -856,7 +856,6 @@
&Config {
epoch: Some(200),
workers: vec![MemberId::new(worker_id)],
- ..Config::default()
},
Some(&f.admin),
seconds,
crates/cli/ents-web/src/assets/ents.css
@@ -572,7 +572,6 @@
}
.picker .opt .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-4); }
.picker .opt.active { font-weight: 600; }
-.opt-help { font-size: 12px; line-height: 1.5; margin: 8px 0 0; }
/* Label picker chips (`labelPicker`): pick existing or type-and-create. */
.label-chip {
crates/cli/ents-web/src/pages/agents.rs
@@ -61,7 +61,6 @@
.map(|entry| (entry.refname, entry.error))
.collect();
let default_base = default_base_ref(&state);
- let default_model = resolved_default_model(&state);
Ok(super::layout_split(
&super::RepoHeader::from_state(&state),
&super::identity_label(&state),
@@ -80,7 +79,7 @@
}
div.card {
div.card-header { "Start an Agent Session" }
- (new_form(&session, &default_base, &default_model))
+ (new_form(&session, &default_base))
}
}
},
@@ -697,19 +696,18 @@
/// The start-a-session form (`POST /agents`, `docs/agent-sessions-plan.adoc`'s
/// Phase 3, "mobile-critical"): a prompt textarea, a base-branch text input
/// pre-filled with `default_base` ([`default_base_ref`]), a model text
-/// input pre-filled with `default_model` ([`resolved_default_model`]), and
-/// a closed two-option review policy picker defaulting to `manual`
-/// (mirrors `crate::pages::commits::start_review_form`'s identical
-/// closed-verdict picker) -- deliberately no toolchain or retry field: the
-/// plan's own words are "complexity lives in the session doc, not the
-/// form."
-fn new_form(session: &Session, default_base: &str, default_model: &str) -> Markup {
+/// input pre-filled with [`DEFAULT_MODEL`], and a closed two-option review
+/// policy picker defaulting to `manual` (mirrors
+/// `crate::pages::commits::start_review_form`'s identical closed-verdict
+/// picker) -- deliberately no toolchain or retry field: the plan's own
+/// words are "complexity lives in the session doc, not the form."
+fn new_form(session: &Session, default_base: &str) -> Markup {
html! {
form method="post" action="/agents" {
(super::csrf_input(session))
label { "prompt" textarea name="prompt" {} }
label { "base branch" input type="text" name="base_ref" value=(default_base); }
- label { "model" input type="text" name="model" value=(default_model); }
+ label { "model" input type="text" name="model" value=(DEFAULT_MODEL); }
div {
p.muted { "review policy" }
div.picker {
@@ -724,12 +722,6 @@
"auto"
}
}
- p.opt-help.muted {
- strong { "Manual" }
- " — no review opens on its own; you start one yourself when you want it. "
- strong { "Auto" }
- " — a review of the result opens automatically once the run finishes."
- }
}
div.composer-buttons {
a.composer-cancel href="/agents" { "Cancel" }
@@ -739,26 +731,11 @@
}
}
-/// The model id [`resolved_default_model`] falls back to when
-/// `refs/meta/config` names no `agent_default_model` (or does not exist
-/// yet) -- the same default id this codebase's own fixtures and
-/// `git-ents::agent_worker` tests already use.
+/// The model id [`new_form`] pre-fills and [`NewForm::model`] defaults to
+/// when a submission omits the field entirely -- the same default id this
+/// codebase's own fixtures and `git-ents::agent_worker` tests already use.
const DEFAULT_MODEL: &str = "claude-sonnet-5";
-/// The model id [`new_form`] pre-fills and [`NewForm::model`] falls back to
-/// when a submission omits the field entirely: `refs/meta/config`'s
-/// `agent_default_model` (`ents_gate::agent_default_model`) when a signed
-/// config write has set one, else [`DEFAULT_MODEL`] -- a forge-wide
-/// default lets an operator change what every new session starts at
-/// without touching this crate's own compiled-in fallback, which stays as
-/// the floor for a repository that has never configured one.
-fn resolved_default_model<O: Find>(state: &AppState<O>) -> String {
- ents_gate::agent_default_model(state.refs.as_ref(), &*state.objects())
- .ok()
- .flatten()
- .unwrap_or_else(|| DEFAULT_MODEL.to_owned())
-}
-
/// The base ref [`new_form`] pre-fills: `refs/heads/<branch>` for the
/// served repository's own current `HEAD` branch
/// ([`super::RepoHeader::from_state`]), or plain `HEAD` when that cannot
@@ -799,11 +776,10 @@
/// [`default_base_ref`]).
#[serde(default = "default_base_ref_field")]
base_ref: String,
- /// The model id the run executes against; `None` when a submission
- /// omits the field entirely, resolved by [`resolved_default_model`]
- /// (see [`create`]).
- #[serde(default)]
- model: Option<String>,
+ /// The model id the run executes against; defaults to
+ /// [`DEFAULT_MODEL`].
+ #[serde(default = "default_model_field")]
+ model: String,
/// The session's initially resolved review policy: `auto` or `manual`;
/// defaults to `manual` (see [`default_review_policy`]).
#[serde(default = "default_review_policy")]
@@ -812,6 +788,11 @@
csrf: String,
}
+/// [`NewForm::model`]'s serde default -- see [`DEFAULT_MODEL`].
+fn default_model_field() -> String {
+ DEFAULT_MODEL.to_owned()
+}
+
/// `POST /agents`: start an agent session owned by the current signing
/// identity's resolved member (`ents_forge::agent::new`), signed
/// (`roots.web-signing`) on behalf of the current session
@@ -837,11 +818,10 @@
super::require_csrf(&session, &form.csrf)?;
let member = session_owner(&state);
let identity = state.identity.as_ref();
- let model = form.model.unwrap_or_else(|| resolved_default_model(&state));
let new = NewAgentSession {
member,
prompt: form.prompt,
- model,
+ model: form.model,
toolchains: Vec::new(),
base_ref: form.base_ref,
review_policy: form
crates/cli/git-ents/src/commands/mod.rs
@@ -12,7 +12,6 @@
pub mod agent;
pub mod bootstrap;
pub mod comment;
-pub mod config;
pub mod effect;
pub mod inbox;
pub mod issue;
crates/forge/ents-forge/src/agent/cli.rs
@@ -33,9 +33,7 @@
/// The ref the run executes against as its starting point.
#[facet(args::named, default = "HEAD")]
base: String,
- /// The session's initially resolved review policy. `manual` (default):
- /// no review opens on its own; you start one yourself. `auto`: a review
- /// of the result opens automatically once the run finishes.
+ /// The session's initially resolved review policy: auto or manual.
#[facet(args::named, default = "manual")]
review_policy: String,
/// The genesis oid of a prior session this one retries.
crates/cli/git-ents/src/commands/config.rs
@@ -1,96 +1,0 @@
-//! `git ents config`: forge-wide, non-secret agent-runtime defaults
-//! (provider name, default model) recorded in `refs/meta/config` alongside
-//! the gate's own `epoch`/`workers` fields (`ents_gate::Config`).
-//!
-//! The API token is deliberately not here and never will be: it lives only
-//! in the deployment-time credential seam (`crate::credentials`,
-//! `GIT_ENTS_CREDENTIALS_FILE`), never in a signed, replicated,
-//! multi-reader tree.
-
-use ents_gate::Config;
-use ents_model::namespace;
-use ents_receive::{Identity, propose_entity};
-use gix_ref_store::RefStoreRead;
-
-use super::{actor, signer};
-use crate::error::Result;
-use crate::mutate::outcome_to_result;
-use crate::root::LocalRoot;
-
-/// `git ents config show`: this repository's current forge-wide
-/// configuration -- [`Config::default`] (every field unset) when
-/// `refs/meta/config` has no tip yet, the same "absent means unconfigured"
-/// reading every `ents_gate::config` reader already gives.
-///
-/// # Errors
-///
-/// Propagates a ref-store or object read failure, or an unreadable config
-/// tree.
-pub fn show(root: &LocalRoot) -> Result<Config> {
- #[expect(
- clippy::expect_used,
- clippy::unwrap_in_result,
- reason = "CONFIG_REF is a fixed, compile-time-known-valid refname literal"
- )]
- let name: gix::refs::FullName = namespace::CONFIG_REF
- .try_into()
- .expect("fixed, valid refname");
- let Some(tip) = root.refs.get(name.as_ref())? else {
- return Ok(Config::default());
- };
- let tree = super::commit_tree(&root.objects, tip)?;
- Ok(facet_git_tree::deserialize::<Config>(&tree, &root.objects)?)
-}
-
-/// `git ents config set`: narrow the agent-runtime defaults. Each argument
-/// is an independent optional narrowing -- omit one to leave whatever it
-/// currently holds untouched, rather than resetting it to `None`. Reads
-/// the current config first and writes the merged whole back, so a `set`
-/// naming only `agent_provider` cannot clobber an `agent_default_model`
-/// set earlier, or the gate's own `epoch`/`workers`.
-///
-/// # Errors
-///
-/// Propagates a ref-store/object read failure or a signing failure;
-/// otherwise see [`crate::mutate::outcome_to_result`] for how a reached
-/// refusal renders.
-pub fn set(
- root: &LocalRoot,
- agent_provider: Option<String>,
- agent_default_model: Option<String>,
- key: Option<std::path::PathBuf>,
-) -> Result<()> {
- let signer = signer(root, key)?;
- let mut config = show(root)?;
- if let Some(provider) = agent_provider {
- config.agent_provider = Some(provider);
- }
- if let Some(model) = agent_default_model {
- config.agent_default_model = Some(model);
- }
- #[expect(
- clippy::expect_used,
- clippy::unwrap_in_result,
- reason = "CONFIG_REF is a fixed, compile-time-known-valid refname literal"
- )]
- let name: gix::refs::FullName = namespace::CONFIG_REF
- .try_into()
- .expect("fixed, valid refname");
- let identity = Identity {
- actor: actor(&signer),
- author: None,
- sign: &|payload| signer.sign(payload),
- };
- let outcome = propose_entity(
- &root.refs,
- &root.objects,
- &root.events,
- name,
- &config,
- &identity,
- "Set agent config",
- root.mode(),
- )?;
- outcome_to_result(outcome, None)?;
- Ok(())
-}
crates/cli/git-ents/tests/config.rs
@@ -1,65 +1,0 @@
-//! Integration coverage for `git ents config` against a real local
-//! composition root (`roots.local`): narrowing the agent-runtime defaults
-//! at `refs/meta/config` without disturbing fields `set` was not told to
-//! touch, and reading an unconfigured repository back as
-//! `ents_gate::Config::default()`.
-
-#![allow(clippy::expect_used, reason = "integration test")]
-
-mod common;
-
-use ents_gate::Config;
-use git_ents::commands::config;
-use git_ents::root::LocalRoot;
-
-/// A repository that has never had `refs/meta/config` written reads back
-/// as every field unset -- the same "absent means unconfigured" reading
-/// `ents_gate::config`'s own readers give, and what lets an old config
-/// (predating `agent_provider`/`agent_default_model`) keep parsing.
-// @relation(roots.local, scope=function, role=Verifies)
-#[test]
-fn absent_config_reads_as_default() {
- let fixture = common::Fixture::new(1);
- let root = LocalRoot::open(fixture.path()).expect("opens");
-
- let config = config::show(&root).expect("shows");
- assert_eq!(config, Config::default());
-}
-
-/// `set` narrows one field at a time: a later call naming only
-/// `agent_default_model` must not clobber an `agent_provider` an earlier
-/// call set, and neither call ever touches `workers`/`epoch` (unset by
-/// either call).
-// @relation(roots.local, scope=function, role=Verifies)
-#[test]
-fn set_narrows_without_clobbering_other_fields() {
- let fixture = common::Fixture::new(1);
- let root = LocalRoot::open(fixture.path()).expect("opens");
-
- config::set(
- &root,
- Some("anthropic".to_owned()),
- None,
- Some(fixture.key_path.clone()),
- )
- .expect("sets provider");
- let config = config::show(&root).expect("shows");
- assert_eq!(config.agent_provider.as_deref(), Some("anthropic"));
- assert_eq!(config.agent_default_model, None);
- assert!(config.workers.is_empty());
- assert_eq!(config.epoch, None);
-
- config::set(
- &root,
- None,
- Some("claude-sonnet-5".to_owned()),
- Some(fixture.key_path.clone()),
- )
- .expect("sets default model");
- let config = config::show(&root).expect("shows");
- assert_eq!(config.agent_provider.as_deref(), Some("anthropic"));
- assert_eq!(
- config.agent_default_model.as_deref(),
- Some("claude-sonnet-5")
- );
-}