feat: parliament seat collaboration loop (0.9.19)
Seats publish via parliament_note, sync pushes on write, member join without stealing the chair, and worker tools are hard-gated when parliament is active. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+44
-5
@@ -30,12 +30,18 @@ int main(void) {
|
||||
err, sizeof(err));
|
||||
assert(hand && strstr(hand, "LOGIN_OK") && strstr(hand, "chair=phone-1"));
|
||||
free(hand);
|
||||
assert(cst_parliament_is_chair());
|
||||
assert(cst_parliament_sync_pending()); /* login bumps context path request */
|
||||
|
||||
cst_parliament_meta_t m;
|
||||
assert(cst_parliament_load(&m) == 0);
|
||||
assert(!strcmp(m.chair_instance, "phone-1"));
|
||||
|
||||
assert(cst_parliament_context_put("shared agenda v1") == 0);
|
||||
assert(cst_parliament_sync_pending());
|
||||
cst_parliament_sync_ack();
|
||||
assert(!cst_parliament_sync_pending());
|
||||
|
||||
hand = cst_parliament_login("correct horse battery", "laptop-2", "thinkpad",
|
||||
err, sizeof(err));
|
||||
assert(hand && strstr(hand, "handover_from=phone-1"));
|
||||
@@ -43,11 +49,37 @@ int main(void) {
|
||||
free(hand);
|
||||
assert(cst_parliament_load(&m) == 0);
|
||||
assert(!strcmp(m.chair_instance, "laptop-2"));
|
||||
assert(cst_parliament_is_chair());
|
||||
|
||||
assert(cst_parliament_session_ok(NULL, 0));
|
||||
|
||||
assert(cst_parliament_new_project("proj-b") == 0);
|
||||
/* Member seat can join without stealing the chair. */
|
||||
hand = cst_parliament_seat_join("correct horse battery", "tablet-3", "pad",
|
||||
err, sizeof(err));
|
||||
assert(hand && strstr(hand, "JOIN_OK") && strstr(hand, "role=member"));
|
||||
assert(strstr(hand, "chair=laptop-2"));
|
||||
free(hand);
|
||||
/* Join rewrote the local seat ticket to tablet-3 (this process). */
|
||||
{
|
||||
char sid[64] = {0};
|
||||
assert(cst_parliament_session_ok(sid, sizeof(sid)));
|
||||
assert(!strcmp(sid, "tablet-3"));
|
||||
assert(!cst_parliament_is_chair());
|
||||
}
|
||||
assert(cst_parliament_load(&m) == 0);
|
||||
assert(!strcmp(m.chair_instance, "laptop-2"));
|
||||
|
||||
assert(cst_parliament_context_append("tablet-3", "status",
|
||||
"ready to take the UI slice") == 0);
|
||||
char *ctx = cst_parliament_context_get();
|
||||
assert(ctx && strstr(ctx, "shared agenda v1"));
|
||||
assert(strstr(ctx, "seat=tablet-3") && strstr(ctx, "ready to take the UI"));
|
||||
free(ctx);
|
||||
assert(cst_parliament_sync_pending());
|
||||
cst_parliament_sync_ack();
|
||||
|
||||
assert(cst_parliament_new_project("proj-b") == 0);
|
||||
ctx = cst_parliament_context_get();
|
||||
assert(ctx && ctx[0] == 0);
|
||||
free(ctx);
|
||||
assert(cst_parliament_load(&m) == 0);
|
||||
@@ -55,9 +87,11 @@ int main(void) {
|
||||
assert(m.chair_instance[0] == 0);
|
||||
assert(!cst_parliament_session_ok(NULL, 0));
|
||||
|
||||
assert(cst_parliament_session_write("local-a") == 0);
|
||||
/* Claim chair so session_ok matches. */
|
||||
assert(cst_parliament_claim_chair("local-a", "dev") == 0);
|
||||
hand = cst_parliament_login("correct horse battery", "local-a", "dev", err,
|
||||
sizeof(err));
|
||||
assert(hand && strstr(hand, "LOGIN_OK"));
|
||||
free(hand);
|
||||
assert(cst_parliament_is_chair());
|
||||
assert(cst_parliament_session_ok(NULL, 0));
|
||||
assert(cst_parliament_apply_sync(9, "parl-x", "proj-c", "chair-z",
|
||||
"synced-body") == 0);
|
||||
@@ -67,17 +101,22 @@ int main(void) {
|
||||
assert(cst_parliament_load(&m) == 0);
|
||||
assert(m.revision == 9);
|
||||
assert(!strcmp(m.chair_instance, "chair-z"));
|
||||
/* Remote chair takeover clears local login ticket. */
|
||||
/* Remote chair takeover clears the demoted chair's local ticket. */
|
||||
assert(!cst_parliament_session_ok(NULL, 0));
|
||||
|
||||
char *st = cst_parliament_status_text();
|
||||
assert(st && strstr(st, "parliament"));
|
||||
assert(strstr(st, "service"));
|
||||
assert(strstr(st, "peer_sync") && strstr(st, "sealed"));
|
||||
assert(strstr(st, "role"));
|
||||
free(st);
|
||||
assert(cst_parliament_is_active());
|
||||
assert(cst_parliament_daemon_info(NULL, NULL, 0, NULL) != 0);
|
||||
|
||||
char def[64];
|
||||
assert(cst_parliament_default_instance(def, sizeof(def)) == 0);
|
||||
assert(def[0]);
|
||||
|
||||
test_rmrf(dir);
|
||||
puts("test_parliament: OK");
|
||||
return 0;
|
||||
|
||||
@@ -138,11 +138,11 @@ int main(void) {
|
||||
}
|
||||
|
||||
cJSON *all = cst_tools_schema_cfg(&cfg);
|
||||
/* Every tool the host can actually run is offered in the default profile;
|
||||
* one whose platform probe fails (the clipboard without a helper) is not. */
|
||||
/* Every tool active for this config is offered; platform-unavailable tools
|
||||
* and mode-gated tools (e.g. parliament_note outside parliament) are not. */
|
||||
int usable = 0;
|
||||
for (int i = 0; i < cst_tool_count(); i++)
|
||||
if (cst_tool_available(cst_tool_at(i), NULL, 0) == 0)
|
||||
if (cst_tool_active(&cfg, cst_tool_at(i)))
|
||||
usable++;
|
||||
EXPECT(cJSON_GetArraySize(all) == usable, "default: every usable tool");
|
||||
EXPECT(schema_has(all, "edit_file") && schema_has(all, "grep") &&
|
||||
|
||||
Reference in New Issue
Block a user