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
325 changes: 325 additions & 0 deletions .agents/plugins/evaluations/contentcloud-video-production-0.15.0.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions .agents/plugins/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
{
"id": "contentcloud-video-production",
"kind": "scene_plugin",
"version": "0.14.0",
"version": "0.15.0",
"source": {
"repository": "https://github.com/limecloud/contentcloud",
"ref": "v0.14.0"
"ref": "v0.15.0"
},
"license": "Apache-2.0",
"digest": "sha256:f6fd78c173966c35685189131f7a555abbe06fa8d13f528df45490570a3c15e0",
"digest": "sha256:7d58f6af20d63ea3b7a86b39978be095381efc0a2431facf5de62606248ffa82",
"signature": {
"status": "verified",
"algorithm": "ed25519",
"key_id": "contentcloud-plugin-release-2026-07",
"value": "/hM3xQ6XzpymgxsJSYj9FPVuCW71hw2hkPUMNnJen+ZdEoVJ4VYRZJHG8QkZZ+rI+aLQ5HonvMs0NxPjbMK5BA=="
"value": "xvS3+Wk297LLlOSrU3GoLNN4AoHF+vOysq/E/gqcJ10JxoPanaFSd+zb0QOBRl+++GeW+n7SOQpCuw8W9gdcDQ=="
},
"compatible_profiles": [
"contentcloud.video-production"
Expand Down Expand Up @@ -54,8 +54,8 @@
],
"evaluation": {
"status": "passed",
"report": ".agents/plugins/evaluations/contentcloud-video-production-0.14.0.json",
"digest": "sha256:32ba3746cd5bba43d4192b2acc988b46f72c9633ab99c29fed4e35af4e9772d4",
"report": ".agents/plugins/evaluations/contentcloud-video-production-0.15.0.json",
"digest": "sha256:e71936aad416a6bc94712fb66fe8bc96293529ca6442fffea2026b7b3c28f2f4",
"evidence": [
"codex-plugin-transaction",
"bootstrap-confirmation",
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

ContentCloud 的重要变更记录在此文件中。

## [0.15.0] - 2026-08-03

### Added

- 增加首次连接后的项目简报入口,让项目、素材、知识和内容生产沿一条可恢复的本地业务链路推进。
- 增加 `workspace_context` 的结构化 onboarding 状态与 `workspace_project_brief`,项目简报确认后写入共享业务上下文。

### Changed

- 新会话在项目简报确认前只展示一个业务下一步,避免把内部工具和未准备好的任务入口同时暴露给用户。
- 工作区 MCP、Codex 接入、Plugin、Web、Environment Profile 和 CLI 安装器统一升级到 `0.15.0`。
- 项目服务计划默认声明 SOP 可配置、审批可选,后续规则由管理后台和工作区配置承载。

### Fixed

- 修复已连接工作区没有明确下一步、连接链路与首次业务流程断开的问题。
- 收敛后台工作区和知识库标签,减少重复入口和含义不清的英文文案。

## [0.14.0] - 2026-08-02

### Added
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.14.0
0.15.0
2 changes: 1 addition & 1 deletion deploy/systemd/contentcloud.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ CONTENTCLOUD_PLUGIN_TRUST_FILE=/etc/contentcloud/plugin-trusted-keys.json
CONTENTCLOUD_ENVIRONMENT_TRUST_FILE=/etc/contentcloud/environment-trusted-keys.json
CONTENTCLOUD_ENVIRONMENT_SIGNING_KEY_FILE=/etc/contentcloud/secrets/environment-ed25519.key
CONTENTCLOUD_ENVIRONMENT_SIGNING_KEY_ID=contentcloud-environment-2026-07
CONTENTCLOUD_CAPABILITY_RELEASE_VERSION=0.14.0
CONTENTCLOUD_CAPABILITY_RELEASE_VERSION=0.15.0
CONTENTCLOUD_ENVIRONMENT_MANIFEST_TTL=24h
2 changes: 1 addition & 1 deletion deploy/systemd/environment-profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"id": "contentcloud-video-production",
"kind": "scene_plugin",
"version": "0.14.0",
"version": "0.15.0",
"required": true,
"scope": "environment",
"capabilities": [
Expand Down
2 changes: 1 addition & 1 deletion docs/roadmap/v6/02-runtime-and-content-packs.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Content Pack 不能把领域事实藏在 prompt 中。Prompt 只能编排已声
{
"tenant_id": "tenant_x",
"workspace_id": "workspace_x",
"runtime": {"client": "codex", "version": "0.14.0", "status": "ready"},
"runtime": {"client": "codex", "version": "0.15.0", "status": "ready"},
"content_packs": [
{"id": "video_script", "state": "enabled", "digest": "sha256:..."},
{"id": "wechat_article", "state": "disabled", "reason_code": "tenant_not_enabled"}
Expand Down
4 changes: 2 additions & 2 deletions internal/app/automation_environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ func TestAutomationPollRequiresVerifiedEnvironmentPackAndCapabilityBeforeLease(t
assertDomainCode(t, err, "ENVIRONMENT_PREPARATION_REQUIRED")
assertRunUnleased(t, ctx, service, store, actor, run.ID)

lease, err := service.PollWithRuntime(ctx, deviceActor, device, []domain.Capability{capability}, []app.AutomationEnvironmentClaim{{Manifest: manifest, Lock: lock}}, "0.14.0")
lease, err := service.PollWithRuntime(ctx, deviceActor, device, []domain.Capability{capability}, []app.AutomationEnvironmentClaim{{Manifest: manifest, Lock: lock}}, "0.15.0")
must(t, err)
if lease.Run.ID != run.ID || lease.ExecutionBundle == nil || lease.ExecutionBundle.BundleID != bundle.BundleID || lease.Attempt.CapabilityDigest != requirement.Digest {
t.Fatalf("verified environment did not receive the exact bundle-bound lease: %#v", lease)
}
devices, err := service.Devices(ctx, actor, project.ID)
must(t, err)
if len(devices) != 1 || devices[0].Version != "0.14.0" {
if len(devices) != 1 || devices[0].Version != "0.15.0" {
t.Fatalf("daemon poll did not refresh the running CLI version: %#v", devices)
}
verifier, err := environment.NewVerifier([]environment.TrustedKey{{KeyID: "environment-automation-test", Status: "active", PublicKey: publicKey}})
Expand Down
2 changes: 1 addition & 1 deletion internal/capabilityrouting/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func SHA256() string {
}

func MCPInstructions() string {
return "ContentCloud 创作路由(version " + Version + ",sha256 " + SHA256() + "):\n- " + strings.Join(rules, "\n- ")
return "ContentCloud 创作路由(version " + Version + ",sha256 " + SHA256() + "):\n- " + strings.Join(rules, "\n- ") + "\n- 首次进入且 onboarding.state 为 needs_project_brief 时,只收集并确认项目简报;确认后重新读取 workspace_context,只展示 onboarding.next_step。"
}

func ManagedBlock() string {
Expand Down
18 changes: 9 additions & 9 deletions internal/cli/bootstrap_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestBootstrapPlanIsReadOnlyAndUsesOnlyPublicSessionID(t *testing.T) {
if err := json.Unmarshal(stdout.Bytes(), &envelope); err != nil {
t.Fatalf("decode output: %v; output=%s", err, stdout.String())
}
if !envelope.OK || envelope.Data.State != "ready" || !strings.HasPrefix(envelope.Data.PlanID, "bp_") || envelope.Data.CLIPackage != "@limecloud/contentcloud@0.14.0" || len(envelope.Data.Plugin.Actions) != 2 || !envelope.Data.WouldEnableDaemon {
if !envelope.OK || envelope.Data.State != "ready" || !strings.HasPrefix(envelope.Data.PlanID, "bp_") || envelope.Data.CLIPackage != "@limecloud/contentcloud@0.15.0" || len(envelope.Data.Plugin.Actions) != 2 || !envelope.Data.WouldEnableDaemon {
t.Fatalf("unexpected plan: %s", stdout.String())
}
if strings.Contains(stdout.String(), "connect_key") || envelope.Data.AuthorizationMode != "browser_device" || !envelope.Data.WouldAuthorizeDevice {
Expand Down Expand Up @@ -469,8 +469,8 @@ func TestBootstrapApplyRejectsPlanAfterCodexStateChanges(t *testing.T) {
t.Setenv("CONTENTCLOUD_CONFIG_PATH", filepath.Join(t.TempDir(), "config.json"))
approvedPlanID := bootstrapPlanIDForTest(t, directory, "https://content.example.com")
runner := &bootstrapRunner{responses: []bootstrapRunnerResponse{
{stdout: `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.14.0"}}]}`},
{stdout: `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.14.0","installed":true,"enabled":true}],"available":[]}`},
{stdout: `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.15.0"}}]}`},
{stdout: `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.15.0","installed":true,"enabled":true}],"available":[]}`},
}}
root := &Root{stdout: &bytes.Buffer{}, stderr: &bytes.Buffer{}, codexRunner: runner, bootstrapCheckHook: healthyBootstrapCheck}
command := root.command()
Expand Down Expand Up @@ -535,30 +535,30 @@ func TestRequireHealthyWorkspaceBlocksRegistration(t *testing.T) {
func successfulBootstrapRunner() *bootstrapRunner {
missingMarketplace := `{"marketplaces":[]}`
missingPlugin := `{"installed":[],"available":[]}`
currentMarketplace := `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.14.0"}}]}`
currentPlugin := `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.14.0","installed":true,"enabled":true}],"available":[]}`
currentMarketplace := `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.15.0"}}]}`
currentPlugin := `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.15.0","installed":true,"enabled":true}],"available":[]}`
return &bootstrapRunner{responses: []bootstrapRunnerResponse{
{stdout: missingMarketplace}, {stdout: missingPlugin},
{stdout: missingMarketplace}, {stdout: missingPlugin},
{stdout: `{"marketplaceName":"contentcloud","installedRoot":"/tmp/cache","alreadyAdded":false}`},
{stdout: `{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.14.0","installedPath":"/tmp/plugin"}`},
{stdout: `{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.15.0","installedPath":"/tmp/plugin"}`},
{stdout: currentMarketplace}, {stdout: currentPlugin},
}}
}

func successfulBootstrapUpgradeRunner() *bootstrapRunner {
oldMarketplace := `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache-old","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.7.0"}}]}`
oldPlugin := `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.7.0","installed":true,"enabled":true}],"available":[]}`
currentMarketplace := `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.14.0"}}]}`
currentPlugin := `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.14.0","installed":true,"enabled":true}],"available":[]}`
currentMarketplace := `{"marketplaces":[{"name":"contentcloud","root":"/tmp/cache","marketplaceSource":{"sourceType":"git","source":"limecloud/contentcloud","ref":"v0.15.0"}}]}`
currentPlugin := `{"installed":[{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.15.0","installed":true,"enabled":true}],"available":[]}`
return &bootstrapRunner{responses: []bootstrapRunnerResponse{
{stdout: oldMarketplace}, {stdout: oldPlugin},
{stdout: oldMarketplace}, {stdout: oldPlugin},
{stdout: oldMarketplace}, {stdout: oldPlugin},
{stdout: `{}`},
{stdout: `{}`},
{stdout: `{"marketplaceName":"contentcloud","installedRoot":"/tmp/cache","alreadyAdded":false}`},
{stdout: `{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.14.0","installedPath":"/tmp/plugin"}`},
{stdout: `{"pluginId":"contentcloud-video-production@contentcloud","name":"contentcloud-video-production","marketplaceName":"contentcloud","version":"0.15.0","installedPath":"/tmp/plugin"}`},
{stdout: currentMarketplace}, {stdout: currentPlugin},
}}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/daemon_runtime_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestDaemonRuntimeTrackerPersistsNonSecretHealthAndUpdatePolicy(t *testing.T
if err != nil {
t.Fatal(err)
}
tracker.recordPoll(app.DaemonRuntimePolicy{CurrentVersion: "0.10.0", LatestVersion: "0.14.0", UpdateAvailable: true}, true, nil)
tracker.recordPoll(app.DaemonRuntimePolicy{CurrentVersion: "0.10.0", LatestVersion: "0.15.0", UpdateAvailable: true}, true, nil)
tracker.taskStarted()
tracker.taskFinished(nil)
state, err := loadDaemonRuntimeState()
Expand Down
8 changes: 4 additions & 4 deletions internal/cli/daemon_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ func TestLaunchdDaemonStartIsIdempotentAndVersionAware(t *testing.T) {
t.Fatalf("idempotent start restarted daemon: state=%#v error=%v calls=%#v", state, err, calls)
}

upgraded := &launchdDaemonService{home: home, executable: "/opt/contentcloud-0.14.0", version: "0.14.0", uid: 501, now: func() time.Time { return now.Add(time.Hour) }, run: runner, environment: launchEnvironment}
upgraded := &launchdDaemonService{home: home, executable: "/opt/contentcloud-0.15.0", version: "0.15.0", uid: 501, now: func() time.Time { return now.Add(time.Hour) }, run: runner, environment: launchEnvironment}
state, err = upgraded.Start()
if err != nil || state.Version != "0.14.0" || state.Executable != "/opt/contentcloud-0.14.0" || !state.Running {
if err != nil || state.Version != "0.15.0" || state.Executable != "/opt/contentcloud-0.15.0" || !state.Running {
t.Fatalf("version-aware start did not reload daemon: state=%#v error=%v", state, err)
}
wantTail := [][]string{
Expand All @@ -105,7 +105,7 @@ func TestLaunchdDaemonStartIsIdempotentAndVersionAware(t *testing.T) {
t.Fatalf("upgrade restart sequence=%#v", calls)
}
metadata, err := os.ReadFile(filepath.Join(home, "Library", "Application Support", "ContentCloud", "daemon.json"))
if err != nil || !strings.Contains(string(metadata), `"version": "0.14.0"`) {
if err != nil || !strings.Contains(string(metadata), `"version": "0.15.0"`) {
t.Fatalf("daemon metadata was not upgraded: error=%v body=%s", err, metadata)
}
}
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestLaunchdDaemonStatusKeepsLastRuntimeStateWhenStopped(t *testing.T) {
if err != nil {
t.Fatal(err)
}
tracker.recordPoll(app.DaemonRuntimePolicy{CurrentVersion: "0.10.0", LatestVersion: "0.14.0", UpdateAvailable: true}, false, nil)
tracker.recordPoll(app.DaemonRuntimePolicy{CurrentVersion: "0.10.0", LatestVersion: "0.15.0", UpdateAvailable: true}, false, nil)
service := &launchdDaemonService{
home: t.TempDir(), executable: "/opt/contentcloud", version: "0.10.0", uid: 501, now: func() time.Time { return now },
run: func(string, ...string) ([]byte, error) { return nil, errors.New("service not loaded") },
Expand Down
Loading
Loading