loopctl-mcp-server 2.69.0 → 2.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/index.js +58 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -266,8 +266,8 @@ Epic 39 Repo Coordination Bus — a lightweight, tenant-isolated channel for age
|
|
|
266
266
|
| `knowledge_random_walk` | Random walk through the link graph from `start_id` (no cycles, up to `length` nodes), traversing only **agent's visible published articles**, surfacing unexpected connections. Agent callers see only their own and `shared` articles. Returns `{id, title, category}` in walk order. Required: `start_id`. Optional: `length` (default 4, max 25). |
|
|
267
267
|
| `knowledge_conflicts` | List potential-conflict article pairs — published articles flagged "too similar to comfortably coexist" by the auto-linker / nightly lint sweep, highest-overlap first. The KB only FLAGS the pair; it does NOT decide redundancy-vs-contradiction — that's your call with live context. Each entry has both articles (id/title/status/category) + similarity. Then merge (supersede one, `knowledge_create` the merged article, or PATCH) or reconcile if they genuinely disagree. Paginated with `total_count` in meta. Agent role. Optional: `limit` (default 50, max 1000, clamped), `offset`. |
|
|
268
268
|
| `knowledge_resolve_conflict` | Record YOUR verdict on a potential-conflict pair (from `knowledge_conflicts`). Dispositions: `dismiss` (false positive, drops from queue), `supersede` (one wins — pass `authoritative_article_id`; nightly executor links + retires loser, only at `confidence:"high"`, reversible/audited), `merge` (at high confidence an LLM synthesizes both into ONE new DRAFT, sources preserved, never auto-published). Non-destructive at agent role — you record intent, the privileged nightly job executes. Last-write-wins per pair. Required: `source_article_id`, `target_article_id`, `disposition`. Optional: `authoritative_article_id`, `classification`, `evidence`, `confidence`. |
|
|
269
|
-
| `knowledge_create` | Create a new knowledge article. File findings, document patterns, or record decisions. **Published immediately by default** (visible per `metadata.visibility` — default `owner` for agent authors, only visible to that agent; `shared` for visibility to all agents) — the response `note` says which outcome occurred. Pass `draft: true` to stage it for later review instead (publish afterwards with `knowledge_publish`). Pass `metadata: {visibility: "shared"}` to make the article visible to other agents; higher roles can set visibility and agent_id explicitly. Pass `idempotency_key` for idempotent capture (re-creating with the same key is a no-op returning the existing article — no partial duplicates). Optional: `category`, `tags`, `project_id`, `draft`, `idempotency_key`, `source_type`, `source_id`, `metadata`. |
|
|
270
|
-
| `knowledge_update` | Edit an EXISTING article IN PLACE, **preserving its ID** (IDs are load-bearing — cited in project CLAUDE.mds and cross-links). Fold in a new fact, tidy a hub, retag, or reclassify without churning a new row. Send only the fields to change; `tags` REPLACES the whole array. A changed body/tags re-triggers embedding + auto-linking. Agent role — KB-content curation (
|
|
269
|
+
| `knowledge_create` | Create a new knowledge article. File findings, document patterns, or record decisions. **Published immediately by default** (visible per `metadata.visibility` — default `owner` for agent authors, only visible to that agent; `shared` for visibility to all agents) — the response `note` says which outcome occurred. Pass `draft: true` to stage it for later review instead (publish afterwards with `knowledge_publish`). Pass `metadata: {visibility: "shared"}` to make the article visible to other agents; higher roles can set visibility and agent_id explicitly. Pass `idempotency_key` for idempotent capture (re-creating with the same key is a no-op returning the existing article — no partial duplicates). RESERVED TAG NAMESPACE: a tag starting with `idem-` must be `idem-<family>-<digest>` (digest = 12 or 40 lowercase hex chars, e.g. `idem-url-7ebe1ca33431`) or the write is rejected 422 — never silently rewritten; put topics outside that prefix and use `idempotency_key` for idempotent capture. Optional: `category`, `tags`, `project_id`, `draft`, `idempotency_key`, `source_type`, `source_id`, `metadata`. |
|
|
270
|
+
| `knowledge_update` | Edit an EXISTING article IN PLACE, **preserving its ID** (IDs are load-bearing — cited in project CLAUDE.mds and cross-links). Fold in a new fact, tidy a hub, retag, or reclassify without churning a new row. Send only the fields to change; `tags` REPLACES the whole array. A changed body/tags re-triggers embedding + auto-linking. Agent role — KB-content curation (non-destructive + audited; the in-place edit overwrites the prior body, so it is not reversible either); visibility-scoped, so another agent's private/owner memory 404s. The reserved `idem-` tag namespace applies here too (see `knowledge_create`). Required: `article_id`. Optional: `title`, `body`, `category`, `tags`, `metadata`. |
|
|
271
271
|
| `knowledge_okf_export` | **Requires `LOOPCTL_USER_KEY`.** Export the wiki as a portable OKF (Open Knowledge Format) v0.1 bundle of markdown files. Writes to `out_dir`, or returns `{files, meta}` inline. |
|
|
272
272
|
| `knowledge_okf_import` | **Requires `LOOPCTL_USER_KEY`.** Import an OKF v0.1 bundle from a local directory. Creates or (with `merge`) updates articles; tolerates and preserves unknown frontmatter. |
|
|
273
273
|
|
|
@@ -299,12 +299,12 @@ it is enforced server-side and a no-op for a non-superadmin key — see below.)
|
|
|
299
299
|
| `knowledge_bulk_publish` | **Requires `LOOPCTL_USER_KEY`.** Publish drafts, partial-success style: every valid draft publishes; others are reported per-id as `skipped` (already published — idempotent — or archived/superseded), `not_found`, or `errored`. No 100-id cap (auto-chunked); duplicates ignored; safe to retry. `meta.count` = published; `meta.counts`/`meta.results` give the breakdown. Required: `article_ids` (array). |
|
|
300
300
|
| `knowledge_unpublish` | **Requires `LOOPCTL_USER_KEY`.** Revert a published article back to draft (hidden from search/context, not deleted). Required: `article_id`. |
|
|
301
301
|
| `knowledge_bulk_unpublish` | **Requires `LOOPCTL_USER_KEY`.** Revert published articles to draft in bulk, partial-success style (mirror of `knowledge_bulk_publish`): per-id `unpublished`/`skipped` (already draft, or archived/superseded)/`not_found`/`errored`. No 100-id cap (auto-chunked, ≤5000); duplicates ignored; safe to retry. Not deleted (re-publish to restore; `knowledge_bulk_delete` to archive). `meta.count`/`meta.counts`/`meta.results` give the breakdown. Required: `article_ids` (array). |
|
|
302
|
-
| `knowledge_archive` | Soft-delete an article (draft or published). Row retained for audit; hidden from all reads
|
|
303
|
-
| `knowledge_delete` | Alias for `knowledge_archive` — DELETE verb on the REST API archives under the hood (soft delete, reversible,
|
|
304
|
-
| `knowledge_bulk_delete` | **Requires `LOOPCTL_USER_KEY`.** Bulk archive (default, reversible) or IRREVERSIBLE hard-delete by selector. Provide exactly one selector: `article_ids` (list), `source_type`+`source_id` (every active article from a source), or `tag`+`confirm:true` (every active article with the tag — high blast radius). Default = set-based soft archive (idempotent; `meta.count`=archived, `meta.counts`/`meta.results` give the breakdown; ≤5000). **Dry-run** (`dry_run:true`) mutates nothing, returns `meta.would_affect` (with `hard:true` also a single-use `meta.token`, or `meta.confirm_hash` for oversized selectors). **Hard delete** (irreversible): dry-run with `hard:true` for a token, then call again with `hard:true`+`token` to FK-correctly delete the frozen id-set (links first, access events cascade). |
|
|
302
|
+
| `knowledge_archive` | Soft-delete an article (draft or published). Row retained for audit; hidden from all reads. **NOT reversible by you** — `:archived` is a TERMINAL status (no unarchive call, no outbound transition), so restoring one needs a user-role PATCH with an explicit status. Nothing is destroyed, but do not reach for this as an undoable action: for a retraction you can undo, use `knowledge_unpublish` and `knowledge_publish`. Agent role — KB-content curation, visibility-scoped (another agent's private/owner memory 404s). Required: `article_id`. |
|
|
303
|
+
| `knowledge_delete` | Alias for `knowledge_archive` — DELETE verb on the REST API archives under the hood (soft delete: row retained and audited, but NOT reversible by any call you can make, since `:archived` is terminal — use `knowledge_unpublish` when you need an undoable retraction). Agent role. (Irreversible HARD delete is `knowledge_bulk_delete hard:true`, which stays `LOOPCTL_USER_KEY`.) Required: `article_id`. |
|
|
304
|
+
| `knowledge_bulk_delete` | **Requires `LOOPCTL_USER_KEY`.** Bulk archive (default — non-destructive, but NOT reversible by any call: `:archived` is terminal and restoring needs a user-role PATCH) or IRREVERSIBLE hard-delete by selector. Provide exactly one selector: `article_ids` (list), `source_type`+`source_id` (every active article from a source), or `tag`+`confirm:true` (every active article with the tag — high blast radius). Default = set-based soft archive (idempotent; `meta.count`=archived, `meta.counts`/`meta.results` give the breakdown; ≤5000). **Dry-run** (`dry_run:true`) mutates nothing, returns `meta.would_affect` (with `hard:true` also a single-use `meta.token`, or `meta.confirm_hash` for oversized selectors). **Hard delete** (irreversible): dry-run with `hard:true` for a token, then call again with `hard:true`+`token` to FK-correctly delete the frozen id-set (links first, access events cascade). |
|
|
305
305
|
| `knowledge_drafts` | List draft (unpublished) knowledge articles with pagination. Optional: `limit` (default 20, max 1000 — over-max → 400, no silent clamp), `offset` (default 0), `project_id`. Returns `meta.total_count`. |
|
|
306
306
|
| `knowledge_lint` | Run a lint check on the knowledge wiki to identify stale or low-coverage articles. Optional: `project_id`, `stale_days`, `min_coverage`, `max_per_category` (default 50, max 500). True totals returned in `summary.total_per_category`. |
|
|
307
|
-
| `knowledge_consolidation` | Read the nightly consolidation ("dream") report: NUMBERED proposals for reconciling the corpus, each naming the articles involved and quoting an excerpt from each as evidence. **
|
|
307
|
+
| `knowledge_consolidation` | Read the nightly consolidation ("dream") report: NUMBERED proposals for reconciling the corpus, each naming the articles involved and quoting an excerpt from each as evidence. **This tool** applies nothing and recomputes nothing — it returns persisted rows. **The pass** it reports on does write: since #608 the nightly run UNPUBLISHES the losers of each `duplicate_capture` group that two consecutive reports both propose. That is its only write to `articles`, it is an unpublish and never an archive (archive is terminal for an article), and it still writes no links or conflict resolutions. Classes: `duplicate_capture` (titles that collide once case/punctuation normalize away, or idempotency keys that collide under the same normalization while differing verbatim — capture tag-format drift, which the novelty gate does not catch because novelty scoring and idempotency are separate paths), `generic_title` (a placeholder title that collides on active-title uniqueness and blocks hub creation). Two classes are **RETIRED** (#605) and no longer produced, though the `class` filter still accepts them so historical reports stay readable: `contradiction_candidate` (the nightly lint judges those pairs itself now) and `stale_entry` (age is not a defect signal — for stale articles call `knowledge_lint`, which computes them with a caller-chosen `stale_days`). **Denominators:** `corpus_size` = PUBLISHED articles owned by the tenant at scan time, not its total article count; `proposal_count` = the TRUE pre-cap count of PROPOSALS, not of articles (one duplicate group of three articles is ONE proposal, and one article can appear in proposals of several classes); `persisted_count` = proposal ROWS the report carries, lower than `proposal_count` exactly when a class hit `max_per_class` (`truncated` flags which); `meta.total_count` counts persisted proposals matching the `class` filter, so it is bounded by `persisted_count`, never `proposal_count`. `review_status`/`reviewed_by`/`reviewed_at` are vestigial — nothing reads them to decide anything, there is no approve/reject surface and there will not be one (#605 supersedes #594); auto-apply is gated on reversibility and two-run agreement. They still reset to pending/null whenever the nightly pass re-derives a proposal, so refreshed machine output never inherits an earlier verdict. Requires orchestrator role. Optional: `day` (ISO8601, default most recent report), `class`, `limit` (default 50, max 500), `offset`. |
|
|
308
308
|
| `knowledge_export` | Export all knowledge articles as an OKF v0.1 bundle (gzipped tar archive, unbounded, bounded-memory streaming, fail-closed). Returns a curl command for direct download — **the download requires `LOOPCTL_USER_KEY`** (an orchestrator key would 403). Pass `format=json` for buffered in-memory JSON (convenience tool for file writers; capped at `export_max_buffered_export_articles` — returns 413 if over-cap). Optional: `project_id`, `format` (`tar.gz` default or `json`). |
|
|
309
309
|
| `knowledge_ingest` | Submit a URL or raw content for knowledge extraction. Enqueues an Oban job. Extracted articles are **drafts by default** (lower-trust LLM output); pass `publish: true` to publish on extraction. **BYO:** runs on the tenant's own Anthropic key — a keyless tenant gets a 422 whose result leads with an `ACTION REQUIRED` notice pointing at `set_llm_config` (see [First-time setup](#first-time-setup--provision-your-byo-llm-keys)). Required: `source_type`. One of: `url` or `content`. Optional: `project_id`, `publish`. |
|
|
310
310
|
| `knowledge_ingest_batch` | Submit up to 50 ingestion items in a single request. Each item has the same shape as `knowledge_ingest` (incl. `publish`). Returns per-item results. Required: `items`. Optional: batch-level `project_id` / `publish` defaults. |
|
package/index.js
CHANGED
|
@@ -1786,8 +1786,9 @@ async function knowledgeUnpublish({ article_id }) {
|
|
|
1786
1786
|
return toContent(result);
|
|
1787
1787
|
}
|
|
1788
1788
|
|
|
1789
|
-
// #331: single-article archive is agent-role KB curation (
|
|
1790
|
-
// audited, visibility-scoped server-side).
|
|
1789
|
+
// #331: single-article archive is agent-role KB curation (non-destructive soft delete,
|
|
1790
|
+
// audited, visibility-scoped server-side). NOT reversible in code — #606/#605: `:archived`
|
|
1791
|
+
// is a terminal status. The row survives; nothing automated brings it back.
|
|
1791
1792
|
async function knowledgeArchive({ article_id }) {
|
|
1792
1793
|
const result = await apiCall(
|
|
1793
1794
|
"POST",
|
|
@@ -4734,7 +4735,14 @@ const TOOLS = [
|
|
|
4734
4735
|
tags: {
|
|
4735
4736
|
type: "array",
|
|
4736
4737
|
items: { type: "string" },
|
|
4737
|
-
description:
|
|
4738
|
+
description:
|
|
4739
|
+
"Optional: list of TOPICAL tags. RESERVED NAMESPACE: the 'idem-' prefix belongs " +
|
|
4740
|
+
"to per-source idempotency keys — a tag starting with it must be " +
|
|
4741
|
+
"idem-<family>-<digest> where <digest> is a 12- or 40-character lowercase hex " +
|
|
4742
|
+
"digest (e.g. idem-url-7ebe1ca33431), or the write is REJECTED with a 422. It is " +
|
|
4743
|
+
"never silently rewritten. Do not put a topic in that prefix. For idempotent " +
|
|
4744
|
+
"capture use the idempotency_key field, which is server-guaranteed unique per " +
|
|
4745
|
+
"tenant — a tag is not.",
|
|
4738
4746
|
},
|
|
4739
4747
|
project_id: {
|
|
4740
4748
|
type: "string",
|
|
@@ -4810,7 +4818,9 @@ const TOOLS = [
|
|
|
4810
4818
|
"project CLAUDE.mds and cross-links). Send only the fields you want to change; every " +
|
|
4811
4819
|
"field is optional except article_id. `tags` REPLACES the whole array (send the full " +
|
|
4812
4820
|
"desired set, not a delta). A changed body/tags re-triggers embedding + auto-linking. " +
|
|
4813
|
-
"Agent role — this is KB-content curation (
|
|
4821
|
+
"Agent role — this is KB-content curation (non-destructive + audited: the edit is in " +
|
|
4822
|
+
"place and there is no version-restore endpoint, but the prior body is retained in the " +
|
|
4823
|
+
"article.updated audit entry). Visibility-scoped: " +
|
|
4814
4824
|
"you can only edit an article you can see, so another agent's private/owner memory " +
|
|
4815
4825
|
"returns 404. `tenant_id` is never accepted. Returns the full updated article. To " +
|
|
4816
4826
|
"instead retire/replace an article, use knowledge_archive or knowledge_resolve_conflict.",
|
|
@@ -4836,7 +4846,11 @@ const TOOLS = [
|
|
|
4836
4846
|
tags: {
|
|
4837
4847
|
type: "array",
|
|
4838
4848
|
items: { type: "string" },
|
|
4839
|
-
description:
|
|
4849
|
+
description:
|
|
4850
|
+
"Optional: REPLACES the whole tags array (send the full desired set). RESERVED " +
|
|
4851
|
+
"NAMESPACE: a tag starting with 'idem-' must be idem-<family>-<digest> " +
|
|
4852
|
+
"(<digest> = 12 or 40 lowercase hex chars, e.g. idem-url-7ebe1ca33431) or the " +
|
|
4853
|
+
"update is REJECTED with a 422 — it is never silently rewritten.",
|
|
4840
4854
|
},
|
|
4841
4855
|
metadata: {
|
|
4842
4856
|
type: "object",
|
|
@@ -5190,11 +5204,15 @@ const TOOLS = [
|
|
|
5190
5204
|
{
|
|
5191
5205
|
name: "knowledge_archive",
|
|
5192
5206
|
description:
|
|
5193
|
-
"Archive an article (soft delete). The article is hidden from search, context, " +
|
|
5194
|
-
"
|
|
5195
|
-
"
|
|
5196
|
-
"
|
|
5197
|
-
"
|
|
5207
|
+
"Archive an article (soft delete). The article is hidden from search, context, and " +
|
|
5208
|
+
"the index but the row is retained for audit/history. NOT reversible by you: " +
|
|
5209
|
+
"`:archived` is a TERMINAL article status — there is no unarchive call and no " +
|
|
5210
|
+
"{archived -> anything} transition, so restoring one needs a user-role PATCH with an " +
|
|
5211
|
+
"explicit status. Nothing is destroyed, but do not reach for this as an undoable " +
|
|
5212
|
+
"action. If you want a RETRACTION you can undo, use knowledge_unpublish (published " +
|
|
5213
|
+
"-> draft) and knowledge_publish to put it back. Works for drafts and published " +
|
|
5214
|
+
"articles. Agent role — KB-content curation. Visibility-scoped: you can only archive " +
|
|
5215
|
+
"an article you can see, so another agent's private/owner memory returns 404.",
|
|
5198
5216
|
inputSchema: {
|
|
5199
5217
|
type: "object",
|
|
5200
5218
|
properties: {
|
|
@@ -5210,10 +5228,13 @@ const TOOLS = [
|
|
|
5210
5228
|
name: "knowledge_delete",
|
|
5211
5229
|
description:
|
|
5212
5230
|
"Delete an article. Under the hood this performs the same soft-delete (archive) " +
|
|
5213
|
-
"as knowledge_archive — use whichever name is clearer at the call site
|
|
5214
|
-
"
|
|
5215
|
-
"
|
|
5216
|
-
"
|
|
5231
|
+
"as knowledge_archive — use whichever name is clearer at the call site, and note " +
|
|
5232
|
+
"that it inherits archive's terminality: the row is retained for audit, but " +
|
|
5233
|
+
"`:archived` has no outbound transition, so NOTHING you can call restores it. " +
|
|
5234
|
+
"For a retraction you can undo, use knowledge_unpublish instead. There is no hard " +
|
|
5235
|
+
"delete here (that is knowledge_bulk_delete hard:true, which stays user-gated). " +
|
|
5236
|
+
"Agent role — KB-content curation: non-destructive + audited, visibility-scoped " +
|
|
5237
|
+
"(another agent's private/owner memory 404s).",
|
|
5217
5238
|
inputSchema: {
|
|
5218
5239
|
type: "object",
|
|
5219
5240
|
properties: {
|
|
@@ -5228,7 +5249,9 @@ const TOOLS = [
|
|
|
5228
5249
|
{
|
|
5229
5250
|
name: "knowledge_bulk_delete",
|
|
5230
5251
|
description:
|
|
5231
|
-
"Bulk archive (default, reversible
|
|
5252
|
+
"Bulk archive (default, non-destructive but NOT reversible by any call you can make — " +
|
|
5253
|
+
"`:archived` is terminal; restoring needs a user-role PATCH) or IRREVERSIBLE hard-delete " +
|
|
5254
|
+
"of articles by selector. " +
|
|
5232
5255
|
"REQUIRES LOOPCTL_USER_KEY (user role — orchestrator is NOT sufficient). Provide EXACTLY ONE " +
|
|
5233
5256
|
"selector: article_ids (explicit list), source_type + source_id (every active article from " +
|
|
5234
5257
|
"that source), or tag + confirm:true (every active article carrying the tag — high blast " +
|
|
@@ -5274,8 +5297,9 @@ const TOOLS = [
|
|
|
5274
5297
|
hard: {
|
|
5275
5298
|
type: "boolean",
|
|
5276
5299
|
description:
|
|
5277
|
-
"IRREVERSIBLE hard delete (vs default
|
|
5278
|
-
"
|
|
5300
|
+
"IRREVERSIBLE hard delete (vs the default soft archive, which is non-destructive but " +
|
|
5301
|
+
"terminal — `:archived` has no outbound transition, so restoring one needs a user-role " +
|
|
5302
|
+
"PATCH). Run dry_run first to get a token, then pass hard:true + token.",
|
|
5279
5303
|
},
|
|
5280
5304
|
token: {
|
|
5281
5305
|
type: "string",
|
|
@@ -5466,16 +5490,21 @@ const TOOLS = [
|
|
|
5466
5490
|
description:
|
|
5467
5491
|
"Read the nightly consolidation (\"dream\") report: NUMBERED proposals for reconciling " +
|
|
5468
5492
|
"the corpus, each naming the articles involved and quoting an excerpt from each as " +
|
|
5469
|
-
"evidence.
|
|
5470
|
-
"
|
|
5493
|
+
"evidence. THIS TOOL applies nothing and recomputes nothing — it returns persisted rows. " +
|
|
5494
|
+
"The PASS it reports on does write: since #608 the nightly run UNPUBLISHES the losers of " +
|
|
5495
|
+
"each `duplicate_capture` group that two consecutive reports both propose. That is its " +
|
|
5496
|
+
"only write to articles, it is an unpublish and never an archive (archive is terminal for " +
|
|
5497
|
+
"an article), and it still writes no links or conflict resolutions. Requires orchestrator " +
|
|
5498
|
+
"role.\n\n" +
|
|
5471
5499
|
"Classes: `duplicate_capture` (titles that collide once case/punctuation normalize away, " +
|
|
5472
5500
|
"or idempotency keys that collide under the same normalization while differing verbatim — " +
|
|
5473
5501
|
"capture tag-format drift, which the novelty gate does not catch because novelty scoring " +
|
|
5474
|
-
"and idempotency are separate paths); `
|
|
5475
|
-
"
|
|
5476
|
-
"
|
|
5477
|
-
"
|
|
5478
|
-
"
|
|
5502
|
+
"and idempotency are separate paths); `generic_title` (a placeholder title that collides " +
|
|
5503
|
+
"on active-title uniqueness and blocks hub creation). Two classes are RETIRED (#605) and " +
|
|
5504
|
+
"no longer produced, though the `class` filter still accepts them so historical reports " +
|
|
5505
|
+
"stay readable: `contradiction_candidate` (the nightly lint judges those pairs itself now) " +
|
|
5506
|
+
"and `stale_entry` (age is not a defect signal — for stale articles call knowledge_lint, " +
|
|
5507
|
+
"which computes them with a caller-chosen `stale_days`).\n\n" +
|
|
5479
5508
|
"Denominators: `corpus_size` counts PUBLISHED articles owned by the tenant at scan time, " +
|
|
5480
5509
|
"not its total article count. `proposal_count` is the TRUE pre-cap count of PROPOSALS, not " +
|
|
5481
5510
|
"of articles — one duplicate group of three articles is ONE proposal, and one article can " +
|
|
@@ -5483,8 +5512,11 @@ const TOOLS = [
|
|
|
5483
5512
|
"report carries, lower than `proposal_count` exactly when a class hit `max_per_class` " +
|
|
5484
5513
|
"(`truncated` flags which). `meta.total_count` counts persisted proposals matching the " +
|
|
5485
5514
|
"`class` filter, so it is bounded by `persisted_count`, never by `proposal_count`.\n\n" +
|
|
5486
|
-
"Review state (`review_status`/`reviewed_by`/`reviewed_at`)
|
|
5487
|
-
"
|
|
5515
|
+
"Review state (`review_status`/`reviewed_by`/`reviewed_at`) is VESTIGIAL: nothing reads it " +
|
|
5516
|
+
"to decide anything, there is no approve/reject surface and there will not be one (#605 " +
|
|
5517
|
+
"supersedes #594) — auto-apply is gated on reversibility and two-run agreement, not on an " +
|
|
5518
|
+
"approval. It still RESETS to pending/null whenever the nightly pass re-derives a proposal, " +
|
|
5519
|
+
"so refreshed machine output can never inherit an earlier verdict.",
|
|
5488
5520
|
inputSchema: {
|
|
5489
5521
|
type: "object",
|
|
5490
5522
|
properties: {
|