Skip to content

feat(actors): a model label on the actor row - #170

Merged
ChesterRa merged 3 commits into
ChesterRa:mainfrom
chriscoveries:feat/actor-model-v2
Oct 30, 2026
Merged

ChesterRa merged 3 commits into
ChesterRa:mainfrom
chriscoveries:feat/actor-model-v2

Conversation

@chriscoveries

@chriscoveries chriscoveries commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

The actor row says which runtime an Actor uses, but not which model it runs.
That shows up only inside the command line, as a runtime-specific flag, and
not at all for an Actor whose command does not name one. A foreman or a tool
that wants to pick between Actors by model has to parse commands. A model
key sent to actor_add or actor_update today is dropped without an error,
and cccc actor add --model is rejected as an unknown argument.

What changes.

  • An Actor carries an optional model label. It is set on actor_add,
    changed on actor_update, and cleared there with an empty string. It
    appears on actor_list rows and in the actor.add event, and it is stored
    with the group, so it survives a daemon restart.
  • The label is trimmed and limited to 128 characters, with no control
    characters; anything else is refused. An unset label is left out of the row
    rather than shown as an empty string.
  • It is a label for people and tools. Launching does not read it, so it never
    changes what runs. (fix(codex): open the thread on the model the command declares #156 is the other direction: it opens a Codex thread on
    the model the command declares.)
  • The CLI gains --model on actor add and actor update. The MCP
    cccc_actor schema describes the key for add.

How we built it.

  • Current PR base is upstream main f1d27838; head d4619924 is the reviewed feature change merged with that base. The eight-file feature delta adds an optional Actor.model label with serde defaults and validates it in core actors::add and actors::update.
  • CLI args and the actor_add / actor_update requests pass it;
    resources/mcp_tools.json and CCCC_DAEMON_IPC_V1.md describe it.
  • 8 files, +122/−2, of which about 85 lines are tests.

How we tested it.

  • Daemon test (integration_ops.rs), through actor_add, actor_list and
    actor_update: a label with surrounding spaces is stored trimmed and is in
    the actor.add event and the row; an update changes it; 129 characters and
    a label with a newline are refused and leave it unchanged; an empty string
    clears it, and the row then has no model key.
  • CLI parse test: actor add --model and actor update --model "".
  • Historical red reference on upstream main a212cb04, before main advanced to f1d27838: run 39763752925 (2,716 tests: 2,715 passed, and only an_actor_carries_the_model_label_its_operator_gives_it failed). The CLI parse test is excluded because it needs the new field to compile.
  • Local Linux verification, 2026-10-22 (Debian 13):
    • On the same change based on 3d3d10cb: both tests pass, with the rest of the contracts, core and
      MCP suites, the CLI's args tests and the daemon's integration ops
      (609 tests).
    • clippy -D warnings and rustfmt are clean.
    • At the red reference the daemon test fails, and only that test.
  • Live verification with a real daemon in a throwaway home:
    • The operator uses the cccc CLI and the daemon socket; a foreman (a real
      actor process) adds a peer through the cccc mcp stdio server.
    • With 0.4.44 and upstream main, 8 of the 9 checks fail. --model is an
      unexpected argument on add and update; a model sent over the socket or
      MCP is accepted and dropped; a 129-character label and one with a newline
      are accepted and dropped. The ninth check, that a labelled Actor starts
      and runs, is a control and passes everywhere.
    • With this build all 9 pass, including the label surviving a daemon
      restart.
  • GitHub Actions CI on the fork at exact current PR head d4619924bb4fa3e4a0240ebb5c67c2ac2abac2fb passed all six jobs, including rust-linux, windows-smoke, web, quality, package and ci-required: run 39771682941.

Tested on: fork CI, GitHub-hosted ubuntu-26.04 runner (Ubuntu 26.04.1 LTS,
image 20261012.163.1; the job log does not name the CPU).

Which model an Actor runs is visible today only inside its command line,
as a runtime-specific flag, and not at all for Actors whose command does
not name one. A board or a foreman that wants to choose between Actors by
model has to parse commands, and a `model` key sent to actor_add or
actor_update is dropped without an error.

An Actor now carries an optional `model` label: set on actor_add, changed
or cleared (with an empty string) on actor_update, returned on actor_list
rows and in the actor.add event. It is trimmed and limited to 128
characters without control characters. It is a label for people and
tools; launching does not read it. The CLI gains `--model` on `actor add`
and `actor update`, and the MCP `cccc_actor` schema describes the key.
Main's retry-safe task creation appended a daemon test where this branch
appended its own; both tests are kept.
@ChesterRa

Copy link
Copy Markdown
Owner

Thanks for this contribution and the careful validation. Making an Actor’s model easier to identify is a useful goal, and I understand that this field is intentionally metadata only.

My hesitation is with the public semantics: --model looks like launch configuration, while this value neither selects nor verifies the running model and can become stale after a model switch.

Before asking you to revise the patch, could you share the concrete workflow that needs a separate machine-readable model declaration rather than the existing Actor title? If that distinction is necessary, we could discuss an explicitly named model_label, with clear operator-supplied semantics.

I’d prefer to settle that requirement first. Please don’t expand this into runtime-specific command parsing or database inspection; keeping the integration small is important to us.

@chriscoveries

Copy link
Copy Markdown
Contributor Author

The concrete workflow is an external work allocator. It reads Actor availability, joins each Actor to an operator-maintained model table, and uses that table’s cost/ranking preferences when placing work. We already do that lookup outside CCCC; the association currently comes from our own configuration and command-line conventions. A separate field would give clients a common read surface for that declaration without putting allocation policy in CCCC.

The Actor title is the human-facing role/name. Using it as the model key would couple display naming to the allocator’s configuration: role titles and model declarations can change independently.

I agree that --model suggests launch configuration. model_label would describe the intended contract more accurately: an optional operator-supplied declaration, not an observation or guarantee of the model actually serving a turn. The operator would need to update or clear it after a model change; an absent label means undeclared. It would not drive launching or provide billing evidence, and this would add no runtime-specific command parsing or database inspection.

If this workflow is in scope, I’m happy to discuss model_label with those semantics before revising the patch.

@ChesterRa

Copy link
Copy Markdown
Owner

Thanks for clarifying the allocator workflow. That gives the separate field a concrete purpose, and your point about keeping role titles independent from model declarations makes sense.

I’m comfortable reviewing a narrowly scoped revision using model_label and --model-label.

Please keep the contract explicit: this is an optional, operator-maintained declaration. Absence means undeclared; it neither configures launching nor verifies the model serving a turn. Updating the label should not restart the Actor or alter its launch configuration.

Please rename the field consistently across the contracts, CLI, MCP surface, documentation, and tests, without retaining the unmerged model name as an alias. Cost tables, rankings, allocation policy, and runtime detection should remain outside this change.

Focused coverage for persistence, validation, clearing, and unchanged runtime behavior would be appropriate. No additional model registry or automatic synchronization is needed. Once revised, we can review the implementation against that scope.

Preserve native-session launch guards while reconciling Actor arguments and validation. Use model_label and --model-label consistently without a model alias, and cover launch settings remaining unchanged.
@ChesterRa
ChesterRa merged commit b5743a3 into ChesterRa:main Oct 30, 2026
7 checks passed
@chriscoveries
chriscoveries deleted the feat/actor-model-v2 branch November 3, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants