@ttctl/core 0.1.0-rc.7 → 0.1.0-rc.8

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.
Files changed (39) hide show
  1. package/dist/__generated__/gateway.d.ts +9 -9
  2. package/dist/__generated__/gateway.d.ts.map +1 -1
  3. package/dist/__generated__/zod-schemas.d.ts +9 -9
  4. package/dist/__generated__/zod-schemas.d.ts.map +1 -1
  5. package/dist/__generated__/zod-schemas.js +9 -9
  6. package/dist/__generated__/zod-schemas.js.map +1 -1
  7. package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -1
  8. package/dist/__tests__/fixtures/profile/builders.js +1 -0
  9. package/dist/__tests__/fixtures/profile/builders.js.map +1 -1
  10. package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -1
  11. package/dist/__tests__/fixtures/profile/data.js +2 -0
  12. package/dist/__tests__/fixtures/profile/data.js.map +1 -1
  13. package/dist/consent.d.ts +236 -0
  14. package/dist/consent.d.ts.map +1 -0
  15. package/dist/consent.js +225 -0
  16. package/dist/consent.js.map +1 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/services/applications/index.d.ts +917 -13
  22. package/dist/services/applications/index.d.ts.map +1 -1
  23. package/dist/services/applications/index.js +1284 -6
  24. package/dist/services/applications/index.js.map +1 -1
  25. package/dist/services/jobs/index.d.ts.map +1 -1
  26. package/dist/services/jobs/index.js.map +1 -1
  27. package/dist/services/payments/index.d.ts +66 -0
  28. package/dist/services/payments/index.d.ts.map +1 -1
  29. package/dist/services/payments/index.js +120 -0
  30. package/dist/services/payments/index.js.map +1 -1
  31. package/dist/services/profile/employment/index.d.ts +50 -4
  32. package/dist/services/profile/employment/index.d.ts.map +1 -1
  33. package/dist/services/profile/employment/index.js +73 -16
  34. package/dist/services/profile/employment/index.js.map +1 -1
  35. package/dist/services/profile/reviews/index.d.ts +31 -1
  36. package/dist/services/profile/reviews/index.d.ts.map +1 -1
  37. package/dist/services/profile/reviews/index.js +19 -1
  38. package/dist/services/profile/reviews/index.js.map +1 -1
  39. package/package.json +1 -1
@@ -1,4 +1,8 @@
1
+ import type { JobExpertiseAnswerInput, JobPositionAnswerInput, PitchInput } from "../../__generated__/zod-schemas.js";
2
+ import { JobExpertiseAnswerInputSchema, JobPositionAnswerInputSchema, PitchInputSchema } from "../../__generated__/zod-schemas.js";
1
3
  import type { DryRunPreview } from "../../transport.js";
4
+ export type { JobExpertiseAnswerInput, JobPositionAnswerInput, PitchInput };
5
+ export { JobExpertiseAnswerInputSchema, JobPositionAnswerInputSchema, PitchInputSchema };
2
6
  /**
3
7
  * Applications-domain error codes. Mirrors the `ProfileError` /
4
8
  * `SkillsError` shape per project convention so each sub-domain carries
@@ -14,7 +18,25 @@ import type { DryRunPreview } from "../../transport.js";
14
18
  * `NOT_FOUND` so the CLI can render a "no such application" line and
15
19
  * the MCP tool can return a structured `(NOT_FOUND)` error response.
16
20
  */
17
- export type ApplicationsErrorCode = "NO_VIEWER" | "NOT_FOUND" | "GRAPHQL_ERROR" | "MUTATION_ERROR" | "NETWORK_ERROR" | "WIRE_SHAPE_ERROR" | "UNKNOWN";
21
+ export type ApplicationsErrorCode = "NO_VIEWER" | "NOT_FOUND" | "GRAPHQL_ERROR" | "MUTATION_ERROR" | "NETWORK_ERROR" | "WIRE_SHAPE_ERROR"
22
+ /**
23
+ * Direct-apply consent gate (#426). The wire's `consentIssued: Boolean!`
24
+ * is a legal-compliance attestation; the service refuses to issue the
25
+ * mutation unless the caller explicitly passes `consentIssued: true`
26
+ * on {@link ApplyInput}. Same posture #411 took on the DESTRUCTIVE
27
+ * IR mutations, with the legal dimension added. Fired before any wire
28
+ * call.
29
+ */
30
+ | "CONSENT_REQUIRED"
31
+ /**
32
+ * Direct-apply double-application gate (#426). The wire returns
33
+ * `success: false` with `errors[].key === "already_applied"` when the
34
+ * talent has previously applied to the same job. Mapped to a typed
35
+ * code so callers (CLI / MCP / agents) can surface a "you already
36
+ * applied" hint pointing at `ttctl applications show <activity-id>`
37
+ * instead of the generic `MUTATION_ERROR` envelope.
38
+ */
39
+ | "ALREADY_APPLIED" | "UNKNOWN";
18
40
  export declare class ApplicationsError extends Error {
19
41
  readonly code: ApplicationsErrorCode;
20
42
  readonly name = "ApplicationsError";
@@ -260,13 +282,17 @@ export interface AvailabilityRequestRespondPayload {
260
282
  * {@link AvailabilityRequestKind} for the value spellings.
261
283
  * - `comment` (optional) — the talent's free-text accompanying message.
262
284
  * Mapped to the wire's `talentComment` field.
263
- * - `matcherQuestionsAnswers`, `expertiseQuestionsAnswers`, `pitchData`
285
+ * - `matcherQuestionsAnswers`, `expertiseQuestionsAnswers`, `pitchInput`
264
286
  * (optional) — structural inputs for AR confirmations that require
265
- * matcher / expertise question answers or a custom pitch. These are
266
- * wire pass-throughs; the service does NOT introspect them. v1
267
- * exposes them as `unknown` arrays — callers passing them are
268
- * responsible for the wire shape (`JobPositionAnswerInput[]`,
269
- * `JobExpertiseAnswerInput[]`, `PitchInput`).
287
+ * matcher / expertise question answers or a custom pitch. Stage-2
288
+ * (#438) types these against the recovered SDL shapes
289
+ * {@link JobPositionAnswerInput}, {@link JobExpertiseAnswerInput},
290
+ * {@link PitchInput} (regenerated from #425's recovery output).
291
+ * `matcherQuestionsAnswers` entries use `id` (NOT `questionId`) per
292
+ * the SDL; `expertiseQuestionsAnswers` entries use `questionId`.
293
+ * The service still passes them through to the wire opaquely; the
294
+ * typing is the boundary contract for CLI / MCP / direct-Core
295
+ * callers.
270
296
  */
271
297
  export interface ConfirmInput {
272
298
  /** Optional talent-side free-text message. Wire field: `talentComment`. */
@@ -275,12 +301,12 @@ export interface ConfirmInput {
275
301
  requestedHourlyRate?: string;
276
302
  /** AR kind. Auto-detected from `metadata.__typename` when omitted. INFERRED enum values — see {@link AvailabilityRequestKind}. */
277
303
  kind?: AvailabilityRequestKind;
278
- /** Optional matcher-questions answers (`JobPositionAnswerInput[]`). v1: opaque pass-through. */
279
- matcherQuestionsAnswers?: unknown[];
280
- /** Optional expertise-questions answers (`JobExpertiseAnswerInput[]`). v1: opaque pass-through. */
281
- expertiseQuestionsAnswers?: unknown[];
282
- /** Optional pitch input (`PitchInput`). v1: opaque pass-through. */
283
- pitchInput?: Record<string, unknown>;
304
+ /** Optional matcher-questions answers — wire shape `JobPositionAnswerInput[]` (`{ id, answer }`). */
305
+ matcherQuestionsAnswers?: JobPositionAnswerInput[];
306
+ /** Optional expertise-questions answers — wire shape `JobExpertiseAnswerInput[]` (`{ questionId, other, subjectId }`). */
307
+ expertiseQuestionsAnswers?: JobExpertiseAnswerInput[];
308
+ /** Optional pitch input wire shape `PitchInput`. */
309
+ pitchInput?: PitchInput;
284
310
  }
285
311
  /**
286
312
  * Input for {@link reject}. The wire mutation's input takes
@@ -473,6 +499,259 @@ export declare function show(token: string, id: string): Promise<JobActivityItem
473
499
  * user knows exactly what went wrong.
474
500
  */
475
501
  export declare function stats(token: string): Promise<ApplicationsStats>;
502
+ /**
503
+ * One entry of `viewer.job.operations.apply.errors` (#424). Schema
504
+ * declares both fields as `String!` — non-null — but the projection
505
+ * helper {@link projectApplyErrors} keeps a defensive list-entry null
506
+ * filter because the WIRE shape on the schema-gap path (this op is in
507
+ * `GATEWAY_MOBILE_KNOWN_UNTRUSTED_OPS`) is best-effort.
508
+ */
509
+ export interface ApplyError {
510
+ code: string;
511
+ message: string;
512
+ }
513
+ /**
514
+ * Aggregate pre-apply context returned by {@link applyData} (#424).
515
+ *
516
+ * Surfaces the load-bearing scalars from the captured `JobApplyData`
517
+ * operation — the suggested rate (REQ-A4), platform validation
518
+ * bounds, the apply-state errors, and basic job context — trimmed of
519
+ * the heavy pitch / talent-card / market-condition cascades the
520
+ * captured op also pulls in. Downstream consumers:
521
+ *
522
+ * - **#426 (apply core fn)** — reads `canApply` to short-circuit
523
+ * before the mutation, uses `suggestedRate` as the
524
+ * `requestedHourlyRate` default, validates against `rateValidation`.
525
+ * - **#437 (`jobs show`)** — surfaces `applyErrors` so the user can
526
+ * see WHY they can't apply (already applied, job closed, etc.)
527
+ * directly on the job-detail view.
528
+ *
529
+ * `canApply` is a convenience boolean derived from
530
+ * `applyErrors.length === 0` — kept as a separate field so callers
531
+ * don't have to recompute it.
532
+ */
533
+ export interface PreApplyData {
534
+ job: {
535
+ id: string;
536
+ isCoaching: boolean | null;
537
+ hasRequiredApplicationPitch: boolean | null;
538
+ };
539
+ /** Empty when the talent may apply; populated lists the blocking reasons. */
540
+ applyErrors: ApplyError[];
541
+ /** Convenience: `true` iff `applyErrors` is empty. */
542
+ canApply: boolean;
543
+ /**
544
+ * Talent's configured hourly rate (`viewerRole.rates.hourly`). The
545
+ * apply path uses this as the `requestedHourlyRate` default
546
+ * (REQ-A4). `null` when the viewerRole is absent (defensive — the
547
+ * schema declares `ViewerRole.rates.hourly: String!`, but absence
548
+ * is treated as null projection rather than a hard error).
549
+ */
550
+ suggestedRate: string | null;
551
+ /**
552
+ * Platform hourly-rate validation bounds. `null` when the platform
553
+ * configuration block is absent (defensive — the schema declares
554
+ * `PlatformConfiguration.rateValidationRules: TalentRateValidationRules!`
555
+ * non-null, but gateway-side absence is surfaced as null projection
556
+ * rather than a hard error). Note `rateStep` is `Int` on the wire,
557
+ * not a decimal string.
558
+ */
559
+ rateValidation: {
560
+ minRate: string;
561
+ rateStep: number;
562
+ } | null;
563
+ }
564
+ /**
565
+ * One question on the apply form (#424). The four-field shape is
566
+ * uniform across matcher and expertise variants per REQ-Q1:
567
+ *
568
+ * - `identifier` — the wire `id` field (`JobPositionQuestion.id` /
569
+ * `JobExpertiseQuestion.id`). Threaded into the apply-mutation
570
+ * answer arrays at asymmetric field names per the recovered SDL:
571
+ * `JobPositionAnswerInput.id` (matcher) and
572
+ * `JobExpertiseAnswerInput.questionId` (expertise). Both reference
573
+ * this same `identifier`; see ADR-008 § Decision Part 2 and #438
574
+ * for the recovered-shape rationale.
575
+ * - `prompt` — the human-readable question text. For matcher
576
+ * questions: the wire `question` field. For expertise questions:
577
+ * the `subject.name` (`Industry.name` or `Skill.name`) — expertise
578
+ * questions ask "which of your profile items demonstrates this
579
+ * skill / industry?", so the subject's name IS the prompt the
580
+ * user sees.
581
+ * - `type` — TTCtl-side discriminant `"matcher" | "expertise"`,
582
+ * making each question self-describing if consumers flatten the
583
+ * two arrays (e.g., #426's answers-file template builder).
584
+ * - `isMandatory` — for matcher questions, the wire `isRequired`
585
+ * field. For expertise questions: projected as `true`. The
586
+ * captured `JobApplicationQuestions` operation selects no
587
+ * per-question mandatory flag on `expertiseQuestions` (and the
588
+ * synthesized schema doesn't even declare `JobExpertiseQuestion`),
589
+ * but the `JobApply` mutation takes
590
+ * `$expertiseQuestionsAnswers: [JobExpertiseAnswerInput!]` as a
591
+ * required apply-payload field (research note
592
+ * `03-applications.md` § Apply flow specifics: "Both question
593
+ * types ... must be fetched first ... The client cannot guess
594
+ * them"). Documented inference; #445 live E2E is the wire
595
+ * authority and may refine this projection if real data surfaces
596
+ * a more nuanced mandatory-ness signal.
597
+ */
598
+ export interface ApplicationQuestion {
599
+ identifier: string;
600
+ prompt: string;
601
+ type: "matcher" | "expertise";
602
+ isMandatory: boolean;
603
+ }
604
+ /**
605
+ * Questions inventory returned by {@link applyQuestions} (#424).
606
+ * Mirrors the captured `JobApplicationQuestions` operation's two
607
+ * parallel selections — `viewer.job.questions(hideExpertiseQuestion:
608
+ * true)` for matcher questions, `viewer.job.expertiseQuestions` for
609
+ * expertise — projecting each entry to the four-field
610
+ * {@link ApplicationQuestion} shape. Empty arrays surface verbatim
611
+ * when the job has no questions of that kind.
612
+ */
613
+ export interface ApplicationQuestions {
614
+ matcherQuestions: ApplicationQuestion[];
615
+ expertiseQuestions: ApplicationQuestion[];
616
+ }
617
+ /**
618
+ * Rate insight when the talent's rate (or default rate) is judged
619
+ * COMPETITIVE relative to the job's market (#424). Discriminated-union
620
+ * member of {@link RateInsight}; surfaces the captured wire's
621
+ * `TalentJobRateInsightCompetitive` fields verbatim.
622
+ *
623
+ * All revenue / rate fields are `BigDecimal` decimal-string scalars
624
+ * per the captured wire (the captured
625
+ * `JobApplicationRateInsight.graphql` operation selects them bare,
626
+ * no `{ }` sub-selection; the synthesized schema confirms
627
+ * `BigDecimal`). They are NOT a `Money { decimal verbose }` shape —
628
+ * see PR body for the deviation from the issue parenthetical.
629
+ */
630
+ export interface CompetitiveRateInsight {
631
+ kind: "competitive";
632
+ /** Estimated revenue at the supplied rate (BigDecimal scalar). */
633
+ estimatedRevenue: string | null;
634
+ /** Server-localised prose explaining the revenue estimate. */
635
+ estimatedRevenueExplanation: string | null;
636
+ /** Server-localised disclaimer about long-term engagement assumptions. */
637
+ longTermDisclaimer: string | null;
638
+ }
639
+ /**
640
+ * Rate insight when the talent's rate (or default rate) is judged
641
+ * UNCOMPETITIVE relative to the job's market (#424).
642
+ * Discriminated-union member of {@link RateInsight}; surfaces the
643
+ * captured wire's `TalentJobRateInsightUncompetitive` fields verbatim.
644
+ *
645
+ * `recentApplicationRate` + `recommendedRate` together form the
646
+ * "range guidance" the apply path uses to inform the talent
647
+ * (`recentApplicationRate` = empirical rate of recent successful
648
+ * applicants on this specific job; `recommendedRate` = Toptal's
649
+ * suggested rate to be competitive). Both are `BigDecimal`
650
+ * decimal-string scalars on the wire.
651
+ */
652
+ export interface UncompetitiveRateInsight {
653
+ kind: "uncompetitive";
654
+ estimatedRevenue: string | null;
655
+ estimatedRevenueExplanation: string | null;
656
+ /** Empirical rate of recent successful applicants (BigDecimal scalar). */
657
+ recentApplicationRate: string | null;
658
+ /** Toptal's suggested rate to be competitive (BigDecimal scalar). */
659
+ recommendedRate: string | null;
660
+ }
661
+ /**
662
+ * Discriminated-union projection of the wire's `TalentJobRateInsight`
663
+ * union (members `TalentJobRateInsightCompetitive` |
664
+ * `TalentJobRateInsightUncompetitive`). The `kind` discriminant
665
+ * narrows access to the variant-specific fields. Returned by
666
+ * {@link rateInsight}; `null` when the gateway omits the rate-insight
667
+ * payload (viewer null, job null, or `rateInsight` field null).
668
+ */
669
+ export type RateInsight = CompetitiveRateInsight | UncompetitiveRateInsight;
670
+ /**
671
+ * Pre-apply aggregate context for a job (#424). Wraps `JobApplyData
672
+ * ($jobId)` — the mobile gateway's aggregate pre-apply query — and
673
+ * trims the response to the load-bearing scalars (REQ-A4 rate
674
+ * default, apply-state errors, platform validation bounds, plus
675
+ * basic job context). The captured operation also pulls in the
676
+ * pitch / talent-card / market-condition cascades; those are
677
+ * deliberately elided here. The apply path (#426) takes the pitch
678
+ * from `--pitch-file` per ADR-008's grammar, NOT from
679
+ * `suggestedPitch` / `lastPitches`, and `applyQuestions` /
680
+ * `rateInsight` cover the other captured slices. Future widening is
681
+ * additive.
682
+ *
683
+ * **Wire authority**: hand-authored from the captured
684
+ * `JobApplyData.graphql` selection set; CLAUDE.md schema/contract
685
+ * rule TRIGGERED for #424, live E2E coverage in #445.
686
+ *
687
+ * **Bad-id behavior**: `viewer.job(id:)` returns the Relay decode
688
+ * error (per `project-toptal-wire-quirks` memory) when the supplied
689
+ * id doesn't resolve to a viewable job; remapped to
690
+ * `ApplicationsError("NOT_FOUND")` via the shared
691
+ * {@link NOT_FOUND_MESSAGE_PATTERN} (widened in #424).
692
+ *
693
+ * @throws `ApplicationsError("NOT_FOUND")` when the job id doesn't
694
+ * resolve (Relay decode error, `Invalid ID`, `Record not found`,
695
+ * or successful response with `viewer.job === null`).
696
+ * @throws `ApplicationsError("NO_VIEWER")` when the session is valid
697
+ * but no viewer is bound (defensive — `callGateway` with
698
+ * `requireViewer: true` already raises this case, but the
699
+ * post-call null check keeps the type narrowing clean).
700
+ */
701
+ export declare function applyData(token: string, jobId: string): Promise<PreApplyData>;
702
+ /**
703
+ * Pre-apply matcher + expertise questions inventory for a job (#424).
704
+ * Wraps `JobApplicationQuestions($jobId)`; trims the captured
705
+ * operation's `subject.possibleAnswers` cascades — the four-field
706
+ * {@link ApplicationQuestion} shape is the public projection per
707
+ * #424 AC.
708
+ *
709
+ * The two arrays surface verbatim presence: empty when the job has
710
+ * no questions of that kind. Order is server-supplied; no
711
+ * client-side re-sorting.
712
+ *
713
+ * **Bad-id behavior + NOT_FOUND mapping**: identical to
714
+ * {@link applyData}.
715
+ *
716
+ * @throws `ApplicationsError("NOT_FOUND")` for unresolved job ids.
717
+ * @throws `ApplicationsError("NO_VIEWER")` for sessions with no
718
+ * bound viewer.
719
+ */
720
+ export declare function applyQuestions(token: string, jobId: string): Promise<ApplicationQuestions>;
721
+ /**
722
+ * Pre-apply rate guidance for a job (#424). Wraps
723
+ * `JobApplicationRateInsight($jobId)`; surfaces the captured
724
+ * operation's `TalentJobRateInsight` discriminated union as
725
+ * {@link RateInsight}. Returns `null` when the gateway omits the
726
+ * insight payload (the `rateInsight` field on the job resolves to
727
+ * null).
728
+ *
729
+ * The operation declares `$requestedRate: BigDecimal` (verbatim from
730
+ * the captured wire) but the public signature does NOT expose
731
+ * `requestedRate` per #424 AC — the variable is threaded as `null`,
732
+ * which the gateway treats as "show me the insight for the talent's
733
+ * default rate". Re-exposing the parameter is a future widening.
734
+ *
735
+ * **Wire shape**: union members carry `BigDecimal` scalar fields
736
+ * (`estimatedRevenue`, `recommendedRate`, `recentApplicationRate`)
737
+ * — NOT `Money { decimal verbose }` objects. The captured
738
+ * `JobApplicationRateInsight.graphql` operation selects them bare
739
+ * (no sub-selection), and the synthesized schema confirms
740
+ * `BigDecimal`. The #424 issue parenthetical "Money shape `{ decimal,
741
+ * verbose }` + range guidance" reflects an intuition rather than the
742
+ * captured wire; the captured operation's selection set is
743
+ * authoritative per the issue's own primary directive ("define shape
744
+ * based on captured operation's selection set"). PR body documents
745
+ * the deviation.
746
+ *
747
+ * **Bad-id behavior + NOT_FOUND mapping**: identical to
748
+ * {@link applyData}.
749
+ *
750
+ * @throws `ApplicationsError("NOT_FOUND")` for unresolved job ids.
751
+ * @throws `ApplicationsError("NO_VIEWER")` for sessions with no
752
+ * bound viewer.
753
+ */
754
+ export declare function rateInsight(token: string, jobId: string): Promise<RateInsight | null>;
476
755
  /**
477
756
  * Confirm an Interest Request — wire `ConfirmAvailabilityRequest` (#411).
478
757
  *
@@ -536,4 +815,629 @@ export declare function reject(token: string, id: string, input: RejectInput, op
536
815
  * field is non-null in the schema; absence is wire-shape drift).
537
816
  */
538
817
  export declare function rejectReasons(token: string): Promise<AvailabilityRequestRejectReasons>;
818
+ /**
819
+ * Input for {@link apply}. Field names mirror ADR-008's locked grammar
820
+ * (`matcherAnswers` / `expertiseAnswers` / `pitchData` / `message`)
821
+ * which is the MCP-side schema key set, NOT the wire-side variable
822
+ * names (`matcherQuestionsAnswers`, `expertiseQuestionsAnswers`,
823
+ * `talentCard`, `comment`). The service maps the public field names
824
+ * onto the wire variables internally.
825
+ *
826
+ * **Consent gate**: `consentIssued` is the literal `true` — the
827
+ * tightest type-system constraint TS supports, matching ADR-008
828
+ * § Decision Part 4. The runtime check covers `as`-cast bypasses
829
+ * and JSON-sourced inputs from the CLI/MCP layers where the type
830
+ * system can't reach. Auto-filling consent on the caller's behalf is
831
+ * FORBIDDEN by the same ADR; the service throws
832
+ * `CONSENT_REQUIRED` BEFORE any wire call when omitted.
833
+ *
834
+ * **Rate default**: `requestedHourlyRate` is optional at the input
835
+ * surface. When omitted, the service threads
836
+ * `PreApplyData.suggestedRate` (the talent's own configured rate
837
+ * `viewerRole.rates.hourly`) into the mutation per REQ-A4. If the
838
+ * talent has no configured rate, the service throws `MUTATION_ERROR`.
839
+ * The `rateInsight` payload returned by the pre-fetch suite serves as
840
+ * additional guidance for the caller (CLI / MCP / agent) — not as a
841
+ * silent default; callers surface it to the user before the apply.
842
+ *
843
+ * **Answer arrays**: `matcherAnswers` / `expertiseAnswers` are typed
844
+ * against the recovered `JobPositionAnswerInput[]` /
845
+ * `JobExpertiseAnswerInput[]` shapes (Stage 2 per #438; the recovered
846
+ * schemas are committed in `packages/core/src/__generated__/zod-schemas.ts`).
847
+ * The service validates each entry's id field against the inventory
848
+ * returned by `applyQuestions(jobId)` and rejects unknown ids with
849
+ * `WIRE_SHAPE_ERROR`. The id-field name is **asymmetric** per the
850
+ * recovered SDL — matcher entries carry `id`, expertise entries carry
851
+ * `questionId`.
852
+ */
853
+ export interface ApplyInput {
854
+ /**
855
+ * Consent attestation — MUST be the literal `true`. Auto-filling
856
+ * this field on the caller's behalf is FORBIDDEN per ADR-008
857
+ * § Decision Part 4 (legal compliance).
858
+ */
859
+ consentIssued: true;
860
+ /**
861
+ * Hourly rate the talent requests for this engagement. Decimal
862
+ * string (matches `BigDecimal!`). When omitted, the service
863
+ * defaults from `PreApplyData.suggestedRate` (REQ-A4).
864
+ */
865
+ requestedHourlyRate?: string;
866
+ /**
867
+ * Optional talent-side free-text accompanying message. Mapped to
868
+ * the wire's `$comment` variable / `JobApplyInput.comment` field.
869
+ */
870
+ message?: string;
871
+ /**
872
+ * Matcher-question answers (`JobPositionAnswerInput[]`). Each
873
+ * entry MUST carry an `id` field matching one returned from
874
+ * `applyQuestions(jobId).matcherQuestions[].identifier` — the
875
+ * service rejects unknown ids with `WIRE_SHAPE_ERROR`. Stage 2
876
+ * (#438) types the array against the recovered SDL shape
877
+ * `{ answer: string, id: string }` (NOT `questionId` — distinct
878
+ * from the expertise shape; this field-name asymmetry is per the
879
+ * recovered SDL).
880
+ */
881
+ matcherAnswers?: JobPositionAnswerInput[];
882
+ /**
883
+ * Expertise-question answers (`JobExpertiseAnswerInput[]`). Each
884
+ * entry's `questionId` is validated against
885
+ * `applyQuestions(jobId).expertiseQuestions[].identifier`. Stage 2
886
+ * (#438) types the array against the recovered SDL shape
887
+ * `{ other: string|null, questionId: string, subjectId: string|null }`.
888
+ */
889
+ expertiseAnswers?: JobExpertiseAnswerInput[];
890
+ /**
891
+ * Pitch input (`PitchInput`). Mapped to the wire's `$talentCard`
892
+ * variable / `JobApplyInput.pitchData` field. Stage 2 (#438) types
893
+ * the field against the recovered `PitchInput` shape (`mentorship`
894
+ * remains `unknown` per ADR-008 spike outcome — the position is
895
+ * untyped in the SDL).
896
+ */
897
+ pitchData?: PitchInput;
898
+ }
899
+ /**
900
+ * Projected `JobApplication` record returned by {@link apply} on the
901
+ * apply-success path. Reads the post-mutation `JobApplication` echo
902
+ * routed through the new activity-item's nested `jobApplication`
903
+ * field on `TalentJob.activityItem`.
904
+ *
905
+ * Shape is the conservative initial projection per #426 AC; #445 live
906
+ * E2E is the wire authority and may widen the projection if real
907
+ * responses surface fields the CLI / MCP need to render.
908
+ */
909
+ export interface JobApplicationRecord {
910
+ /** `JobApplication.id` — the new application's identifier. */
911
+ id: string;
912
+ /** Application status (specific value + verbose label, projected from `TalentJobActivityItem.statusV2`). */
913
+ statusV2: ApplicationStatus;
914
+ /**
915
+ * The rate the wire echoes back on the new `JobApplication`. The
916
+ * captured op selects `requestedHourlyRate { decimal }` only — no
917
+ * `verbose` — and the projection mirrors that selection until #445
918
+ * confirms `verbose` is selectable on this position.
919
+ */
920
+ requestedHourlyRate: {
921
+ decimal: string;
922
+ } | null;
923
+ /**
924
+ * The `TalentJobActivityItem.id` that wraps the new application —
925
+ * the id callers pass to `applications show` to view the new row.
926
+ */
927
+ jobActivityItemId: string;
928
+ }
929
+ /**
930
+ * Apply-path outcome for {@link apply}. Carries the post-mutation
931
+ * {@link JobApplicationRecord} projection.
932
+ */
933
+ export interface JobApplyAppliedOutcome {
934
+ kind: "applied";
935
+ result: JobApplicationRecord;
936
+ }
937
+ /**
938
+ * Dry-run outcome for {@link apply}. Mirrors the
939
+ * `AvailabilityRequestDryRunPreviewOutcome` pattern from #411 —
940
+ * named separately for surface symmetry on the apply path.
941
+ */
942
+ export interface JobApplyDryRunPreviewOutcome {
943
+ kind: "preview";
944
+ preview: DryRunPreview;
945
+ }
946
+ /**
947
+ * Discriminated-union return type for {@link apply}.
948
+ */
949
+ export type ApplyOutcome = JobApplyAppliedOutcome | JobApplyDryRunPreviewOutcome;
950
+ /**
951
+ * Direct-apply to a Toptal job — wire `JobApply` (#426, ADR-008
952
+ * § Decision Part 5).
953
+ *
954
+ * Flow:
955
+ *
956
+ * 1. **Consent gate**: refuses the call (`CONSENT_REQUIRED`) BEFORE
957
+ * any wire call when `input.consentIssued !== true`. Type-system
958
+ * gate at `ApplyInput.consentIssued: true` covers compile-time;
959
+ * the runtime check covers `as`-cast bypasses and JSON-sourced
960
+ * inputs.
961
+ * 2. **Dry-run short-circuit**: when `options.dryRun === true`,
962
+ * emits a {@link DryRunPreview} with the prepared variables
963
+ * (including `<resolved at apply time>` placeholders for fields
964
+ * that would have been resolved by the pre-fetch) and returns
965
+ * `{ kind: "preview", preview }`. Zero wire calls under dry-run —
966
+ * including the 3 pre-fetch calls.
967
+ * 3. **Pre-fetch via Promise.all**: runs `applyData` +
968
+ * `applyQuestions` + `rateInsight` concurrently. Promise.all
969
+ * rejects-on-first; any pre-fetch failure (NOT_FOUND,
970
+ * GRAPHQL_ERROR, AuthRevokedError) blocks the apply.
971
+ * 4. **Answer validation**: every `matcherAnswers[]` /
972
+ * `expertiseAnswers[]` entry's `questionId` must resolve against
973
+ * the inventory; unknown ids throw `WIRE_SHAPE_ERROR` with the
974
+ * offending array path.
975
+ * 5. **Rate default**: when `input.requestedHourlyRate` is omitted,
976
+ * threads `PreApplyData.suggestedRate` (the talent's own
977
+ * configured rate). Throws `MUTATION_ERROR` if neither source
978
+ * yields a rate.
979
+ * 6. **Wire call**: issues `JobApply` against the mobile gateway.
980
+ * 7. **Error mapping**: a `MutationResult.errors[]` entry with
981
+ * `key === "already_applied"` is mapped to `ALREADY_APPLIED`
982
+ * with a hint pointing at `ttctl applications show
983
+ * <activity-id>`. Other `success: false` responses surface as
984
+ * `MUTATION_ERROR` with the formatted error detail.
985
+ *
986
+ * **Bad-id behavior**: mutations crash 500 on bad ids per
987
+ * `project-toptal-wire-quirks` auto-memory. The service does NOT
988
+ * pre-validate the job id; the pre-fetch suite (`applyData` etc.)
989
+ * already surfaces NOT_FOUND via the shared widened
990
+ * {@link NOT_FOUND_MESSAGE_PATTERN} when the bad id is detected
991
+ * read-side.
992
+ */
993
+ export declare function apply(token: string, jobId: string, input: ApplyInput, options?: DryRunOptions): Promise<ApplyOutcome>;
994
+ /**
995
+ * One historical answer to a question similar to the queried one.
996
+ * Wire selection: `JobPositionAnswer { id answer createdAt }` per the
997
+ * captured `SimilarJobQuestionAnswers.graphql` operation. `createdAt`
998
+ * is selected on a schema-gap position (`JobPositionAnswer.createdAt`
999
+ * is not declared on the synthesized SDL — see the schema-gap note in
1000
+ * the inline query string below); the projection is `string` here per
1001
+ * the empirical wire shape, the T1 snapshot is the authority.
1002
+ */
1003
+ export interface SimilarJobAnswer {
1004
+ /** `JobPositionAnswer.id` — the historical answer's identifier. */
1005
+ id: string;
1006
+ /** The historical answer text (`JobPositionAnswer.answer`). */
1007
+ answer: string;
1008
+ /** ISO 8601 timestamp the historical answer was authored. */
1009
+ createdAt: string;
1010
+ }
1011
+ /**
1012
+ * One group of suggestions, keyed by the question identifier the
1013
+ * suggestions were resolved against. `questionId` mirrors the wire
1014
+ * filter (`forQuestionsSimilarToQuestionId: <questionId>`). The
1015
+ * `suggestions` array carries the talent's own historical answers to
1016
+ * SIMILAR questions on prior applications — useful as autocomplete
1017
+ * candidates the user can review and selectively re-use when authoring
1018
+ * an application.
1019
+ *
1020
+ * Empty `suggestions` arrays surface verbatim: the wire returned zero
1021
+ * similar-job history for this question. Common for new talent
1022
+ * accounts and unique question prompts.
1023
+ */
1024
+ export interface SimilarJobAnswerGroup {
1025
+ /**
1026
+ * The `ApplicationQuestion.identifier` (from
1027
+ * {@link ApplicationQuestion}) the suggestions were resolved
1028
+ * against — both matcher and expertise question identifiers are
1029
+ * accepted.
1030
+ */
1031
+ questionId: string;
1032
+ /**
1033
+ * Historical answers to questions semantically similar to the one
1034
+ * identified by `questionId`. Order is server-supplied; the helper
1035
+ * does NOT re-sort.
1036
+ */
1037
+ suggestions: SimilarJobAnswer[];
1038
+ }
1039
+ /**
1040
+ * Fetch the talent's similar-answer suggestions for every question on
1041
+ * a job's apply form (#452).
1042
+ *
1043
+ * Returns one {@link SimilarJobAnswerGroup} per question — matcher
1044
+ * AND expertise. The order mirrors the underlying
1045
+ * {@link applyQuestions} inventory (matcher questions first, then
1046
+ * expertise; server-supplied order within each section).
1047
+ *
1048
+ * **Cardinality**: N+1 wire calls — first an {@link applyQuestions}
1049
+ * fetch to resolve the question identifier list, then N parallel
1050
+ * `SimilarJobQuestionAnswers` calls (one per question) via
1051
+ * `Promise.all`. The fan-out matches the mobile app's apply-screen
1052
+ * autocomplete behavior; aggregating server-side is not exposed by
1053
+ * the wire.
1054
+ *
1055
+ * **Bad-id behavior**: a bad `jobId` surfaces NOT_FOUND from
1056
+ * `applyQuestions` (same mapping as the rest of the pre-apply suite).
1057
+ * A per-question `SimilarJobQuestionAnswers` call that surfaces
1058
+ * NOT_FOUND propagates verbatim via `Promise.all`'s reject-on-first
1059
+ * — intentional: callers that want graceful per-question fallback
1060
+ * (e.g. the CLI's `--suggest-answers` flag) should catch the rejection
1061
+ * and continue without suggestions.
1062
+ *
1063
+ * **Performance**: when the job has zero questions, the call resolves
1064
+ * to `[]` after the single `applyQuestions` fetch — no wasted parallel
1065
+ * round-trips. When the job has questions but the talent's account
1066
+ * has no similar-job history, each per-question call returns an empty
1067
+ * `suggestions` array; surface the empty grouping verbatim.
1068
+ *
1069
+ * **Off the critical apply path**: this fn is NOT called from
1070
+ * {@link apply}. It's opt-in via the CLI's `--suggest-answers` flag
1071
+ * (#452) and the MCP's `ttctl_jobs_apply_similar_answers` tool. The
1072
+ * design rationale is in the ADR-008 follow-ups thread.
1073
+ *
1074
+ * @param token - Bearer token from the resolved auth config.
1075
+ * @param jobId - The `TalentJob.id` to resolve questions against.
1076
+ * @throws `ApplicationsError("NOT_FOUND")` when the jobId or a
1077
+ * resolved questionId doesn't resolve.
1078
+ * @throws `ApplicationsError("NO_VIEWER")` for sessions with no
1079
+ * bound viewer.
1080
+ */
1081
+ export declare function similarAnswers(token: string, jobId: string): Promise<SimilarJobAnswerGroup[]>;
1082
+ /**
1083
+ * `InterviewStatusEnum` values from the synthesized schema
1084
+ * (`../research/graphql/gateway/schema.graphql`). Closed set.
1085
+ */
1086
+ export type InterviewStatus = "ACCEPTED" | "MISSED" | "PENDING" | "REJECTED" | "SCHEDULED" | "TIME_ACCEPTED" | "TIME_REJECTED";
1087
+ export declare const INTERVIEW_STATUSES: readonly InterviewStatus[];
1088
+ /**
1089
+ * `InterviewKindEnum` values from the synthesized schema. `INTERNAL`
1090
+ * = interview between talent and Toptal (vetting); `EXTERNAL` =
1091
+ * interview between talent and client (post-match).
1092
+ */
1093
+ export type InterviewKind = "EXTERNAL" | "INTERNAL";
1094
+ /**
1095
+ * `TalentInterviewMethodTypeEnum` values from the synthesized schema.
1096
+ * Typed as a string for forward compatibility with un-enumerated future
1097
+ * members (the wire is untrusted; new method types may appear without
1098
+ * codegen warning).
1099
+ */
1100
+ export type InterviewMethodType = string;
1101
+ /**
1102
+ * Time-zone descriptor. `value` is the IANA-ish zone name; `location`
1103
+ * is a human-readable label. Either may be `null` when the wire omits
1104
+ * the field.
1105
+ */
1106
+ export interface InterviewTimeZone {
1107
+ value: string | null;
1108
+ location: string | null;
1109
+ }
1110
+ /**
1111
+ * One interviewer-side contact (recruiter, client representative, etc.).
1112
+ * `main: true` flags the primary contact on the interview.
1113
+ */
1114
+ export interface InterviewContact {
1115
+ id: string;
1116
+ fullName: string | null;
1117
+ email: string | null;
1118
+ phoneNumber: string | null;
1119
+ position: string | null;
1120
+ main: boolean | null;
1121
+ timeZone: InterviewTimeZone | null;
1122
+ }
1123
+ /**
1124
+ * Method by which the interview will be conducted (Zoom, phone, etc.).
1125
+ *
1126
+ * - `typeV2` — one of the `TalentInterviewMethodTypeEnum` members
1127
+ * (`ZOOM`, `PHONE`, `BLUEJEANS`, `CUSTOM_WEB_CONFERENCE`,
1128
+ * `GOOGLE_HANGOUTS`, `SKYPE`). Stringly-typed because the wire is
1129
+ * untrusted; the codegen-exclusion may add new members.
1130
+ * - `conferenceUrl` — meeting link for `ZOOM` / `BLUEJEANS` /
1131
+ * `GOOGLE_HANGOUTS` / `CUSTOM_WEB_CONFERENCE` methods.
1132
+ * - `resource` — free-text channel string (phone number for `PHONE`,
1133
+ * handle for `SKYPE`).
1134
+ */
1135
+ export interface InterviewMethod {
1136
+ typeV2: InterviewMethodType | null;
1137
+ conferenceUrl: string | null;
1138
+ resource: string | null;
1139
+ }
1140
+ /**
1141
+ * One free-form note the talent has attached to the interview. `section`
1142
+ * is one of the `InterviewGuideSectionIdentifierEnum` members
1143
+ * (`ASK_YOUR_CLIENT`, `GAPS`, `JOB_HIGHLIGHTS`, `POTENTIAL_QUESTIONS`,
1144
+ * `PRO_TIPS`, `STRENGTHS`) or `null` when the note isn't section-pinned.
1145
+ */
1146
+ export interface InterviewTalentNote {
1147
+ id: string;
1148
+ section: string | null;
1149
+ note: string | null;
1150
+ }
1151
+ /**
1152
+ * Back-pointer to the parent job + activity item. Presence indicators
1153
+ * only — the CLI surfaces them as discovery hints (`applications show
1154
+ * <activityId>` to drill into the full activity row).
1155
+ */
1156
+ export interface InterviewJobRef {
1157
+ /** `TalentJob.id`. */
1158
+ id: string;
1159
+ /** `TalentJobActivityItem.id` for the activity row containing this interview. */
1160
+ activityItemId: string | null;
1161
+ }
1162
+ /**
1163
+ * Projected interview detail returned by `interviews.show()`. The shape
1164
+ * the CLI's pretty renderer and the MCP tool's JSON payload depend on.
1165
+ */
1166
+ export interface InterviewDetail {
1167
+ id: string;
1168
+ /** `InterviewStatusEnum` member (see {@link INTERVIEW_STATUSES}) or null. */
1169
+ status: InterviewStatus | null;
1170
+ /** `InterviewKindEnum` member or null. */
1171
+ kind: InterviewKind | null;
1172
+ /** Free-text interview-type label (legacy; modern wire prefers {@link kind}). */
1173
+ interviewType: string | null;
1174
+ /** Duration / display string (e.g. `"30 minutes"`). */
1175
+ interviewTime: string | null;
1176
+ /** Recruiter brief, markdown-formatted. */
1177
+ information: string | null;
1178
+ /** Who scheduled the interview (display string). */
1179
+ initiator: string | null;
1180
+ /** Proposed slot timestamps (ISO 8601). */
1181
+ scheduledAtTimes: string[];
1182
+ /** Free-text scheduling comment from the initiator. */
1183
+ schedulingComment: string | null;
1184
+ /** Conference method (Zoom, phone, …) — `null` until the slot is locked. */
1185
+ method: InterviewMethod | null;
1186
+ /** Interviewer contacts. Server-supplied order preserved. */
1187
+ contacts: InterviewContact[];
1188
+ /** Prep-guide id (presence indicator). Full guide is the `InterviewGuide` op, out of scope here. */
1189
+ guideId: string | null;
1190
+ /** Talent's own notes attached to the interview. Server order preserved. */
1191
+ talentNotes: InterviewTalentNote[];
1192
+ /** Back-pointer to the parent job + activity item. */
1193
+ job: InterviewJobRef | null;
1194
+ /** Server-supplied last-mutation timestamp (ISO 8601). */
1195
+ updatedAt: string | null;
1196
+ }
1197
+ /**
1198
+ * Read one `TalentInterview` by id via the mobile-gateway `Interview`
1199
+ * query (#439). Sibling sub-namespace to the top-level activity-row
1200
+ * leaves (`list` / `show` / `stats`) — fetches the rich interview
1201
+ * detail once the user knows the id from `applications show
1202
+ * <activityId>` (the `Interview: <id>` line).
1203
+ *
1204
+ * @throws `ApplicationsError("NOT_FOUND")` when the id doesn't resolve
1205
+ * to an interview the signed-in user can see, OR when the wire
1206
+ * surfaces a `NOT_FOUND_MESSAGE_PATTERN`-matched GraphQL error
1207
+ * (`Record not found` / `Invalid ID` / Relay `Node id ... resolves to`).
1208
+ * @throws `ApplicationsError("NO_VIEWER")` when the session is valid
1209
+ * but no viewer is bound.
1210
+ */
1211
+ declare function interviewsShow(token: string, id: string): Promise<InterviewDetail>;
1212
+ /**
1213
+ * Projected response returned by `interviews.notes.show()`. Shape the
1214
+ * CLI's pretty renderer and the MCP tool's JSON payload depend on.
1215
+ *
1216
+ * `jobId` is the input echo (always populated). `interviewId` /
1217
+ * `interviewKind` are populated when the job has an attached interview;
1218
+ * `null` when the job's `activityItem.interview` is null on the wire
1219
+ * (e.g. the job exists but no interview was scheduled). `notes`
1220
+ * preserves server order; empty array when the interview has no
1221
+ * recorded prep notes.
1222
+ */
1223
+ export interface InterviewNotesProjection {
1224
+ jobId: string;
1225
+ interviewId: string | null;
1226
+ interviewKind: InterviewKind | null;
1227
+ notes: InterviewTalentNote[];
1228
+ }
1229
+ /**
1230
+ * Read the talent's prep notes for the interview attached to a given
1231
+ * job via the portal-side `GetInterviewNotes` query (#440). Sub-sub-
1232
+ * namespace leaf of `applications.interviews.*` — wraps the same
1233
+ * read-only path the portal matcher UI uses to load interview notes.
1234
+ *
1235
+ * @param token Captured bearer.
1236
+ * @param jobId `TalentJob.id` (NOT the interview id). Discover via
1237
+ * `applications interview show <interviewId>` (the
1238
+ * `Job → Job id` line, populated by the #439 projection)
1239
+ * or `applications show <activityId>`.
1240
+ *
1241
+ * @throws `ApplicationsError("NOT_FOUND")` when the job id doesn't
1242
+ * resolve to a job the signed-in user can see, OR when the wire
1243
+ * surfaces a `NOT_FOUND_MESSAGE_PATTERN`-matched GraphQL error
1244
+ * (`Record not found` / `Invalid ID` / Relay `Node id ... resolves to`).
1245
+ * @throws `ApplicationsError("NO_VIEWER")` when the session is valid
1246
+ * but no viewer is bound.
1247
+ */
1248
+ declare function interviewsNotesShow(token: string, jobId: string): Promise<InterviewNotesProjection>;
1249
+ /**
1250
+ * `InterviewGuideSectionIdentifierEnum` values from the synthesized
1251
+ * schema (`../research/graphql/gateway/schema.graphql`). Closed set —
1252
+ * statically extractable from the schema. The mobile portal uses these
1253
+ * as the prep-guide section spine: `STRENGTHS` (talent's job-match
1254
+ * strengths), `GAPS` (likely follow-up topics), `JOB_HIGHLIGHTS` (key
1255
+ * job characteristics), `POTENTIAL_QUESTIONS` (questions to expect),
1256
+ * `PRO_TIPS` (Toptal interview tips), `ASK_YOUR_CLIENT` (questions to
1257
+ * ask the interviewer).
1258
+ */
1259
+ export type InterviewGuideSectionIdentifier = "ASK_YOUR_CLIENT" | "GAPS" | "JOB_HIGHLIGHTS" | "POTENTIAL_QUESTIONS" | "PRO_TIPS" | "STRENGTHS";
1260
+ export declare const INTERVIEW_GUIDE_SECTION_IDENTIFIERS: readonly InterviewGuideSectionIdentifier[];
1261
+ /**
1262
+ * `InterviewGuideTipIdentifierEnum` values from the synthesized schema
1263
+ * (`../research/graphql/gateway/schema.graphql`). Closed set —
1264
+ * statically extractable from the schema. Each tip identifier is a
1265
+ * named template slot the Toptal guide-rendering pipeline fills with
1266
+ * job/talent-specific content.
1267
+ */
1268
+ export type InterviewGuideTipIdentifier = "BE_PRESENTABLE" | "CAMERA_ON" | "DONT_DISCUSS_RATE" | "GAP_ANALYSIS" | "HIRING_FACTORS" | "JOB_SUMMARY" | "PROFILE_REFERENCES" | "QUESTIONS_TO_ASK" | "QUESTIONS_TO_PREPARE_FOR" | "SMALL_TALK" | "STANDARD_QUESTIONS" | "STRENGTHS_OVERLAP";
1269
+ export declare const INTERVIEW_GUIDE_TIP_IDENTIFIERS: readonly InterviewGuideTipIdentifier[];
1270
+ /**
1271
+ * One tip within an {@link InterviewGuideSection}. `content` is the
1272
+ * job/talent-personalized body (the Toptal guide-rendering pipeline
1273
+ * splices in job-specific examples); `hardcodedContent` is the generic
1274
+ * template body that ships with every guide regardless of job context.
1275
+ * Either or both may be populated; the renderer is responsible for
1276
+ * choosing precedence.
1277
+ */
1278
+ export interface InterviewGuideTip {
1279
+ /** `InterviewGuideTipIdentifierEnum` member (see {@link INTERVIEW_GUIDE_TIP_IDENTIFIERS}) or null. */
1280
+ identifier: InterviewGuideTipIdentifier | null;
1281
+ title: string | null;
1282
+ /** Personalized tip body (markdown). May be null when no personalization applies. */
1283
+ content: string | null;
1284
+ /** Generic template body (markdown) shipped with every guide. May be null. */
1285
+ hardcodedContent: string | null;
1286
+ }
1287
+ /**
1288
+ * One section of the interview-prep guide.
1289
+ */
1290
+ export interface InterviewGuideSection {
1291
+ /** `InterviewGuideSectionIdentifierEnum` member (see {@link INTERVIEW_GUIDE_SECTION_IDENTIFIERS}) or null. */
1292
+ identifier: InterviewGuideSectionIdentifier | null;
1293
+ title: string | null;
1294
+ subtitle: string | null;
1295
+ /** Server-supplied order preserved. */
1296
+ tips: InterviewGuideTip[];
1297
+ }
1298
+ /**
1299
+ * Projected guide payload returned by `interviews.guide.show()`. Shape
1300
+ * the CLI's pretty renderer and the MCP tool's JSON payload depend on.
1301
+ *
1302
+ * `interviewId` is the input echo (always populated). `guideId` /
1303
+ * `sections` are populated when the interview has an attached guide;
1304
+ * `guideId` is `null` and `sections` is `[]` when no guide is attached
1305
+ * to the interview (some interview types may not have a prep guide).
1306
+ */
1307
+ export interface InterviewGuideProjection {
1308
+ /** Input echo. */
1309
+ interviewId: string;
1310
+ /** `TalentInterviewGuide.id` — matches `InterviewDetail.guideId` from #439. `null` when no guide is attached. */
1311
+ guideId: string | null;
1312
+ /** Guide sections in server-supplied order. Empty array when no guide is attached. */
1313
+ sections: InterviewGuideSection[];
1314
+ }
1315
+ /**
1316
+ * Read the interview-prep guide content (sections + tips) for one
1317
+ * interview via the mobile-gateway `InterviewGuide` query (#470).
1318
+ * Sub-sub-namespace leaf of `applications.interviews.*` — wraps the
1319
+ * mobile-portal interview-prep view that talents use to prepare.
1320
+ *
1321
+ * @param token Captured bearer.
1322
+ * @param interviewId `TalentInterview.id` (NOT the guide id). Discover
1323
+ * via `applications interview show <interviewId>`
1324
+ * or `applications show <activityId>`.
1325
+ *
1326
+ * @throws `ApplicationsError("NOT_FOUND")` when the id doesn't resolve
1327
+ * to an interview the signed-in user can see, OR when the wire
1328
+ * surfaces a `NOT_FOUND_MESSAGE_PATTERN`-matched GraphQL error
1329
+ * (`Record not found` / `Invalid ID` / Relay `Node id ... resolves to`).
1330
+ * @throws `ApplicationsError("NO_VIEWER")` when the session is valid
1331
+ * but no viewer is bound.
1332
+ */
1333
+ declare function interviewsGuideShow(token: string, interviewId: string): Promise<InterviewGuideProjection>;
1334
+ /**
1335
+ * `applications.interviews.*` sub-namespace. Read-only leaves for
1336
+ * interview-detail access — sibling to the top-level activity-row
1337
+ * leaves on this module. Sub-namespace grouping pattern follows
1338
+ * `payments.rate.*` (#447) and `payments.payouts.*` / `payments.methods.*`
1339
+ * (#149); the plural form here matches `payouts` / `methods` for
1340
+ * collection-style namespaces.
1341
+ *
1342
+ * Sub-sub-namespaces:
1343
+ * - `interviews.notes.*` (#440) — portal-side notes-focused projection.
1344
+ * `notes.show(jobId)` is the lightweight read of the talent's prep
1345
+ * notes for one job's interview, paired with the heavier
1346
+ * `interviews.show(interviewId)` from #439.
1347
+ * - `interviews.guide.*` (#470) — mobile-gateway guide-content
1348
+ * projection. `guide.show(interviewId)` is the read of the
1349
+ * interview-prep guide (sections + tips). Paired with #439 —
1350
+ * `interviews.show` surfaces the guide-id presence indicator;
1351
+ * `interviews.guide.show` fetches the full content.
1352
+ */
1353
+ export declare const interviews: {
1354
+ show: typeof interviewsShow;
1355
+ notes: {
1356
+ show: typeof interviewsNotesShow;
1357
+ };
1358
+ guide: {
1359
+ show: typeof interviewsGuideShow;
1360
+ };
1361
+ };
1362
+ /**
1363
+ * `AvailabilityRequestStatusEnum` values from the synthesized schema
1364
+ * (`../research/graphql/gateway/schema.graphql`). Closed set — unlike
1365
+ * the INFERRED {@link AvailabilityRequestKind} enum, the status enum is
1366
+ * statically extractable from the schema.
1367
+ *
1368
+ * NB: distinct from the GraphQL schema type *named* `AvailabilityRequestStatus`
1369
+ * (the `{ value: String! }` wrapper that `statusV2` / `jirStatus`
1370
+ * resolve to). This TS type is the closed set of `.value` spellings.
1371
+ */
1372
+ export type AvailabilityRequestStatus = "CANCELLED" | "CONFIRMED" | "EXPIRED" | "PENDING" | "REJECTED" | "WITHDRAWN";
1373
+ export declare const AVAILABILITY_REQUEST_STATUSES: readonly AvailabilityRequestStatus[];
1374
+ /**
1375
+ * Projected availability-request detail returned by
1376
+ * `availabilityRequests.show()`. The shape the CLI's pretty renderer
1377
+ * and the MCP tool's JSON payload depend on.
1378
+ */
1379
+ export interface AvailabilityRequestDetail {
1380
+ id: string;
1381
+ /**
1382
+ * `AvailabilityRequestStatusEnum` member (see
1383
+ * {@link AVAILABILITY_REQUEST_STATUSES}) or `null`. Read off the
1384
+ * wire's `jirStatus` (aliased `statusV2`) `{ value }` wrapper.
1385
+ */
1386
+ status: AvailabilityRequestStatus | null;
1387
+ /**
1388
+ * AR kind, auto-detected from `metadata.__typename` via
1389
+ * {@link kindFromMetadataTypename}. `null` when metadata is absent or
1390
+ * an unrecognised variant.
1391
+ */
1392
+ kind: AvailabilityRequestKind | null;
1393
+ /**
1394
+ * Recruiter-pinned Fixed hourly rate (the `metadata.offeredHourlyRate`
1395
+ * Money shape). `null` for FLEXIBLE / MARKETPLACE_FLEXIBLE ARs — their
1396
+ * metadata carries no offered rate.
1397
+ */
1398
+ fixedRate: FixedRate | null;
1399
+ /** Recruiter's free-text note attached to the request. */
1400
+ comment: string | null;
1401
+ /** Server-supplied creation timestamp (ISO 8601). */
1402
+ createdAt: string | null;
1403
+ /** Server-supplied last-mutation timestamp (ISO 8601). */
1404
+ updatedAt: string | null;
1405
+ /**
1406
+ * Timestamp the talent answered the request (confirmed / rejected).
1407
+ * `null` while the request is still pending.
1408
+ */
1409
+ answeredAt: string | null;
1410
+ /** The job the availability request is for. */
1411
+ job: ApplicationJobRef | null;
1412
+ }
1413
+ /**
1414
+ * Read one `AvailabilityRequest` by id via the mobile-gateway
1415
+ * `AvailabilityRequest` query (#442). Sibling sub-namespace to the
1416
+ * top-level activity-row leaves (`list` / `show` / `stats`) and to
1417
+ * `interviews.show` (#439) — fetches the rich availability-request
1418
+ * detail once the user knows the id from `applications show
1419
+ * <activityId>` (the `Availability request: <id>` line). The id is the
1420
+ * same `AvailabilityRequest.id` the #411 `confirm` / `reject` write-side
1421
+ * ops accept.
1422
+ *
1423
+ * @throws `ApplicationsError("NOT_FOUND")` when the id doesn't resolve
1424
+ * to an availability request the signed-in user can see, OR when the
1425
+ * wire surfaces a `NOT_FOUND_MESSAGE_PATTERN`-matched GraphQL error
1426
+ * (`Record not found` / `Invalid ID` / Relay `Node id ... resolves to`).
1427
+ * @throws `ApplicationsError("NO_VIEWER")` when the session is valid
1428
+ * but no viewer is bound.
1429
+ */
1430
+ declare function availabilityRequestsShow(token: string, id: string): Promise<AvailabilityRequestDetail>;
1431
+ /**
1432
+ * `applications.availabilityRequests.*` sub-namespace. Read-only leaf
1433
+ * for availability-request-detail access — sibling to `interviews.*`
1434
+ * (#439 / #440) and to the top-level activity-row leaves. The plural
1435
+ * `availabilityRequests` form matches `interviews` / `payouts` /
1436
+ * `methods` for collection-style namespaces; the #411 write-side ops
1437
+ * (`confirm` / `reject` / `rejectReasons`) stay top-level flat exports
1438
+ * (they predate the sub-namespace convention).
1439
+ */
1440
+ export declare const availabilityRequests: {
1441
+ show: typeof availabilityRequestsShow;
1442
+ };
539
1443
  //# sourceMappingURL=index.d.ts.map