Skip to content

docs(CLNT-754): send the full template when editing via CLI or SDK - #974

Merged
madisonvast merged 2 commits into
mainfrom
CLNT-754-docs-template-guides-full-body
Oct 21, 2026
Merged

madisonvast merged 2 commits into
mainfrom
CLNT-754-docs-template-guides-full-body

Conversation

@madisonvast

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #971. The hand-written CLI and SDK template guides still told readers to "include only the flags/parameters you want to change" with partial examples. That was never true for the CLI, which sends every field, and under PUT /api/v1/template/ an omitted --name or --image goes up as null and lands on the new version. A reader following the old example would blank their template's name and image.

  • cli/templates.mdx: the Edit section now says edits create a new version and omitted fields are not carried over; keeps only the full example (adds --disk_space), adds a Warning, and the Note now mentions the new id and that the previous version keeps its identifiers.
  • sdk/python/templates.mdx: same rewrite with hash_id= (the real parameter name), disk_space= and a dict result; drops the stale hand-typed signature block (HASH_ID, disk, -> str) in favour of a link to the generated reference page; fixes the two remaining HASH_ID mentions in the identifier table and troubleshooting accordion.

Test plan

Jira: https://vastai.atlassian.net/browse/CLNT-754

@mintlify

mintlify Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
vastai-80aa3a82 🟢 Ready View Preview Oct 21, 2026, 7:12 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@Azaeres

Azaeres commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

cc-review: PR #974 — Edit sections of the CLI and Python SDK template guides, follow-up to #971 (CLNT-754)

Branch Strategy

Repository Base Branch Strategy Feature Branch Destination Branch Round
vast-ai/docs main independent, single commit head d99d6ad main 1

The merge-base is 4bf00bb, which is the current main tip (and the merged #971). The three-dot diff is clean: 2 files, cli/templates.mdx and sdk/python/templates.mdx.

Summary

Docs-only follow-up to #971. It rewrites both Edit sections to say that edits create a new version and that every field must be resent, and it fixes the stale HASH_ID names and signature. The factual core holds against the backend and the shipped client: the example flags and kwargs exist, omitted --name/--image go up null, the ValueError claim is true, and result["template"]["hash_id"] is valid on every return shape. No in-scope Major was found. Five Minors remain, all documentary:

  • The Warning's "clears" is imprecise.
  • The edit examples drop --search_params and public.
  • "Always a new version" ignores the no-op early exit.
  • The "repeat every flag" remedy cannot preserve fields that have no flag or parameter.
  • The new prose points at a still-stale create_template signature.

The "not carried over" overclaim raised on #971 is re-checked below: for every field a CLI or SDK reader controls, the sentence is accurate.

Coverage limits: The ticket text was carried forward from the earlier review of the same ticket and its current status is unconfirmed. The full Edit section of api-reference/creating-and-using-templates-with-api.mdx was read at search level only. The Mintlify preview rendering of the Warning and Note blocks was not inspected.

Test execution: deferred to the repo's CI/CD pipeline (repo setting); findings are by inspection and the CI result is not part of this review

1. Sources & Blade Sharpening

Inputs from Steps 1-5.

Sources consulted:

  • Jira (CLNT-754, Task, "Security: deprecate PUT /api/v0/template/ - replace with /api/v1/template/"): description carried forward from the earlier review of this ticket, status unconfirmed; comments and attachments were not read. The docs-facing requirement is to remove references to the deprecated endpoint and point users to the replacement.
  • Prior PR comments: 1 comment, a preview bot. No earlier review round on this PR.
  • Specs (reviewed repo): the docs repo has no openspec/ directory, so no specs apply.
  • Figma: not applicable.
  • Pre-change code: both pages at the merge-base via the diff. Backend update_template_v1, format_template_for_insertion, insert_and_update_templates and validate_template_params at origin/master. Client offers.py and sdk.py at tag v1.9.0 (its tree is identical to the CLNT-754 CLI branch, which has since merged).
  • Configuration & ambient: docs.json nav slugs, cli/reference/update-template.mdx, sdk/python/reference/update-template.mdx, api-reference/openapi/yaml/edit_template.yaml:19.
  • Diff: git diff 4bf00bbc...d99d6add — 2 files, +25/-57.

Local universe enumeration:

  • Layer 0 (diff): 2 files · read 2/2 ✅
  • Layer 1 (semantic providers): 4 backend functions plus v1.9.0 offers.py/sdk.py · read all ✅
  • Layer 2 (consumers): generated reference pages and the API guide that mention update_template/HASH_ID · search-level read only (see Coverage limits)
  • Layer 3 (same-lifecycle): unchanged neighbours on the same pages (C:51,78-90,284; S:59,80-84,88-100,103-121,360) · read all ✅
  • Layer 4 (config/ambient): docs.json nav and edit_template.yaml · read all ✅
  • Layer 5 (specs): 0
  • Layer 6 (Jira): ticket + 0 adjacent
  • Layer 7 (prior reviews): 1 comment (preview bot, no findings)

Cross-source reconciliations applied during lift:

  • "Not carried over": two readings were tested. One said the backend copies recommended, autoscaler, sort_order and vm from the old row, so the sentence overclaims (the docs(CLNT-754): document template edits on PUT /api/v1/template/ #971 round-1 finding). The other said those four are reset for CLI and SDK edits. The second holds: the handler copies the four fields at origin/master:web/views/templates.py:1295-1299, and format_template_for_insertion then resets all four on this path (:1474-1478) for the payload the CLI and SDK send (v1.9.0 offers.update_template). Only tags carries over (:1323), and no CLI flag or SDK parameter can set tags. The docs(CLNT-754): document template edits on PUT /api/v1/template/ #971 overclaim is therefore narrowed to a footnote (Note 1).
  • Omitted disk_space becomes 16, not null (:1512-1513); the CLI and SDK send None when it is omitted.

🔪 BLADE SHARPENED: ✅

2. Constraints Verified

Input from Step 5 (mesh + vertex tags) + Steps 7-8 (Status).

# Constraint Source · Vertex Status
C1 "Editing creates a new version / new id and hash_id" holds as stated PR body; C:200,217; S:254,275 vs backend early exit origin/master:...:1321 · [Intent] ⚠️
C2 "Fields you leave out are not carried over" is accurate for what the reader controls C:200; S:254 vs origin/master:...:1295-1299,1323,1474-1478 · [Intent] ⚠️ (accurate for flags and params; tags is a footnote, see Note 1)
C3 Warning "Omitting a flag/parameter clears that field" C:212-214; S:270-272 vs v1.9.0:vastai/api/offers.py template_fields_from_flags, origin/master:...:1512-1513 · [Intent] ⚠️
C4 Every example flag and kwarg exists at 1.9.0 (hash_id=, disk_space=, --disk_space, ssh, direct) v1.9.0:vastai/sdk.py:1026-1043, v1.9.0:vastai/cli/commands/offers.py:544 · [Law] ✅
C5 Omitted --name/--image go up null on the v1 path (PR body claim) v1.9.0:vastai/api/offers.py update_template payload · [Intent] ✅
C6 result["template"]["hash_id"] is valid on every return shape (new version, no-op) origin/master:...:1321 and the update_template_v1 returns · [Actuality] ✅
C7 "An unknown hash_id raises ValueError" v1.9.0:vastai/api/offers.py resolve_template_id · [Actuality] ✅
C8 "Previous version keeps its identifiers, so running instances and shared links stay valid" PR sentence vs the retained previous row · [Intent] ✅
C9 Remedy "repeat every other flag with its current value" restores the prior state payload keys at v1.9.0:vastai/api/offers.py update_template vs template columns · [Intent] ⚠️
C10 Edit examples are consistent with the page's own create example and the generated reference C:78-90,202-210; S:88-100,256-268; cli/reference/update-template.mdx · [Law] ⚠️
C11 "Same parameters create_template() accepts" resolves to an accurate signature on the page S:103-121 vs v1.9.0:vastai/sdk.py:983-1000 · [Law] ⚠️
C12 The two guides carry no reference to the deprecated PUT /api/v0/template/ and point to the v1 path (CLNT-754 docs requirement) head-tree grep of both files; edit_template.yaml:19 · [Intent] ✅
C13 The HASH_ID to hash_id rename is complete (S:56,313) and the reference link /sdk/python/reference/update-template resolves sdk/python/reference/update-template.mdx exists at head; docs.json nav · [Actuality] ✅

Vertex tags: [Intent] prescriptive of what diff should produce; [Law] cross-cutting constraint; [Actuality] behavioral observation from diff.

3. Constraint Mesh Analysis

Input from Step 7 (Attack Matrix).

Constraint Attack Matrix

C1 — new version, new id and hash_id ⚠️

  • Contradiction: An identical resend hashes to the current version and the backend returns the old hash_id with the message "No Edits made" (origin/master:...:1321). api-reference/openapi/yaml/edit_template.yaml:15 documents this; these guides do not.
  • Edge case: The unchanged neighbours at C:51,284 and S:59-61,359-360 ("any edit produces a new hash") share the gap.
  • Failure mode: None harmful. "Use the new hash_id returned" still works because the returned hash_id is correct on both shapes.
  • Assumption: The text assumes the resent set always differs from the current version. A user who copies the example for an unchanged template hits the no-op.

C2 — "not carried over" ⚠️

  • Contradiction: None for flags and parameters (see the reconciliation in section 1).
  • Edge case: tags falls back to the previous version (:1323), but no CLI flag or SDK parameter exists for it. Reader impact is none.
  • Failure mode: None. The docs(CLNT-754): document template edits on PUT /api/v1/template/ #971 overclaim was about the four feature fields, and for those it does not hold on CLI and SDK edits.
  • Assumption: "Fields" is read as flags and parameters, which is the only reading the page supports.

C3 — Warning "clears" ⚠️

  • Contradiction: Several omitted flags do not produce a cleared field.
    • --public/public omitted gives private: True, so the new version silently becomes private (template_fields_from_flags, "private": not public).
    • --hide-readme omitted gives readme_visible True.
    • --ssh/--jupyter omitted gives runtype "args".
    • --disk_space omitted becomes 16, not null (origin/master:...:1512-1513).
    • The CLI re-seeds default filters (always_default=True) while the SDK sends {}.
  • Edge case: A reader who wants to keep a public template public must pass --public/public=True again. The SDK fields table (S:45-46) says "(private by default)" and never names public.
  • Failure mode: Wrong outcome, not wrong remedy. The Warning's remedy is correct. The risk is a public template going private when the reader believes only "cleared" fields change.
  • Assumption: "Clears" implies null. For five fields it does not.

C4 — example flags and kwargs exist ✅

  • Contradiction: None. v1.9.0:vastai/sdk.py:1026-1043 has hash_id, disk_space, ssh, direct, onstart_cmd, env, image, name; offers.py:544 has --disk_space.
  • Edge case: None. The CLI flag set equals the create template set.
  • Failure mode: None. disk_space=16 is accepted as Optional[float].
  • Assumption: The docs describe 1.9.0. The reference pages regenerated by docs(CLNT-754): document template edits on PUT /api/v1/template/ #971 agree.

C5 — omitted name/image go up null ✅

  • Contradiction: None. The payload sets "name": name, "image": image with default None.
  • Edge case: None. The backend hashes null name/image into a new version, as the PR says.
  • Failure mode: None found.
  • Assumption: None.

C6 — result shape ✅

  • Contradiction: None. template["hash_id"] is present on the new-version and no-op returns.
  • Edge case: None. The no-op return also carries the template dict.
  • Failure mode: None. The SDK returns r.json() (a dict), so result["template"]["hash_id"] works.
  • Assumption: None.

C7 — ValueError ✅

  • Contradiction: None. resolve_template_id raises ValueError(f"No template found with hash_id {hash_id}").
  • Edge case: Other failures from the endpoint surface as HTTP errors via raise_for_status(); the SDK Note states ValueError as the only error (Note 3).
  • Failure mode: None.
  • Assumption: None.

C8 — identifiers kept, instances and shared links valid ✅

  • Contradiction: None. The previous row is retained with id and hash_id intact.
  • Edge case: None found in what the sentence claims.
  • Failure mode: None.
  • Assumption: "Running instances" refers to contracts keyed on the old template_id/hash_id; no write touches them.

C9 — remedy restores prior state ⚠️

  • Contradiction: Fields with no flag or parameter cannot be repeated: volume_info, docker login user and password, and other template columns. They are not in the payload, so they are null on the new version.
  • Edge case: A template with a private-registry login or a volume spec, edited via the CLI or SDK, produces a new version without them. The previous version remains intact.
  • Failure mode: A reader who follows the remedy exactly cannot restore those fields, and the guide gives no way to know which they are.
  • Assumption: The remedy assumes every field of the old version is expressible as a flag or parameter.

C10 — example consistency ⚠️

  • Contradiction: The page's own create example sets --search_params/search_params= (C:78-90, S:88-100) and the generated reference example for update template includes it. The new full-edit examples omit it (C:202-210, S:256-268), and omit --public/public=True.
  • Edge case: Copying the example for the template created earlier replaces custom filters with the CLI defaults (SDK {}) and flips visibility to private.
  • Failure mode: The examples cut against the new Warning, which tells the reader to repeat every flag.
  • Assumption: The example is illustrative; the surrounding text says "pass the full set".

C11 — create_template signature ⚠️

  • Contradiction: S:103-121 still shows disk_space: Optional[str], -> str, and lacks href, repo, no_default, readme, hide_readme, desc, public. Release 1.9.0 has disk_space: Optional[float] and -> dict (v1.9.0:vastai/sdk.py:983-1000).
  • Edge case: The PR deleted the equivalent stale update_template signature and replaced it with a link, but the new sentence "same parameters create_template() accepts" points at the stale block on the same page.
  • Failure mode: A reader taking that block as authoritative would miss public/hide_readme, the very parameters the Warning makes important.
  • Assumption: Lines 103-121 are unchanged by the PR, but the new prose depends on them.

C12 — deprecated endpoint not referenced ✅

  • Contradiction: None. A grep of both head files finds no v0/template string.
  • Edge case: cli/reference/update-template.mdx mentions HASH_ID only as the positional argument name; that is generated reference content this PR does not touch.
  • Failure mode: None.
  • Assumption: The API reference pages already carry the 410 notice (edit_template.yaml:19).

C13 — rename and link ✅

  • Contradiction: None. HASH_ID is gone from the SDK page at S:56, S:313 and the example.
  • Edge case: None. The link target exists at head and the docs.json nav lists it.
  • Failure mode: None.
  • Assumption: None.

Cluster annotations

  • Warning/remedy cluster [C2, C3, C9, C10] chained, one root: what the v1 payload sends and what the backend then does with it.
  • Result-shape cluster [C1, C6, C7] chained: all return shapes of update_template_v1 were traced.
  • Adjacent-prose cluster [C11, C13] parallel: independent probes of the stale block and the link target.

Operative Test — Could a wrong guide accidentally satisfy this mesh?

  • Enforcement [✅]: Prose has no producer to delete. Each load-bearing claim (example flags, kwargs, link slug, result shape) was tied to a client or backend line, so a wrong claim would show a mismatch. No repository test pins docs text; the docs CI is not part of this review.
  • Dimensional Coverage [⚠️]: WHY (hash derivation), HOW (payload to backend reset) and WHEN (no-op, unknown-hash) are reached. WHERE is partly open: the API-reference edit guide was read at search level only and the preview rendering was not inspected.
  • Detectability [✅]: Each ⚠️ is observable by running the example against a template that has public, filters or a registry login, and comparing the new version's fields.
  • Domain-Risk (Performance/Security) [N/A]: no spec tagged for Domain-Risk exists in this repo. The security change in the ticket is the backend deprecation, which is not in this diff.

4. Implementation / Constraint Analysis

Input from Step 8 (QA) + Step 9 (Deep Spec Audit) + AC Satisfaction cross-refs.

Severity Spread: Critical: 0 | Major: 0 | Minor: 5 in-scope + 1 out-of-scope

Issues Found:

# Severity Description Location Source C_X
1 Minor The Warning says an omitted flag "clears that field", but omission has other effects: --public/public omitted flips the new version to private, --hide-readme omitted makes the readme visible, --ssh/--jupyter omitted gives runtype "args", --disk_space omitted becomes 16 not null, CLI --search_params omitted re-seeds default filters while the SDK sends {}. The visibility flip is the one a reader is most likely to hit. The remedy text itself is correct. C:212-214; S:270-272 C3
2 Minor Both full-edit examples omit --search_params/search_params= and --public/public=True, although the same page's create example sets search_params and the generated reference example includes it. Copying the example drops custom filters and makes the template private, which contradicts the new Warning. C:202-210; S:256-268 C10
3 Minor "Editing creates a new version / new id and hash_id" is stated unconditionally. Resending an identical set returns the old hash_id with "No Edits made". The API page documents this and these guides do not. Neighbouring lines (C:51,284; S:59-61,359-360) repeat "any edit produces a new hash". The returned hash_id is still correct, so the reader's action is unaffected. C:200,216-218; S:254,274-276 C1
4 Minor The remedy "repeat every other flag with its current value" cannot preserve fields that have no flag or parameter (volume_info, docker login user and password, other template columns); they go up null on every CLI or SDK edit, and the guide does not say which fields these are. C:200,212-214; S:254,270-272 C9
5 Minor The new prose "the same parameters create_template() accepts" points at the page's create_template Method Signature, which is still stale (disk_space: Optional[str], -> str, missing href, repo, no_default, readme, hide_readme, desc, public; 1.9.0 returns a dict). Lines 103-121 are unchanged by the PR, but the new text depends on them. S:254 -> S:103-121 C11

Out-of-scope follow-ups (never block this PR; carried at true severity):

# Severity Description Location Source C_X
6 Minor (out-of-scope) The SDK Template Fields Reference lists private as "(private by default)" and never names public, so a reader of the new Warning cannot learn from this page that public=True must be passed to stay public. The CLI table names --public (C:37). Unchanged line. S:45-46 C3

AC Satisfaction:

  • AC1 — documentation updates remove references to the deprecated endpoint and point users to the replacement: ✅ satisfied — verified via C12 (a grep of cli/templates.mdx and sdk/python/templates.mdx at head finds no v0/template reference; the examples now match the v1 payload at v1.9.0:vastai/api/offers.py; edit_template.yaml:19 and creating-and-using-templates-with-api.mdx:361 already carry the 410 notice). Evidence is inspection, since this is a docs-only diff with no test to cite.
  • AC2 — deprecate PUT /api/v0/template/ with HTTPGone pointing to PUT /api/v1/template/: ⚠️ not_in_scope — a backend change, not part of this documentation diff. Ticket status is unconfirmed.

Deep Spec Audit: 0 specs verified · 0 violations · sibling-Requirement sweep: 0 amended specs, 0 cross-Requirement contradictions

  • Per-spec breakdown: the reviewed repo has no openspec/ directory; none applies.
  • Violations: none.

Execution Tracing:

  • State transitions verified: Yes — traced the v1 edit path end to end (resolve id, PUT, hash compare, early exit vs new version, field copy then reset).
  • Command/API semantics validated: Yes — every CLI flag and SDK kwarg in the examples against v1.9.0; the return shapes against update_template_v1.
  • Environment assumptions documented: Partial — the pages assume release 1.9.0 and never state the version.

Contradiction Analysis: 13 constraints × 4 attack vectors = 52 cells checked; 5 in-scope findings plus 1 out-of-scope, 0 Major, 0 contradictions of the PR's central claims.

Ecosystem Impact: The generated reference pages (cli/reference/update-template.mdx, sdk/python/reference/update-template.mdx) already match 1.9.0 and now agree with the guides. api-reference/creating-and-using-templates-with-api.mdx holds the 410 notice. Issue 3 also touches the unchanged "hash_id changed" passages on both pages.

Quality Standards: Warning and Note usage matches the pages' existing patterns (C:50,113; S:58-60). No repository documentation spec applies.

5. Richness Score

Input from Step 9.5 — rendered from Phase 1 data, not recomputed.

Richness: ●●●●●●●○ (Source · Q · C · Seq · Cond · Arch · Sem · Coverage)

  • Source Span [●]: Intent (carried ticket text, PR body), Law (client release 1.9.0, backend), and Actuality (the diff) are all represented in the mesh.
  • Quantitative [●]: the disk_space value 16 against the backend default (:1512-1513), the example payload field counts, the Optional[float] vs Optional[str] types.
  • Causal [●]: the copy-then-reset path (:1295-1299 then :1474-1478) for the CLI and SDK payload.
  • Sequential [●]: resolve id, PUT, hash compare, early exit or insert.
  • Conditional [●]: no-op, new-version and unknown-hash paths.
  • Architectural [●]: Warning and Note usage matches the pages' pattern; the docs nav slug resolves.
  • Semantic [●]: the PR's own sentences ("not carried over", "clears", "stay valid", "new version") checked against the backend and client behaviour. Two are imprecise (Issues 1 and 3) and one holds only for the fields a reader controls (Note 1).
  • Coverage [○]: not fully lifted are the Edit section of api-reference/creating-and-using-templates-with-api.mdx (read at search level only) and the Mintlify preview rendering.

6. Recommendation

Input from Section 4 (Severity Spread) + Section 5 (Richness).

VERDICT: APPROVE

✅ APPROVE — Ready to merge. No in-scope Critical or Major issue exists. The central claims (new version on edit, full resend required, omitted name and image go up null, real flags and kwargs, ValueError, return shape, link target) hold against the backend and client. The five Minors and the notes in §7 are worth folding in, mainly the Warning wording (Issue 1) and the example completeness (Issue 2), because a reader following the Warning literally can end up with a private template that lost its filters.

7. Notes for Author

Input from non-blocking observations gathered throughout.

  1. "Not carried over" (raised on docs(CLNT-754): document template edits on PUT /api/v1/template/ #971 round 1): narrowed, not repeated. For recommended, autoscaler, sort_order and vm, CLI and SDK edits reset the values (see section 1). Only tags carries over, and no flag or parameter can set tags. The sentence is accurate for every field the reader controls. If you want it exact, "flags and parameters you leave out are not carried over" says it.
  2. CLI Note vs SDK Note. The SDK Note says an unknown hash_id raises ValueError; the CLI Note is silent. The CLI prints "No template found with hash_id ..." and returns 1 for the same case, so a matching sentence would be accurate.
  3. Error contract. The SDK Note's "An unknown hash_id raises ValueError" is true at 1.9.0 and is the only error stated. Other failures from the endpoint surface through raise_for_status() as HTTP errors.
  4. S:80-84 (unchanged). The create result is shown as New Template: {...} (a CLI-style string) while the SDK returns a dict. The page is inconsistent about result shape; the new edit example already prints the dict correctly. Out of scope, follow-up.
  5. PR text nit. The third test-plan checkbox is written [x ] with a stray space, so it does not render as a checked box.

Generated by Constraint Cycle 2.7.0

@madisonvast
madisonvast merged commit 6261497 into main Oct 21, 2026
1 check passed

This branch was successfully deployed

1 active deployment
staging — 45099549 Deployed Oct 21, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants