@extrovert.dev/sdk 0.1.0-pre.7 → 0.1.0-pre.9

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/dist/index.d.cts CHANGED
@@ -6,7 +6,7 @@
6
6
  * on 429/5xx, honors `Retry-After`, and surfaces every failure as a typed {@link ApiError}.
7
7
  */
8
8
  /** The library version, surfaced in the User-Agent. Kept in sync with package.json by build. */
9
- declare const SDK_VERSION = "0.1.0-pre.7";
9
+ declare const SDK_VERSION = "0.1.0-pre.9";
10
10
  interface RetryOptions {
11
11
  /** Max retry attempts for idempotent requests on 429/5xx/network errors. Default 2. */
12
12
  maxRetries: number;
@@ -781,6 +781,7 @@ interface ReviewTurn {
781
781
  }
782
782
  /** Filters for listing review requests (spec §5.2). */
783
783
  interface ListReviewsParams {
784
+ composer?: "me";
784
785
  state?: ReviewState | ReviewState[];
785
786
  category_id?: string;
786
787
  inbox?: string;
@@ -911,6 +912,7 @@ interface ReviewEventCursor {
911
912
  }
912
913
  /** Drain result for list/wait: un-acked events in FIFO seq order + cursors. */
913
914
  interface ReviewEventsResult {
915
+ pending_reviews?: number;
914
916
  events: ReviewEvent[];
915
917
  cursors?: ReviewEventCursor[];
916
918
  }
@@ -928,6 +930,12 @@ interface ListReviewEventsParams {
928
930
  * agent-attributed: the deliberate cross-agent-404 exception. Opaque ids only.
929
931
  */
930
932
  interface Category {
933
+ /** Logical accepted messages in this authorized project, counted by creation time. */
934
+ message_count_7d?: number;
935
+ message_count_30d?: number;
936
+ message_count_90d?: number;
937
+ last_used_at?: string;
938
+ pending_review_count?: number;
931
939
  id: string;
932
940
  name: string;
933
941
  description: string;
@@ -944,6 +952,9 @@ interface Category {
944
952
  }
945
953
  /** Browse filter for the category registry (spec §5.5). */
946
954
  interface ListCategoriesParams {
955
+ sort?: "popular" | "messages_7d" | "messages_90d" | "last_used" | "pending_reviews" | "name";
956
+ limit?: number;
957
+ page?: string;
947
958
  /** Pure lexical substring filter over name+description (every token must match; NO LLM). */
948
959
  match?: string;
949
960
  }
@@ -1207,6 +1218,8 @@ interface Rule {
1207
1218
  author_kind: "agent" | "human";
1208
1219
  created_at: IsoTimestamp;
1209
1220
  updated_at: IsoTimestamp;
1221
+ source_review_id?: string;
1222
+ source_turn_id?: string;
1210
1223
  }
1211
1224
  /** Filter for the ordered get_rules read (spec §5.4; §7). */
1212
1225
  interface GetRulesParams {
@@ -1228,8 +1241,8 @@ interface RuleSnapshot extends Page<Rule> {
1228
1241
  *
1229
1242
  * Layering (org/project): an agent-plane save is ALWAYS project-layer: the saved
1230
1243
  * rule's `rule_layer` is `project`, bound to the calling key's project. There is no
1231
- * settable `rule_layer` here: an agent cannot create org-layer / house-style
1232
- * (`rule_layer="org"`) rules in v1; authoring org rules is a console/admin action.
1244
+ * settable `rule_layer` here: this method cannot create org-layer rules. Use learnFromReview for
1245
+ * authenticated reviewer feedback, including organization house style.
1233
1246
  * (`scope: "general"` still means a house-style rule WITHIN the project layer :
1234
1247
  * `scope` is the category axis, `rule_layer` is the ownership axis.)
1235
1248
  */
@@ -1891,6 +1904,24 @@ interface WhoAmI {
1891
1904
  key_id: string;
1892
1905
  scopes: Scope[];
1893
1906
  }
1907
+ /** Learn writing guidance from an authenticated human turn on your review. */
1908
+ interface LearnReviewRuleRequest {
1909
+ client_id: string;
1910
+ source_turn_id: string;
1911
+ rule_text: string;
1912
+ target: "org_house" | "project_general" | "category";
1913
+ category_id?: string;
1914
+ kind?: "soft" | "hard";
1915
+ supersedes_id?: string;
1916
+ }
1917
+ interface LearnedReviewRule {
1918
+ rule: Rule;
1919
+ source_review_id: string;
1920
+ source_turn_id: string;
1921
+ human_id: string;
1922
+ audit_id: string;
1923
+ propagation: "queued";
1924
+ }
1894
1925
 
1895
1926
  /**
1896
1927
  * The ONE list envelope + opaque-cursor iteration (redesign §5.2 / §6.2).
@@ -2067,6 +2098,7 @@ interface Transport {
2067
2098
  getScanBacklogStatus(categoryId: string, signal?: AbortSignal): Promise<ScanBacklogStatus>;
2068
2099
  getCategoryPacingState(categoryId: string, signal?: AbortSignal): Promise<CategoryPacingState>;
2069
2100
  getRules(params: GetRulesParams, signal?: AbortSignal): Promise<RuleSnapshot>;
2101
+ learnReviewRule(reviewId: string, req: LearnReviewRuleRequest, signal?: AbortSignal): Promise<LearnedReviewRule>;
2070
2102
  saveRule(req: SaveRuleRequest, signal?: AbortSignal): Promise<Rule>;
2071
2103
  promoteRule(ruleId: string, toScope: "general" | "category", signal?: AbortSignal): Promise<Rule>;
2072
2104
  retireRule(ruleId: string, signal?: AbortSignal): Promise<Rule>;
@@ -2239,6 +2271,7 @@ declare class MockBackend {
2239
2271
  * is a pure lexical filter (every token must appear in name+description) - NO LLM,
2240
2272
  * mirroring the server.
2241
2273
  */
2274
+ private categoryUsage;
2242
2275
  listCategories(params?: ListCategoriesParams): Page<Category>;
2243
2276
  /** Get one category (mock), or undefined when not found. */
2244
2277
  getCategory(categoryId: string): Category | undefined;
@@ -2287,6 +2320,8 @@ declare class MockBackend {
2287
2320
  /** Get the ORDERED active rule set (mock) - §7 ladder + category-before-general. */
2288
2321
  getRules(params?: GetRulesParams): RuleSnapshot;
2289
2322
  /** Save / edit a rule (mock) - append-only by supersession (D11). */
2323
+ private learnedRules;
2324
+ learnReviewRule(reviewId: string, req: LearnReviewRuleRequest): LearnedReviewRule;
2290
2325
  saveRule(req: SaveRuleRequest): Rule;
2291
2326
  /** Promote a rule between layers (mock, via supersession), or undefined when unknown. */
2292
2327
  promoteRule(ruleId: string, toScope: "general" | "category"): Rule | undefined;
@@ -3253,14 +3288,16 @@ declare class Categories {
3253
3288
  */
3254
3289
  declare class Rules {
3255
3290
  private readonly ctx;
3291
+ /** Learn category or organization house rules from verified human review feedback. */
3292
+ learnFromReview(reviewId: string, req: LearnReviewRuleRequest, signal?: AbortSignal): Promise<LearnedReviewRule>;
3256
3293
  constructor(ctx: ResourceContext);
3257
3294
  /** Get the ORDERED active rule set (precedence ladder applied; NO LLM). */
3258
3295
  get(params?: GetRulesParams, signal?: AbortSignal): Promise<RuleSnapshot>;
3259
3296
  /**
3260
3297
  * Save / edit a rule (append-only by supersession; D11). An agent-plane save is
3261
3298
  * ALWAYS project-layer: the saved rule's `rule_layer` is `project`, bound to the
3262
- * key's project. Agents cannot author org-layer / house-style (`rule_layer:"org"`)
3263
- * rules in v1: that is a console/admin action.
3299
+ * key's project. For all authenticated reviewer feedback use learnFromReview at the intended
3300
+ * organization, project, or category scope. This method is project maintenance only.
3264
3301
  */
3265
3302
  save(req: SaveRuleRequest, signal?: AbortSignal): Promise<Rule>;
3266
3303
  /** Promote a rule between the category and general/house-style layers. */
@@ -3963,7 +4000,7 @@ declare function signWebhook(secret: string, body: string, timestampSeconds: num
3963
4000
  *
3964
4001
  * ## Provisional, pre-1.0 (0.x)
3965
4002
  *
3966
- * {@link CONTRACT_VERSION} is **`0.1.0-pre.7`** - a deliberately **provisional**, pre-1.0
4003
+ * {@link CONTRACT_VERSION} is **`0.1.0-pre.9`** - a deliberately **provisional**, pre-1.0
3967
4004
  * contract. It is open and documented, but it MAY still evolve before 1.0: there
3968
4005
  * are no external users yet, and the **D20 shared-pool auto-send governor** is a
3969
4006
  * hard prerequisite before onboarding external users. Pin the version; expect
@@ -4020,12 +4057,12 @@ interface DiffJson {
4020
4057
  /**
4021
4058
  * The published version of the Extrovert Review-Loop open contract (D14).
4022
4059
  *
4023
- * **`0.1.0-pre.7` - PROVISIONAL, pre-1.0.** Versioned *with the SDK* (this package's
4060
+ * **`0.1.0-pre.9` - PROVISIONAL, pre-1.0.** Versioned *with the SDK* (this package's
4024
4061
  * `package.json` version) and aligned to the openapi `info.version`. Open and
4025
4062
  * documented, but MAY still evolve before 1.0 (no external users yet; the D20
4026
4063
  * shared-pool governor is required before external users). Pin it.
4027
4064
  */
4028
- declare const CONTRACT_VERSION: "0.1.0-pre.7";
4065
+ declare const CONTRACT_VERSION: "0.1.0-pre.9";
4029
4066
  /** The stability posture of a published contract version. */
4030
4067
  type ContractStability = "provisional" | "stable";
4031
4068
  /**
@@ -4068,4 +4105,4 @@ interface ContractManifest {
4068
4105
  */
4069
4106
  declare const CONTRACT_MANIFEST: ContractManifest;
4070
4107
 
4071
- export { API_VERSION_HEADER, type AccountRiskDial, type AckReviewEventEntry, type AckReviewEventRequest, type AckReviewEventResult, type AddContactListRequest, type Agent, type AgentStatus, ApiError, type ApiErrorBody, type Attachment, type AttachmentDownload, type AttachmentInput, AuthenticationError, type BatchUpdateMessagesRequest, type BatchUpdateResult, BornStaleError, BreadthRequiredError, CONTRACT_MANIFEST, CONTRACT_VERSION, CURRENT_API_VERSION, Categories, type Category, type CategoryPacingState, type CategoryRiskDial, Commerce, type CommerceBlocker, type CommerceRequest, type CommerceRequestKind, ConflictError, ConnectionError, type ContactListDirection, type ContactListEntry, type ContactListKind, ContactLists, type ContractManifest, type ContractStability, type CreateInboxRequest, type Cursor, DEFAULT_BASE_URL, type DeleteResult, type DiffHunk, type DiffJson, type Domain, type DomainOffboard, type DomainQuote, type DomainReadiness, type DomainRecord, type DomainScope, type DomainStatusEvent, type DomainStatusEventPage, type DomainWaitResult, Domains, type EffectiveRiskDial, type EmailAddress, type EnrollRequest, type EnrollResponse, type ExtractedCredentials, ExtrovertClient as Extrovert, ExtrovertClient, type ExtrovertClientOptions, ForbiddenScopeError, type ForwardRequest, type GetInboxParams, type GetRuleAuditParams, type GetRulesParams, type GraduationStatus, IdempotencyConflictError, type Inbox, type InboxCredentials, InboxHandle, type InboxInclude, type InboxMetadata, type InboxMetadataPatch, type InboxMetadataValue, type InboxStatus, Inboxes, IntentRequiredError, type IsoTimestamp, type Job, type KeyTier, type List, type ListCategoriesParams, type ListCommerceRequestsParams, type ListInboxesParams, type ListMessagesParams, ListPage, type ListParams, type ListReviewEventsParams, type ListReviewsParams, type ListSuppressionsParams, type ListThreadsParams, MOCK_BASE_URL, type MailFolder, type MailboxQuickstart, type MailboxQuickstartCall, type MarkReadRequest, type Message, type MessageDirection, Messages, MockBackend, NotFoundError, type OnboardDomainRequest, type OnboardingMode, PROBLEM_CODES, type PacingItem, type Page, type PageFetcher, PaymentRequiredError, PermissionError, type PostReviewChatRequest, type Problem, type ProblemCode, type ProblemField, type ProjectInboxListParams, ProjectInboxes, Projects, type ProposeCategoryRequest, type ProposeGraduationRequest, type QueuedForReviewResult, type QuoteDomainRequest, REVIEW_PROBLEM_RETRYABLE, RateLimitError, RecipientSuppressedError, type RegisterWebhookRequest, type ReplyRequest, type RequestDomainPurchaseRequest, type RequestPlanChangeRequest, type RestampReviewRequest, type Review, ReviewConflictError, type ReviewDecisionContext, type ReviewEvent, type ReviewEventCursor, type ReviewEventReason, ReviewEvents, type ReviewEventsResult, type ReviewFeedback, type ReviewFeedbackComment, type ReviewInclude, type ReviewIntent, type ReviewMode, type ReviewPolicy, type ReviewState, type ReviewTurn, type ReviewerAction, type ReviewerDecisionRequest, type ReviewerDecisionResult, Reviews, type RiskDial, type Rule, type RuleAuditEntry, type RuleLayer, type RuleSnapshot, Rules, SDK_VERSION, type SaveRuleRequest, type ScanBacklogStatus, type Scope, type SearchMessagesParams, SendNeedsReconciliationError, type SendOutcome, type SendRequest, type SendResult, type SentResult, type SignUpRequest, type SignUpResponse, StaleError, type StreamEvent, type StreamOptions, type SubmitForReviewResult, type SubmitRevisionRequest, type SuppressionEntry, type SuppressionPrecheck, type SuppressionScope, type SuppressionSource, Suppressions, TerminalError, type Thread, type ThreadDetail, Threads, TimeoutError, UnavailableError, type UpdateCategoryRequest, type UpdateInboxRequest, type UpdateWebhookRequest, ValidationError, type VerifyRequest, type VerifyResponse, type VerifyWebhookOptions, type WaitForEmailRequest, type WaitForEmailResult, type WaitForReviewEventParams, type Webhook, type WebhookEvent, type WebhookPayload, Webhooks, type WhoAmI, WrongStateError, extractCredentials, extractLink, extractOtp, isProblemCode, isQueuedForReview, isSentImmediately, listPage, parseKeyTier, parseProblem, parseWebhook, reviewIdOf, sentMessageIdOf, serializeInclude, signWebhook, threadIdOf, tierAllowsOrgWildcard, tierNeedsExplicitBreadth, verifyWebhookSignature };
4108
+ export { API_VERSION_HEADER, type AccountRiskDial, type AckReviewEventEntry, type AckReviewEventRequest, type AckReviewEventResult, type AddContactListRequest, type Agent, type AgentStatus, ApiError, type ApiErrorBody, type Attachment, type AttachmentDownload, type AttachmentInput, AuthenticationError, type BatchUpdateMessagesRequest, type BatchUpdateResult, BornStaleError, BreadthRequiredError, CONTRACT_MANIFEST, CONTRACT_VERSION, CURRENT_API_VERSION, Categories, type Category, type CategoryPacingState, type CategoryRiskDial, Commerce, type CommerceBlocker, type CommerceRequest, type CommerceRequestKind, ConflictError, ConnectionError, type ContactListDirection, type ContactListEntry, type ContactListKind, ContactLists, type ContractManifest, type ContractStability, type CreateInboxRequest, type Cursor, DEFAULT_BASE_URL, type DeleteResult, type DiffHunk, type DiffJson, type Domain, type DomainOffboard, type DomainQuote, type DomainReadiness, type DomainRecord, type DomainScope, type DomainStatusEvent, type DomainStatusEventPage, type DomainWaitResult, Domains, type EffectiveRiskDial, type EmailAddress, type EnrollRequest, type EnrollResponse, type ExtractedCredentials, ExtrovertClient as Extrovert, ExtrovertClient, type ExtrovertClientOptions, ForbiddenScopeError, type ForwardRequest, type GetInboxParams, type GetRuleAuditParams, type GetRulesParams, type GraduationStatus, IdempotencyConflictError, type Inbox, type InboxCredentials, InboxHandle, type InboxInclude, type InboxMetadata, type InboxMetadataPatch, type InboxMetadataValue, type InboxStatus, Inboxes, IntentRequiredError, type IsoTimestamp, type Job, type KeyTier, type LearnReviewRuleRequest, type LearnedReviewRule, type List, type ListCategoriesParams, type ListCommerceRequestsParams, type ListInboxesParams, type ListMessagesParams, ListPage, type ListParams, type ListReviewEventsParams, type ListReviewsParams, type ListSuppressionsParams, type ListThreadsParams, MOCK_BASE_URL, type MailFolder, type MailboxQuickstart, type MailboxQuickstartCall, type MarkReadRequest, type Message, type MessageDirection, Messages, MockBackend, NotFoundError, type OnboardDomainRequest, type OnboardingMode, PROBLEM_CODES, type PacingItem, type Page, type PageFetcher, PaymentRequiredError, PermissionError, type PostReviewChatRequest, type Problem, type ProblemCode, type ProblemField, type ProjectInboxListParams, ProjectInboxes, Projects, type ProposeCategoryRequest, type ProposeGraduationRequest, type QueuedForReviewResult, type QuoteDomainRequest, REVIEW_PROBLEM_RETRYABLE, RateLimitError, RecipientSuppressedError, type RegisterWebhookRequest, type ReplyRequest, type RequestDomainPurchaseRequest, type RequestPlanChangeRequest, type RestampReviewRequest, type Review, ReviewConflictError, type ReviewDecisionContext, type ReviewEvent, type ReviewEventCursor, type ReviewEventReason, ReviewEvents, type ReviewEventsResult, type ReviewFeedback, type ReviewFeedbackComment, type ReviewInclude, type ReviewIntent, type ReviewMode, type ReviewPolicy, type ReviewState, type ReviewTurn, type ReviewerAction, type ReviewerDecisionRequest, type ReviewerDecisionResult, Reviews, type RiskDial, type Rule, type RuleAuditEntry, type RuleLayer, type RuleSnapshot, Rules, SDK_VERSION, type SaveRuleRequest, type ScanBacklogStatus, type Scope, type SearchMessagesParams, SendNeedsReconciliationError, type SendOutcome, type SendRequest, type SendResult, type SentResult, type SignUpRequest, type SignUpResponse, StaleError, type StreamEvent, type StreamOptions, type SubmitForReviewResult, type SubmitRevisionRequest, type SuppressionEntry, type SuppressionPrecheck, type SuppressionScope, type SuppressionSource, Suppressions, TerminalError, type Thread, type ThreadDetail, Threads, TimeoutError, UnavailableError, type UpdateCategoryRequest, type UpdateInboxRequest, type UpdateWebhookRequest, ValidationError, type VerifyRequest, type VerifyResponse, type VerifyWebhookOptions, type WaitForEmailRequest, type WaitForEmailResult, type WaitForReviewEventParams, type Webhook, type WebhookEvent, type WebhookPayload, Webhooks, type WhoAmI, WrongStateError, extractCredentials, extractLink, extractOtp, isProblemCode, isQueuedForReview, isSentImmediately, listPage, parseKeyTier, parseProblem, parseWebhook, reviewIdOf, sentMessageIdOf, serializeInclude, signWebhook, threadIdOf, tierAllowsOrgWildcard, tierNeedsExplicitBreadth, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * on 429/5xx, honors `Retry-After`, and surfaces every failure as a typed {@link ApiError}.
7
7
  */
8
8
  /** The library version, surfaced in the User-Agent. Kept in sync with package.json by build. */
9
- declare const SDK_VERSION = "0.1.0-pre.7";
9
+ declare const SDK_VERSION = "0.1.0-pre.9";
10
10
  interface RetryOptions {
11
11
  /** Max retry attempts for idempotent requests on 429/5xx/network errors. Default 2. */
12
12
  maxRetries: number;
@@ -781,6 +781,7 @@ interface ReviewTurn {
781
781
  }
782
782
  /** Filters for listing review requests (spec §5.2). */
783
783
  interface ListReviewsParams {
784
+ composer?: "me";
784
785
  state?: ReviewState | ReviewState[];
785
786
  category_id?: string;
786
787
  inbox?: string;
@@ -911,6 +912,7 @@ interface ReviewEventCursor {
911
912
  }
912
913
  /** Drain result for list/wait: un-acked events in FIFO seq order + cursors. */
913
914
  interface ReviewEventsResult {
915
+ pending_reviews?: number;
914
916
  events: ReviewEvent[];
915
917
  cursors?: ReviewEventCursor[];
916
918
  }
@@ -928,6 +930,12 @@ interface ListReviewEventsParams {
928
930
  * agent-attributed: the deliberate cross-agent-404 exception. Opaque ids only.
929
931
  */
930
932
  interface Category {
933
+ /** Logical accepted messages in this authorized project, counted by creation time. */
934
+ message_count_7d?: number;
935
+ message_count_30d?: number;
936
+ message_count_90d?: number;
937
+ last_used_at?: string;
938
+ pending_review_count?: number;
931
939
  id: string;
932
940
  name: string;
933
941
  description: string;
@@ -944,6 +952,9 @@ interface Category {
944
952
  }
945
953
  /** Browse filter for the category registry (spec §5.5). */
946
954
  interface ListCategoriesParams {
955
+ sort?: "popular" | "messages_7d" | "messages_90d" | "last_used" | "pending_reviews" | "name";
956
+ limit?: number;
957
+ page?: string;
947
958
  /** Pure lexical substring filter over name+description (every token must match; NO LLM). */
948
959
  match?: string;
949
960
  }
@@ -1207,6 +1218,8 @@ interface Rule {
1207
1218
  author_kind: "agent" | "human";
1208
1219
  created_at: IsoTimestamp;
1209
1220
  updated_at: IsoTimestamp;
1221
+ source_review_id?: string;
1222
+ source_turn_id?: string;
1210
1223
  }
1211
1224
  /** Filter for the ordered get_rules read (spec §5.4; §7). */
1212
1225
  interface GetRulesParams {
@@ -1228,8 +1241,8 @@ interface RuleSnapshot extends Page<Rule> {
1228
1241
  *
1229
1242
  * Layering (org/project): an agent-plane save is ALWAYS project-layer: the saved
1230
1243
  * rule's `rule_layer` is `project`, bound to the calling key's project. There is no
1231
- * settable `rule_layer` here: an agent cannot create org-layer / house-style
1232
- * (`rule_layer="org"`) rules in v1; authoring org rules is a console/admin action.
1244
+ * settable `rule_layer` here: this method cannot create org-layer rules. Use learnFromReview for
1245
+ * authenticated reviewer feedback, including organization house style.
1233
1246
  * (`scope: "general"` still means a house-style rule WITHIN the project layer :
1234
1247
  * `scope` is the category axis, `rule_layer` is the ownership axis.)
1235
1248
  */
@@ -1891,6 +1904,24 @@ interface WhoAmI {
1891
1904
  key_id: string;
1892
1905
  scopes: Scope[];
1893
1906
  }
1907
+ /** Learn writing guidance from an authenticated human turn on your review. */
1908
+ interface LearnReviewRuleRequest {
1909
+ client_id: string;
1910
+ source_turn_id: string;
1911
+ rule_text: string;
1912
+ target: "org_house" | "project_general" | "category";
1913
+ category_id?: string;
1914
+ kind?: "soft" | "hard";
1915
+ supersedes_id?: string;
1916
+ }
1917
+ interface LearnedReviewRule {
1918
+ rule: Rule;
1919
+ source_review_id: string;
1920
+ source_turn_id: string;
1921
+ human_id: string;
1922
+ audit_id: string;
1923
+ propagation: "queued";
1924
+ }
1894
1925
 
1895
1926
  /**
1896
1927
  * The ONE list envelope + opaque-cursor iteration (redesign §5.2 / §6.2).
@@ -2067,6 +2098,7 @@ interface Transport {
2067
2098
  getScanBacklogStatus(categoryId: string, signal?: AbortSignal): Promise<ScanBacklogStatus>;
2068
2099
  getCategoryPacingState(categoryId: string, signal?: AbortSignal): Promise<CategoryPacingState>;
2069
2100
  getRules(params: GetRulesParams, signal?: AbortSignal): Promise<RuleSnapshot>;
2101
+ learnReviewRule(reviewId: string, req: LearnReviewRuleRequest, signal?: AbortSignal): Promise<LearnedReviewRule>;
2070
2102
  saveRule(req: SaveRuleRequest, signal?: AbortSignal): Promise<Rule>;
2071
2103
  promoteRule(ruleId: string, toScope: "general" | "category", signal?: AbortSignal): Promise<Rule>;
2072
2104
  retireRule(ruleId: string, signal?: AbortSignal): Promise<Rule>;
@@ -2239,6 +2271,7 @@ declare class MockBackend {
2239
2271
  * is a pure lexical filter (every token must appear in name+description) - NO LLM,
2240
2272
  * mirroring the server.
2241
2273
  */
2274
+ private categoryUsage;
2242
2275
  listCategories(params?: ListCategoriesParams): Page<Category>;
2243
2276
  /** Get one category (mock), or undefined when not found. */
2244
2277
  getCategory(categoryId: string): Category | undefined;
@@ -2287,6 +2320,8 @@ declare class MockBackend {
2287
2320
  /** Get the ORDERED active rule set (mock) - §7 ladder + category-before-general. */
2288
2321
  getRules(params?: GetRulesParams): RuleSnapshot;
2289
2322
  /** Save / edit a rule (mock) - append-only by supersession (D11). */
2323
+ private learnedRules;
2324
+ learnReviewRule(reviewId: string, req: LearnReviewRuleRequest): LearnedReviewRule;
2290
2325
  saveRule(req: SaveRuleRequest): Rule;
2291
2326
  /** Promote a rule between layers (mock, via supersession), or undefined when unknown. */
2292
2327
  promoteRule(ruleId: string, toScope: "general" | "category"): Rule | undefined;
@@ -3253,14 +3288,16 @@ declare class Categories {
3253
3288
  */
3254
3289
  declare class Rules {
3255
3290
  private readonly ctx;
3291
+ /** Learn category or organization house rules from verified human review feedback. */
3292
+ learnFromReview(reviewId: string, req: LearnReviewRuleRequest, signal?: AbortSignal): Promise<LearnedReviewRule>;
3256
3293
  constructor(ctx: ResourceContext);
3257
3294
  /** Get the ORDERED active rule set (precedence ladder applied; NO LLM). */
3258
3295
  get(params?: GetRulesParams, signal?: AbortSignal): Promise<RuleSnapshot>;
3259
3296
  /**
3260
3297
  * Save / edit a rule (append-only by supersession; D11). An agent-plane save is
3261
3298
  * ALWAYS project-layer: the saved rule's `rule_layer` is `project`, bound to the
3262
- * key's project. Agents cannot author org-layer / house-style (`rule_layer:"org"`)
3263
- * rules in v1: that is a console/admin action.
3299
+ * key's project. For all authenticated reviewer feedback use learnFromReview at the intended
3300
+ * organization, project, or category scope. This method is project maintenance only.
3264
3301
  */
3265
3302
  save(req: SaveRuleRequest, signal?: AbortSignal): Promise<Rule>;
3266
3303
  /** Promote a rule between the category and general/house-style layers. */
@@ -3963,7 +4000,7 @@ declare function signWebhook(secret: string, body: string, timestampSeconds: num
3963
4000
  *
3964
4001
  * ## Provisional, pre-1.0 (0.x)
3965
4002
  *
3966
- * {@link CONTRACT_VERSION} is **`0.1.0-pre.7`** - a deliberately **provisional**, pre-1.0
4003
+ * {@link CONTRACT_VERSION} is **`0.1.0-pre.9`** - a deliberately **provisional**, pre-1.0
3967
4004
  * contract. It is open and documented, but it MAY still evolve before 1.0: there
3968
4005
  * are no external users yet, and the **D20 shared-pool auto-send governor** is a
3969
4006
  * hard prerequisite before onboarding external users. Pin the version; expect
@@ -4020,12 +4057,12 @@ interface DiffJson {
4020
4057
  /**
4021
4058
  * The published version of the Extrovert Review-Loop open contract (D14).
4022
4059
  *
4023
- * **`0.1.0-pre.7` - PROVISIONAL, pre-1.0.** Versioned *with the SDK* (this package's
4060
+ * **`0.1.0-pre.9` - PROVISIONAL, pre-1.0.** Versioned *with the SDK* (this package's
4024
4061
  * `package.json` version) and aligned to the openapi `info.version`. Open and
4025
4062
  * documented, but MAY still evolve before 1.0 (no external users yet; the D20
4026
4063
  * shared-pool governor is required before external users). Pin it.
4027
4064
  */
4028
- declare const CONTRACT_VERSION: "0.1.0-pre.7";
4065
+ declare const CONTRACT_VERSION: "0.1.0-pre.9";
4029
4066
  /** The stability posture of a published contract version. */
4030
4067
  type ContractStability = "provisional" | "stable";
4031
4068
  /**
@@ -4068,4 +4105,4 @@ interface ContractManifest {
4068
4105
  */
4069
4106
  declare const CONTRACT_MANIFEST: ContractManifest;
4070
4107
 
4071
- export { API_VERSION_HEADER, type AccountRiskDial, type AckReviewEventEntry, type AckReviewEventRequest, type AckReviewEventResult, type AddContactListRequest, type Agent, type AgentStatus, ApiError, type ApiErrorBody, type Attachment, type AttachmentDownload, type AttachmentInput, AuthenticationError, type BatchUpdateMessagesRequest, type BatchUpdateResult, BornStaleError, BreadthRequiredError, CONTRACT_MANIFEST, CONTRACT_VERSION, CURRENT_API_VERSION, Categories, type Category, type CategoryPacingState, type CategoryRiskDial, Commerce, type CommerceBlocker, type CommerceRequest, type CommerceRequestKind, ConflictError, ConnectionError, type ContactListDirection, type ContactListEntry, type ContactListKind, ContactLists, type ContractManifest, type ContractStability, type CreateInboxRequest, type Cursor, DEFAULT_BASE_URL, type DeleteResult, type DiffHunk, type DiffJson, type Domain, type DomainOffboard, type DomainQuote, type DomainReadiness, type DomainRecord, type DomainScope, type DomainStatusEvent, type DomainStatusEventPage, type DomainWaitResult, Domains, type EffectiveRiskDial, type EmailAddress, type EnrollRequest, type EnrollResponse, type ExtractedCredentials, ExtrovertClient as Extrovert, ExtrovertClient, type ExtrovertClientOptions, ForbiddenScopeError, type ForwardRequest, type GetInboxParams, type GetRuleAuditParams, type GetRulesParams, type GraduationStatus, IdempotencyConflictError, type Inbox, type InboxCredentials, InboxHandle, type InboxInclude, type InboxMetadata, type InboxMetadataPatch, type InboxMetadataValue, type InboxStatus, Inboxes, IntentRequiredError, type IsoTimestamp, type Job, type KeyTier, type List, type ListCategoriesParams, type ListCommerceRequestsParams, type ListInboxesParams, type ListMessagesParams, ListPage, type ListParams, type ListReviewEventsParams, type ListReviewsParams, type ListSuppressionsParams, type ListThreadsParams, MOCK_BASE_URL, type MailFolder, type MailboxQuickstart, type MailboxQuickstartCall, type MarkReadRequest, type Message, type MessageDirection, Messages, MockBackend, NotFoundError, type OnboardDomainRequest, type OnboardingMode, PROBLEM_CODES, type PacingItem, type Page, type PageFetcher, PaymentRequiredError, PermissionError, type PostReviewChatRequest, type Problem, type ProblemCode, type ProblemField, type ProjectInboxListParams, ProjectInboxes, Projects, type ProposeCategoryRequest, type ProposeGraduationRequest, type QueuedForReviewResult, type QuoteDomainRequest, REVIEW_PROBLEM_RETRYABLE, RateLimitError, RecipientSuppressedError, type RegisterWebhookRequest, type ReplyRequest, type RequestDomainPurchaseRequest, type RequestPlanChangeRequest, type RestampReviewRequest, type Review, ReviewConflictError, type ReviewDecisionContext, type ReviewEvent, type ReviewEventCursor, type ReviewEventReason, ReviewEvents, type ReviewEventsResult, type ReviewFeedback, type ReviewFeedbackComment, type ReviewInclude, type ReviewIntent, type ReviewMode, type ReviewPolicy, type ReviewState, type ReviewTurn, type ReviewerAction, type ReviewerDecisionRequest, type ReviewerDecisionResult, Reviews, type RiskDial, type Rule, type RuleAuditEntry, type RuleLayer, type RuleSnapshot, Rules, SDK_VERSION, type SaveRuleRequest, type ScanBacklogStatus, type Scope, type SearchMessagesParams, SendNeedsReconciliationError, type SendOutcome, type SendRequest, type SendResult, type SentResult, type SignUpRequest, type SignUpResponse, StaleError, type StreamEvent, type StreamOptions, type SubmitForReviewResult, type SubmitRevisionRequest, type SuppressionEntry, type SuppressionPrecheck, type SuppressionScope, type SuppressionSource, Suppressions, TerminalError, type Thread, type ThreadDetail, Threads, TimeoutError, UnavailableError, type UpdateCategoryRequest, type UpdateInboxRequest, type UpdateWebhookRequest, ValidationError, type VerifyRequest, type VerifyResponse, type VerifyWebhookOptions, type WaitForEmailRequest, type WaitForEmailResult, type WaitForReviewEventParams, type Webhook, type WebhookEvent, type WebhookPayload, Webhooks, type WhoAmI, WrongStateError, extractCredentials, extractLink, extractOtp, isProblemCode, isQueuedForReview, isSentImmediately, listPage, parseKeyTier, parseProblem, parseWebhook, reviewIdOf, sentMessageIdOf, serializeInclude, signWebhook, threadIdOf, tierAllowsOrgWildcard, tierNeedsExplicitBreadth, verifyWebhookSignature };
4108
+ export { API_VERSION_HEADER, type AccountRiskDial, type AckReviewEventEntry, type AckReviewEventRequest, type AckReviewEventResult, type AddContactListRequest, type Agent, type AgentStatus, ApiError, type ApiErrorBody, type Attachment, type AttachmentDownload, type AttachmentInput, AuthenticationError, type BatchUpdateMessagesRequest, type BatchUpdateResult, BornStaleError, BreadthRequiredError, CONTRACT_MANIFEST, CONTRACT_VERSION, CURRENT_API_VERSION, Categories, type Category, type CategoryPacingState, type CategoryRiskDial, Commerce, type CommerceBlocker, type CommerceRequest, type CommerceRequestKind, ConflictError, ConnectionError, type ContactListDirection, type ContactListEntry, type ContactListKind, ContactLists, type ContractManifest, type ContractStability, type CreateInboxRequest, type Cursor, DEFAULT_BASE_URL, type DeleteResult, type DiffHunk, type DiffJson, type Domain, type DomainOffboard, type DomainQuote, type DomainReadiness, type DomainRecord, type DomainScope, type DomainStatusEvent, type DomainStatusEventPage, type DomainWaitResult, Domains, type EffectiveRiskDial, type EmailAddress, type EnrollRequest, type EnrollResponse, type ExtractedCredentials, ExtrovertClient as Extrovert, ExtrovertClient, type ExtrovertClientOptions, ForbiddenScopeError, type ForwardRequest, type GetInboxParams, type GetRuleAuditParams, type GetRulesParams, type GraduationStatus, IdempotencyConflictError, type Inbox, type InboxCredentials, InboxHandle, type InboxInclude, type InboxMetadata, type InboxMetadataPatch, type InboxMetadataValue, type InboxStatus, Inboxes, IntentRequiredError, type IsoTimestamp, type Job, type KeyTier, type LearnReviewRuleRequest, type LearnedReviewRule, type List, type ListCategoriesParams, type ListCommerceRequestsParams, type ListInboxesParams, type ListMessagesParams, ListPage, type ListParams, type ListReviewEventsParams, type ListReviewsParams, type ListSuppressionsParams, type ListThreadsParams, MOCK_BASE_URL, type MailFolder, type MailboxQuickstart, type MailboxQuickstartCall, type MarkReadRequest, type Message, type MessageDirection, Messages, MockBackend, NotFoundError, type OnboardDomainRequest, type OnboardingMode, PROBLEM_CODES, type PacingItem, type Page, type PageFetcher, PaymentRequiredError, PermissionError, type PostReviewChatRequest, type Problem, type ProblemCode, type ProblemField, type ProjectInboxListParams, ProjectInboxes, Projects, type ProposeCategoryRequest, type ProposeGraduationRequest, type QueuedForReviewResult, type QuoteDomainRequest, REVIEW_PROBLEM_RETRYABLE, RateLimitError, RecipientSuppressedError, type RegisterWebhookRequest, type ReplyRequest, type RequestDomainPurchaseRequest, type RequestPlanChangeRequest, type RestampReviewRequest, type Review, ReviewConflictError, type ReviewDecisionContext, type ReviewEvent, type ReviewEventCursor, type ReviewEventReason, ReviewEvents, type ReviewEventsResult, type ReviewFeedback, type ReviewFeedbackComment, type ReviewInclude, type ReviewIntent, type ReviewMode, type ReviewPolicy, type ReviewState, type ReviewTurn, type ReviewerAction, type ReviewerDecisionRequest, type ReviewerDecisionResult, Reviews, type RiskDial, type Rule, type RuleAuditEntry, type RuleLayer, type RuleSnapshot, Rules, SDK_VERSION, type SaveRuleRequest, type ScanBacklogStatus, type Scope, type SearchMessagesParams, SendNeedsReconciliationError, type SendOutcome, type SendRequest, type SendResult, type SentResult, type SignUpRequest, type SignUpResponse, StaleError, type StreamEvent, type StreamOptions, type SubmitForReviewResult, type SubmitRevisionRequest, type SuppressionEntry, type SuppressionPrecheck, type SuppressionScope, type SuppressionSource, Suppressions, TerminalError, type Thread, type ThreadDetail, Threads, TimeoutError, UnavailableError, type UpdateCategoryRequest, type UpdateInboxRequest, type UpdateWebhookRequest, ValidationError, type VerifyRequest, type VerifyResponse, type VerifyWebhookOptions, type WaitForEmailRequest, type WaitForEmailResult, type WaitForReviewEventParams, type Webhook, type WebhookEvent, type WebhookPayload, Webhooks, type WhoAmI, WrongStateError, extractCredentials, extractLink, extractOtp, isProblemCode, isQueuedForReview, isSentImmediately, listPage, parseKeyTier, parseProblem, parseWebhook, reviewIdOf, sentMessageIdOf, serializeInclude, signWebhook, threadIdOf, tierAllowsOrgWildcard, tierNeedsExplicitBreadth, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -266,7 +266,7 @@ var CURRENT_API_VERSION = "2026-06-23";
266
266
  var API_VERSION_HEADER = "Extrovert-Version";
267
267
 
268
268
  // src/http.ts
269
- var SDK_VERSION = "0.1.0-pre.7";
269
+ var SDK_VERSION = "0.1.0-pre.9";
270
270
  function buildUrl(baseUrl, path, query) {
271
271
  const base = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
272
272
  const rel = path.startsWith("/") ? path : `/${path}`;
@@ -936,6 +936,8 @@ ${parent.text}`;
936
936
  var MockBackend = class {
937
937
  constructor() {
938
938
  this.state = freshState();
939
+ /** Save / edit a rule (mock) - append-only by supersession (D11). */
940
+ this.learnedRules = /* @__PURE__ */ new Map();
939
941
  }
940
942
  reset() {
941
943
  this.state = freshState();
@@ -1817,8 +1819,21 @@ var MockBackend = class {
1817
1819
  * is a pure lexical filter (every token must appear in name+description) - NO LLM,
1818
1820
  * mirroring the server.
1819
1821
  */
1822
+ categoryUsage(category) {
1823
+ const now2 = Date.now();
1824
+ const rows = [...this.state.reviews.values()].filter((r) => r.category_id === category.id && Date.parse(r.created_at) <= now2);
1825
+ const count = (days) => rows.filter((r) => Date.parse(r.created_at) >= now2 - days * 864e5).length;
1826
+ return {
1827
+ ...category,
1828
+ message_count_7d: count(7),
1829
+ message_count_30d: count(30),
1830
+ message_count_90d: count(90),
1831
+ last_used_at: rows.map((r) => r.created_at).sort().slice(-1)[0],
1832
+ pending_review_count: rows.filter((r) => ["needs_review", "in_review", "chatting", "rejected", "stale", "approved"].includes(r.state)).length
1833
+ };
1834
+ }
1820
1835
  listCategories(params = {}) {
1821
- let items = [...this.state.categories.values()].filter((c) => !c.merged_into).sort((a, b) => b.created_at.localeCompare(a.created_at));
1836
+ let items = [...this.state.categories.values()].filter((c) => !c.merged_into).map((c) => this.categoryUsage(c)).sort((a, b) => b.created_at.localeCompare(a.created_at));
1822
1837
  const tokens = (params.match ?? "").trim().toLowerCase().split(/\s+/).filter(Boolean);
1823
1838
  if (tokens.length) {
1824
1839
  items = items.filter((c) => {
@@ -1826,15 +1841,22 @@ var MockBackend = class {
1826
1841
  return tokens.every((t) => hay.includes(t));
1827
1842
  });
1828
1843
  }
1829
- return { items, total: items.length };
1844
+ const field = { messages_7d: "message_count_7d", messages_90d: "message_count_90d", pending_reviews: "pending_review_count" }[params.sort] ?? "message_count_30d";
1845
+ items.sort((a, b) => (params.sort === "name" ? a.name.toLowerCase().localeCompare(b.name.toLowerCase()) : params.sort === "last_used" ? 0 : (b[field] ?? 0) - (a[field] ?? 0)) || (b.last_used_at ?? "").localeCompare(a.last_used_at ?? "") || a.id.localeCompare(b.id));
1846
+ const offset = params.page ? JSON.parse(Buffer.from(params.page, "base64url").toString()).o : 0;
1847
+ const total = items.length, limit = params.limit ?? 100;
1848
+ const next = offset + limit < total ? Buffer.from(JSON.stringify({ o: offset + limit, v: 1 })).toString("base64url") : void 0;
1849
+ return { items: items.slice(offset, offset + limit), total, next_cursor: next };
1830
1850
  }
1831
1851
  /** Get one category (mock), or undefined when not found. */
1832
1852
  getCategory(categoryId) {
1833
- return this.state.categories.get(categoryId);
1853
+ const category = this.state.categories.get(categoryId);
1854
+ return category ? this.categoryUsage(category) : void 0;
1834
1855
  }
1835
1856
  /** Propose a category (mock): stands immediately, author_kind=agent (D9). */
1836
1857
  proposeCategory(req) {
1837
1858
  const name = req.name.trim();
1859
+ if ([...this.state.categories.values()].some((c) => !c.merged_into && c.name.toLowerCase() === name.toLowerCase())) throw new ConflictError({ status: 409, code: "conflict", message: "Category name already exists; browse and reuse it." });
1838
1860
  if (!name) {
1839
1861
  throw new ValidationError({ status: 400, code: "invalid", message: "name is required" });
1840
1862
  }
@@ -2040,7 +2062,27 @@ var MockBackend = class {
2040
2062
  composition_token_expires_at: params.scope ? void 0 : new Date(Date.now() + 6e5).toISOString()
2041
2063
  };
2042
2064
  }
2043
- /** Save / edit a rule (mock) - append-only by supersession (D11). */
2065
+ learnReviewRule(reviewId, req) {
2066
+ const fingerprint = JSON.stringify({ reviewId, req });
2067
+ const prior = this.learnedRules.get(req.client_id);
2068
+ if (prior) {
2069
+ if (prior.fingerprint !== fingerprint) throw new ValidationError({ status: 409, code: "conflict", message: "learning retry identity changed" });
2070
+ return structuredClone(prior.result);
2071
+ }
2072
+ const turn = (this.state.reviewTurns.get(reviewId) ?? []).find((t) => t.id === req.source_turn_id);
2073
+ if (!turn || turn.actor_kind !== "human" || !turn.actor_id) throw new ValidationError({ status: 403, code: "forbidden_scope", message: "learning requires authenticated human feedback" });
2074
+ const rule = this.saveRule({ ...req, scope: req.target === "category" ? "category" : "general", source_review_id: reviewId, source_turn_id: turn.id });
2075
+ rule.source_turn_id = turn.id;
2076
+ rule.rule_layer = req.target === "org_house" ? "org" : "project";
2077
+ if (req.target === "org_house") delete rule.project_id;
2078
+ rule.source_review_id = reviewId;
2079
+ rule.source_turn_id = turn.id;
2080
+ const audit = [...this.state.ruleAudit.values()].find((entry) => entry.entity_id === rule.id);
2081
+ audit.after_json = ruleSnapshotJSON(rule);
2082
+ const result = { rule, source_review_id: reviewId, source_turn_id: turn.id, human_id: turn.actor_id, audit_id: audit.id, propagation: "queued" };
2083
+ this.learnedRules.set(req.client_id, { fingerprint, result: structuredClone(result) });
2084
+ return result;
2085
+ }
2044
2086
  saveRule(req) {
2045
2087
  const text = req.rule_text.trim();
2046
2088
  if (!text) {
@@ -3681,6 +3723,7 @@ var HttpTransport = class {
3681
3723
  state: Array.isArray(params.state) ? params.state.join(",") : params.state,
3682
3724
  category_id: params.category_id,
3683
3725
  inbox: params.inbox,
3726
+ composer: params.composer,
3684
3727
  limit: params.limit,
3685
3728
  page: params.page
3686
3729
  };
@@ -3763,10 +3806,12 @@ var HttpTransport = class {
3763
3806
  });
3764
3807
  }
3765
3808
  waitForReviewEvent(params, signal) {
3809
+ const waitSeconds = Math.min(55, Math.max(1, params.wait_seconds ?? 55));
3766
3810
  return this.call({
3767
3811
  method: "GET",
3768
3812
  path: "/v1/reviews/events/wait",
3769
- query: { review_id: params.review_id, limit: params.limit, wait_seconds: params.wait_seconds },
3813
+ query: { review_id: params.review_id, limit: params.limit, wait_seconds: waitSeconds },
3814
+ timeoutMs: (waitSeconds + 10) * 1e3,
3770
3815
  signal
3771
3816
  });
3772
3817
  }
@@ -3779,7 +3824,7 @@ var HttpTransport = class {
3779
3824
  });
3780
3825
  }
3781
3826
  listCategories(params, signal) {
3782
- return this.call({ method: "GET", path: "/v1/categories", query: { match: params.match }, signal });
3827
+ return this.call({ method: "GET", path: "/v1/categories", query: { ...params }, signal });
3783
3828
  }
3784
3829
  getCategory(categoryId, signal) {
3785
3830
  return this.call({ method: "GET", path: `/v1/categories/${encodeURIComponent(categoryId)}`, signal });
@@ -3835,6 +3880,9 @@ var HttpTransport = class {
3835
3880
  signal
3836
3881
  });
3837
3882
  }
3883
+ learnReviewRule(reviewId, req, signal) {
3884
+ return this.call({ method: "POST", path: `/v1/reviews/${encodeURIComponent(reviewId)}/learned-rules`, body: req, signal });
3885
+ }
3838
3886
  saveRule(req, signal) {
3839
3887
  return this.call({
3840
3888
  method: "PUT",
@@ -4242,6 +4290,9 @@ var MockTransport = class {
4242
4290
  async getRules(params) {
4243
4291
  return this.backend.getRules(params);
4244
4292
  }
4293
+ async learnReviewRule(reviewId, req) {
4294
+ return this.backend.learnReviewRule(reviewId, req);
4295
+ }
4245
4296
  async saveRule(req) {
4246
4297
  return this.backend.saveRule(req);
4247
4298
  }
@@ -5271,6 +5322,10 @@ var Rules = class {
5271
5322
  constructor(ctx) {
5272
5323
  this.ctx = ctx;
5273
5324
  }
5325
+ /** Learn category or organization house rules from verified human review feedback. */
5326
+ learnFromReview(reviewId, req, signal) {
5327
+ return this.ctx.transport.learnReviewRule(reviewId, req, signal);
5328
+ }
5274
5329
  /** Get the ORDERED active rule set (precedence ladder applied; NO LLM). */
5275
5330
  get(params = {}, signal) {
5276
5331
  return this.ctx.transport.getRules(params, signal);
@@ -5278,8 +5333,8 @@ var Rules = class {
5278
5333
  /**
5279
5334
  * Save / edit a rule (append-only by supersession; D11). An agent-plane save is
5280
5335
  * ALWAYS project-layer: the saved rule's `rule_layer` is `project`, bound to the
5281
- * key's project. Agents cannot author org-layer / house-style (`rule_layer:"org"`)
5282
- * rules in v1: that is a console/admin action.
5336
+ * key's project. For all authenticated reviewer feedback use learnFromReview at the intended
5337
+ * organization, project, or category scope. This method is project maintenance only.
5283
5338
  */
5284
5339
  save(req, signal) {
5285
5340
  return this.ctx.transport.saveRule(req, signal);
@@ -5556,7 +5611,7 @@ async function signWebhook(secret, body, timestampSeconds) {
5556
5611
  }
5557
5612
 
5558
5613
  // src/contract.ts
5559
- var CONTRACT_VERSION = "0.1.0-pre.7";
5614
+ var CONTRACT_VERSION = "0.1.0-pre.9";
5560
5615
  var CONTRACT_MANIFEST = {
5561
5616
  name: "extrovert.review-loop",
5562
5617
  version: CONTRACT_VERSION,
@@ -5587,6 +5642,8 @@ var CONTRACT_MANIFEST = {
5587
5642
  // realtime (M3)
5588
5643
  "ReviewEventReason",
5589
5644
  "ReviewEventsResult",
5645
+ "LearnReviewRuleRequest",
5646
+ "LearnedReviewRule",
5590
5647
  "ReviewEventCursor",
5591
5648
  // chat / revision / restamp (M5/M7)
5592
5649
  "PostReviewChatRequest",