Ctrl K
ComunidadGuías…

tests/contract/agent-ergonomics.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from "node:assert/strict";
import { CASES } from "./cases";

function expectError(res: { status: number; body: any }, status: number, code: string) {
  assert.equal(res.status, status, JSON.stringify(res.body));
  assert.equal(res.body.error.code, code);
}

CASES.push({
  name: "agent ergonomics explain fences, fill one project, and reassign private principals",
  async run(fx) {
    const owner = await fx.provision({ scopes: ["*"], principalId: "agent_owner" });
    const shared = await fx.call("POST", "/v1/projects/resolve", {
      key: owner.key,
      body: { reference: "owner/shared", create: true, default_visibility: "organization" },
    });
    assert.equal(shared.status, 201, JSON.stringify(shared.body));
    const profile = await fx.call("POST", "/v1/projects/resolve", {
      key: owner.key,
      body: { reference: "owner/profile-agent", create: true },
    });
    assert.equal(profile.status, 201, JSON.stringify(profile.body));
    const sharedId = shared.body.data.project_id as string;
    const profileId = profile.body.data.project_id as string;

    const many = await fx.call("POST", "/v1/keys", {
      key: owner.key,
      body: {
        label: "two projects",
        principal_id: "agent_many",
        max_trust: "asserted",
        scopes: ["observations:write", "claims:write", "context:compile", "mcp:call", "projects:resolve"],
        write_subjects: ["team:shared", "team:profile:agent_a"],
        write_projects: [sharedId, profileId],
      },
    });
    assert.equal(many.status, 201, JSON.stringify(many.body));
    const manyKey = many.body.data.api_key as string;

    const missingProject = await fx.call("POST", "/v1/observations", {
      key: manyKey,
      body: {
        subject_id: "team:profile:agent_a",
        kind: "user_statement",
        content: "A fenced write must name its project.",
        source: { type: "chat", ref: "note-1" },
        visibility: "organization",
      },
    });
    expectError(missingProject, 403, "FORBIDDEN");
    assert.equal(missingProject.body.meta.reason, "project_fence");
    assert.equal(missingProject.body.meta.failed, "project_id");
    assert.equal(missingProject.body.meta.got, null);
    assert.deepEqual(missingProject.body.meta.allowed_projects, [profileId, sharedId].sort());
    assert.match(missingProject.body.error.message, /project_id is required/);

    const wrongSubject = await fx.call("POST", "/v1/observations", {
      key: manyKey,
      body: {
        subject_id: "team:profile:agent_b",
        project_id: sharedId,
        kind: "user_statement",
        content: "A fenced write must name an allowed subject.",
        source: { type: "chat", ref: "note-2" },
        visibility: "organization",
      },
    });
    expectError(wrongSubject, 403, "FORBIDDEN");
    assert.equal(wrongSubject.body.meta.failed, "subject_id");
    assert.equal(wrongSubject.body.meta.reason, "subject_fence");

    const trust = await fx.call("POST", "/v1/observations", {
      key: manyKey,
      body: {
        subject_id: "team:shared",
        project_id: sharedId,
        kind: "user_statement",
        content: "Verified trust is above this key.",
        source: { type: "chat", ref: "note-3" },
        trust: "verified",
        visibility: "organization",
      },
    });
    expectError(trust, 403, "FORBIDDEN");
    assert.equal(trust.body.meta.reason, "trust_ceiling");
    assert.deepEqual(trust.body.meta.allowed_trust, ["unverified", "asserted"]);

    const missing = await fx.call("POST", "/v1/context/compile", { key: manyKey, body: {} });
    expectError(missing, 400, "VALIDATION_ERROR");
    const missingFields = (missing.body.meta.fields as Array<{ field: string }>).map((field) => field.field);
    assert.deepEqual(missingFields, ["subject_id", "task", "max_tokens"]);

    const aliased = await fx.call("POST", "/v1/context/compile", {
      key: manyKey,
      body: { subject: "team:shared", query: "shared notes", max_tokens: 800 },
    });
    assert.equal(aliased.status, 200, JSON.stringify(aliased.body));
    assert.deepEqual(aliased.body.meta.deprecated_fields, ["subject", "query"]);
    assert.match(aliased.body.data.scope.hint, /not project-scoped/);
    assert.match(aliased.body.data.scope.hint, new RegExp(sharedId));
    assert.equal(aliased.body.meta.degraded.reason.length > 0, true);
    assert.match(aliased.body.meta.consistent_as_of, /^\d{4}-/);
    assert.equal(aliased.body.meta.read_your_writes, "sql_fts");

    const one = await fx.call("POST", "/v1/keys", {
      key: owner.key,
      body: {
        label: "one project",
        principal_id: "agent_a",
        max_trust: "asserted",
        scopes: ["observations:write", "claims:write", "context:compile", "mcp:call", "projects:resolve"],
        write_subjects: ["team:profile:agent_a"],
        write_projects: [profileId],
      },
    });
    assert.equal(one.status, 201, JSON.stringify(one.body));
    const oneKey = one.body.data.api_key as string;
    const remembered = await fx.call("POST", "/v1/observations", {
      key: oneKey,
      body: {
        subject_id: "team:profile:agent_a",
        kind: "user_statement",
        content: "One fenced project is filled in.",
        source: { type: "chat", ref: "note-4" },
        visibility: "organization",
        consolidate: true,
        tz: "Asia/Bangkok",
      },
    });
    assert.equal(remembered.status, 201, JSON.stringify(remembered.body));
    assert.equal(remembered.body.data.project_id, profileId);
    assert.equal(remembered.body.data.project_id_source, "key_fence");
    assert.match(remembered.body.data.ingested_at_local, /\+07:00$/);
    assert.match(remembered.body.data.ingested_at, /Z$/);

    const compiled = await fx.call("POST", "/v1/context/compile", {
      key: oneKey,
      body: {
        subject_id: "team:profile:agent_a",
        task: "filled project",
        max_tokens: 800,
        tz: "Asia/Bangkok",
      },
    });
    assert.equal(compiled.status, 200, JSON.stringify(compiled.body));
    assert.equal(compiled.body.data.scope.project_id, profileId);
    assert.equal(compiled.body.data.scope.project_id_source, "key_fence");
    assert.equal(compiled.body.data.scope.project_mode, "project");
    assert.match(compiled.body.data.scope.as_of_local, /\+07:00$/);
    assert.equal(compiled.body.data.budget.unconsolidated_observations, 0);
    const tight = await fx.call("POST", "/v1/context/compile", {
      key: oneKey,
      body: { subject_id: "team:profile:agent_a", task: "filled project", max_tokens: 128 },
    });
    assert.equal(tight.status, 200, JSON.stringify(tight.body));
    if (tight.body.data.items.length === 0 && tight.body.data.budget.budget_exhausted === true)
      assert.match(tight.body.data.budget.hint, /increase max_tokens/);

    const pending = await fx.call("POST", "/v1/observations", {
      key: oneKey,
      body: {
        subject_id: "team:profile:agent_a",
        kind: "user_statement",
        content: "This note still needs a claim.",
        source: { type: "chat", ref: "note-5" },
        visibility: "organization",
      },
    });
    assert.equal(pending.status, 201, JSON.stringify(pending.body));
    const empty = await fx.call("POST", "/v1/context/compile", {
      key: oneKey,
      body: { subject_id: "team:profile:agent_a", task: "pending note", max_tokens: 800 },
    });
    assert.equal(empty.status, 200, JSON.stringify(empty.body));
    assert.equal(empty.body.data.budget.unconsolidated_observations, 1);
    assert.deepEqual(empty.body.data.budget.unconsolidated_observation_ids, [pending.body.data.observation_id]);
    assert.match(empty.body.data.budget.hint, /titen_consolidate/);

    const archival = await fx.call("POST", "/v1/observations", {
      key: oneKey,
      body: {
        subject_id: "team:profile:agent_a",
        kind: "imported_source",
        content: "An archival note dated before standard time.",
        source: { type: "test", ref: "archive:1900" },
        visibility: "organization",
        occurred_at: "1900-01-01T00:00:00Z",
        tz: "Asia/Jakarta",
      },
    });
    assert.equal(archival.status, 201, JSON.stringify(archival.body));
    assert.equal(archival.body.data.occurred_at_local, "1900-01-01T07:07:00.000+07:07");
    assert.equal(Date.parse(archival.body.data.occurred_at_local), Date.parse("1900-01-01T00:00:00Z"));

    const subjectLookup = await fx.call("POST", "/v1/projects/resolve", {
      key: oneKey,
      body: { reference: "team:profile:agent_a" },
    });
    assert.equal(subjectLookup.status, 200, JSON.stringify(subjectLookup.body));
    assert.equal(subjectLookup.body.data.matched, "subject");
    assert.deepEqual(subjectLookup.body.data.projects, [{
      project_id: profileId,
      reference: "owner/profile-agent",
      default_visibility: "private",
    }]);

    const suggestion = await fx.call("POST", "/v1/projects/resolve", {
      key: oneKey,
      body: { reference: "owner/profile-agen" },
    });
    expectError(suggestion, 404, "NOT_FOUND");
    assert.deepEqual(suggestion.body.meta.suggestions, [{
      project_id: profileId,
      reference: "owner/profile-agent",
      default_visibility: "private",
    }]);

    const who = await fx.call("GET", "/v1/principal", { key: oneKey });
    assert.equal(who.status, 200, JSON.stringify(who.body));
    assert.equal(who.body.data.principal_id, "agent_a");
    assert.deepEqual(who.body.data.allowed_trust, ["unverified", "asserted"]);
    assert.equal(JSON.stringify(who.body).includes(oneKey), false);
    assert.equal(who.body.data.projects[0].reference, "owner/profile-agent");
    const mcpWho = await fx.call("POST", "/mcp", {
      key: oneKey,
      body: { jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "titen_whoami", arguments: {} } },
    });
    assert.equal(mcpWho.status, 200, JSON.stringify(mcpWho.body));
    const whoText = mcpWho.body.result.content[0].text as string;
    assert.equal(whoText.includes(oneKey), false);
    assert.match(whoText, /agent_a/);
    assert.equal(mcpWho.body.result.isError, undefined);

    const writer = await fx.provision({
      orgId: owner.orgId,
      principalId: "agent_old",
      scopes: ["observations:write", "context:compile"],
    });
    const kept = await fx.call("POST", "/v1/observations", {
      key: writer.key,
      body: {
        subject_id: "team:shared",
        kind: "decision",
        content: "Private note that should follow the principal.",
        source: { type: "chat", ref: "note-6" },
        visibility: "private",
      },
    });
    assert.equal(kept.status, 201, JSON.stringify(kept.body));
    const reader = await fx.provision({
      orgId: owner.orgId,
      principalId: "agent_next",
      scopes: ["observations:write", "context:compile", "claims:write"],
    });
    const before = await fx.call("POST", "/v1/context/compile", {
      key: reader.key,
      body: { subject_id: "team:shared", task: "private note", max_tokens: 800 },
    });
    assert.equal(before.body.data.budget.unconsolidated_observations, 0);
    const preview = await fx.call("POST", "/v1/principals/reassign", {
      key: owner.key,
      body: { from: "agent_old", to: "agent_next", dry_run: true },
    });
    assert.equal(preview.status, 200, JSON.stringify(preview.body));
    assert.equal(preview.body.data.dry_run, true);
    assert.equal(preview.body.data.observations, 1);
    const stillOld = await fx.query<{ actor_id: string }>(
      "SELECT actor_id FROM observations WHERE id = ?",
      [kept.body.data.observation_id],
    );
    assert.equal(stillOld[0]?.actor_id, "agent_old");
    const moved = await fx.call("POST", "/v1/principals/reassign", {
      key: owner.key,
      body: { from: "agent_old", to: "agent_next" },
    });
    assert.equal(moved.status, 200, JSON.stringify(moved.body));
    assert.equal(moved.body.data.observations, 1);
    const after = await fx.call("POST", "/v1/context/compile", {
      key: reader.key,
      body: { subject_id: "team:shared", task: "private note", max_tokens: 800 },
    });
    assert.equal(after.body.data.budget.unconsolidated_observations, 1);
    assert.deepEqual(after.body.data.budget.unconsolidated_observation_ids, [kept.body.data.observation_id]);
    const outsider = await fx.provision();
    expectError(await fx.call("POST", "/v1/principals/reassign", {
      key: outsider.key,
      body: { from: "agent_old", to: "agent_next" },
    }), 403, "FORBIDDEN");

    const ready = await fx.call("GET", "/readyz");
    assert.equal(ready.status, 200, JSON.stringify(ready.body));
    assert.equal(typeof ready.body.data.version, "string");
    assert.equal(ready.body.data.schema_version, ready.body.data.schema.applied);
  },
});