T-126: C clide shell client + _argv unwrap in the dispatcher
Third slice of T-99. After this `clide status` actually does
something when typed in a shell.
* native/clide-cli/clide.c — ~250 LOC C. Walks CWD up to .git,
hashes the workspace root with FNV-1a 64-bit (byte-for-byte
identical to the Dart side, pinned via reference vectors in
paths_test.dart), opens the per-workspace socket, and ships argv
across the wire as `{cmd:"_argv", args:{argv:[...]}}`.
* lib/src/cli/argv_dispatch.dart — registers the `_argv` sentinel
command on the dispatcher. The handler runs the T-125 parser on
the embedded argv and either re-dispatches the unwrapped request
through the same dispatcher or returns the pre-built error
response. Keeps the parser in Dart so the C side stays dumb.
* lib/src/ipc/paths.dart — fnv1a64Hex hoisted to a public helper +
fixed to format as unsigned (Dart `int` is signed int64; the high
bit lit a leading minus that broke the cross-language compare).
Reference-vector tests added against the FNV reference.
* `make clide-cli` builds it via the host `cc`; output lands at
native/<platform>/clide and is gitignored. Test
test/cli/clide_cli_e2e_test.dart compiles + exercises the full
round-trip; skips cleanly when no cc is on PATH.
* CONTRIBUTING.md gets a "C clide shell client" section.
T-128 (delete legacy IPC) unblocked.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1856,3 +1856,5 @@ INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by,
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-124', 'status', 'in_progress', 'done', NULL, '2026-05-18 12:51:08', '2026-05-18 12:51:08', '2026-05-18 12:51:08', NULL, 'b928ce09ae0b7dbb77bf93f8c0593657', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-125', 'status', 'backlog', 'in_progress', NULL, '2026-05-18 15:49:20', '2026-05-18 15:49:20', '2026-05-18 15:49:20', NULL, 'ac0838fac9e3c97f1728256910776bed', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-125', 'status', 'in_progress', 'done', NULL, '2026-05-18 15:51:09', '2026-05-18 15:51:09', '2026-05-18 15:51:09', NULL, '938624de487aa2f02e034424cae40c77', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-126', 'status', 'backlog', 'in_progress', NULL, '2026-05-18 15:54:20', '2026-05-18 15:54:20', '2026-05-18 15:54:20', NULL, '3266e7ea943867f49ff20a90b7f12ae6', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-126', 'status', 'in_progress', 'done', NULL, '2026-05-18 16:04:29', '2026-05-18 16:04:29', '2026-05-18 16:04:29', NULL, 'b6c783f599585e55ecc36f69ccbcefb1', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -2122,3 +2122,15 @@ Acceptance:
|
||||
4. Sysexit-code parity with pql (0/1/2/3/4 + 64-78 reserved).
|
||||
|
||||
Source: T-99 sketch.', 'done', 'high', NULL, NULL, NULL, '2026-05-18 11:58:52', '2026-05-18 15:51:09', NULL, '99f60de735779ddc37e7701ef4dd3304', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (id, type, parent_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-126', 'task', 'T-99', 'thin C `clide` client binary in native/clide-cli/', 'Third slice of T-99(a). The user-facing entry point.
|
||||
|
||||
~150 LOC of C in native/clide-cli/. Resolves the socket path (env override + default), connects, sends a single JSON-line request shaped as {"argv": [...]} (parsing happens in Dart per T-125), reads the JSON-line response, writes stdout/stderr per the pql contract, exits with the response''s exit code.
|
||||
|
||||
Acceptance:
|
||||
1. native/clide-cli/clide compiles on Linux + macOS via the existing native build harness (same shape as dugite / libtree-sitter.so).
|
||||
2. Binary lands in the install bundle; runs from the user''s PATH after `make build-linux` / `make build-macos`.
|
||||
3. `clide status` against a running app returns the status JSON and exits 0.
|
||||
4. `clide nonsense` returns the right exit code (sysexit 64 = usage error per D-6).
|
||||
5. Documented in assets/licenses.yaml + a one-paragraph note in CONTRIBUTING.md.
|
||||
|
||||
Source: T-99 sketch. Depends on T-124 (server) + T-125 (argv translator).', 'done', 'high', NULL, NULL, NULL, '2026-05-18 11:58:57', '2026-05-18 16:04:29', NULL, 'e4be31e3d80dbaadd64e3a4a2fa029e0', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
Reference in New Issue
Block a user