feat: register Workspace Profiles as Decodal values (T-710)

Project the evaluated Workspace Profile value into a revision-bound JSON archive without source-path registration or Decodal re-evaluation. Preserve partial-value omissions and explicit overrides, validate before save, and reject legacy registrations with a documented explicit migration.

Fix array-element schema completion and provide fingerprint-bound authoring shapes independently of materialization defaults. Carry metadata through REST, regenerate TypeScript/OpenAPI/WASM artifacts, and exercise save/projection/Runtime consumption and persisted Manifest restore boundaries.

Validation: root cargo check; cargo test -p config-source; cargo test -p worker-runtime; cargo test -p server-api --features typescript; focused profile_settings/value_profiles/archive tests; 39 web config-source/profile API tests; deno task check; cargo fmt --all -- --check; git diff --check HEAD.

Full workspace-server test: 641 passed, one pre-existing ticket_checker_suppresses_stale_and_clean_results_and_diagnoses_invalid_output assertion failure. The same filter fails at base 3c424fd17d in a separately archived source tree and isolated target directory. Remaining server crate tests pass with only that filter skipped (641 lib + 11 bin); unrelated checker code is unchanged.
This commit is contained in:
2026-10-07 00:14:51 +09:00
parent 3c424fd17d
commit 58462d5844
24 changed files with 1708 additions and 319 deletions
@@ -0,0 +1,72 @@
# Completion-only shape of partial Profile values. This is never materialized or
# used as defaults: omitted fields remain omitted until Manifest resolution.
let
Flag = { enabled = Bool; };
Model = {
ref = String; scheme = String; base_url = String; model_id = String;
auth = { kind = String; ref = String; file = String; };
capability = Unknown; context_window = Int; max_context_window = Int;
};
Extraction = {
enabled = Bool; model = Model; reasoning = String;
threshold = Int; worker_max_turns = Int;
};
Scope = { intent = String; deny_write = [...String]; symlink_policy = String; };
Profile = {
slug = String;
description = String;
worker = { mode = String; };
model = Model;
engine = {
instruction = String; language = String; reasoning = Unknown;
max_tokens = Int; max_turns = Int; temperature = Unknown; top_p = Unknown;
top_k = Int; stop_sequences = [...String]; tool_call_dispatch = String;
tool_output = { default_max_bytes = Int; per_tool = { ...Int }; };
file_upload = { max_bytes = Int; };
};
scope = Scope;
delegation_scope = Scope;
session = {
record_event_trace = Bool;
};
permissions = { default_action = String; rule = [...{ tool = String; pattern = String; action = String; }]; };
feature = {
task = Flag; web = Flag; image = Flag; sub_worker = Flag; flow = Flag;
worker = { enabled = Bool; direct_spawn = Bool; };
workspace_worker_discovery = Flag; objective = Flag; manage_workdir = Flag;
workdir_catalog = Flag; workspace_config = Flag; orchestration = Flag;
ticket = { enabled = Bool; authoring = Bool; thread = Bool; intake = Bool; workflow = Bool; };
merge_request = { show = Bool; open = Bool; review = Bool; readiness_check = Bool; complete = Bool; };
memory = {
enabled = Bool; staging_tools = Bool;
resident = { inject_summary = Bool; };
extraction = Extraction;
consolidation = { request_enabled = Bool; };
};
subjektiv = { enabled = Bool; consolidation_tools = Bool; extraction = Extraction; };
};
mcp = { stdio_server = [...{
name = String; command = String; args = [...String];
cwd = { kind = String; path = String; };
env = { inherit = [...String]; set = { ...Unknown }; };
}]; };
compaction = {
kind = String; threshold = Unknown; request_threshold = Unknown;
prune_enabled = Bool; worker_context_max_tokens = Unknown;
worker_max_turns = Int; model = Model;
};
web = {
enabled = Bool; allow_private_addresses = Bool;
search = { enabled = Bool; provider = String; api_key_secret = String; timeout_secs = Int; base_url = String; country = String; search_lang = String; ui_lang = String; safesearch = String; };
fetch = { enabled = Bool; timeout_secs = Int; redirect_limit = Int; max_response_bytes = Int; max_output_bytes = Int; allow_private_addresses = Bool; };
};
skills = { directories = [...String]; };
};
in {
profile = {
default_profile = String;
entries = [...{
selector = String; profile = Profile; label = String; description = String;
}];
};
}
+11
View File
@@ -0,0 +1,11 @@
{
profile = {
default_profile = String default "builtin:companion";
entries = [...{
selector = String;
profile = { ...Unknown };
label = String default "";
description = String default "";
}] default [];
};
}