Skip to content

Implement planned topic: 0042-tenuo#248

Open
skill-temporal-developer-updater[bot] wants to merge 1 commit into
mainfrom
draft/0042-tenuo
Open

Implement planned topic: 0042-tenuo#248
skill-temporal-developer-updater[bot] wants to merge 1 commit into
mainfrom
draft/0042-tenuo

Conversation

@skill-temporal-developer-updater
Copy link
Copy Markdown
Contributor

Validation Report — tenuo

Skill root: . (branch draft/0042-tenuo of temporalio/skill-temporal-developer)
Authored artifacts under review:

  • references/python/integrations/tenuo.md (new, 261 lines, 33 citation tags pointing at 11 sections of https://tenuo.ai/temporal)
  • references/integrations.md (one row appended for Tenuo)

Source-of-truth note: the Temporal docs clone (../documentation/docs/) only carries a one-row catalog mention of Tenuo at develop/python/integrations/index.mdx and a one-line bullet at develop/python/index.mdx. Both link out to the external upstream guide at https://tenuo.ai/temporal. This is consistent with how the docs treat other partner-hosted integrations (Google ADK, Pydantic AI). The validation source for Tenuo-specific API claims is therefore the upstream guide, fetched via WebFetch, plus the docs clone for Temporal-side SDK symbols.


Go/no-go

Check Status Notes
Check 1 — citation audit PASS 33/33 citation tags resolve to real sections of the upstream guide. Section names match verbatim.
Check 2 — reverse-grep audit PASS All Tenuo-specific symbols verified in the upstream guide; all Temporal-side symbols (@activity.defn, @workflow.defn, Client.connect, WorkflowHandle, workflow.execute_activity, etc.) verified in the docs clone.
Check 3 — regression on known bugs PASS Zero hits against universal regression patterns; zero hits against Tenuo-specific anti-patterns used as recommended forms.
Check 4 — independent re-verification FAIL — 80 % (2 substantive mismatches out of 10 sampled claims). Both are word-level "subtle-wrong"; correctible in a small follow-up.
Check 5 — integration-layout audit PASS File at the correct location; catalog row terse and well-formed; no SKILL.md, references/python/python.md, or ai-patterns.md edits.
Check 6 — tone and scope audit PASS (with minor patterns) Zero Pattern 1 workaround disclosures. Two mild Pattern 8 / Pattern 3 findings (speculative anti-pattern in Common mistakes, lightly-inferred implementation-internals claim) — both minor.
Check 7 — cross-language structure SKIPPED Python-only integration; no cross-language layout required.

Overall verdict

MINOR FIXES (strict-rubric reading is borderline RE-RUN AUTHORING because Check 4 came in at 80 %, below the 95 % threshold — but both mismatches are single-word factual edits to existing sentences, not structural problems, and Checks 1/2/3/5/6 all pass. A spot-fix commit can close them; full re-authoring would be disproportionate.)


Check 1 findings — citation audit

Result: 33/33 citations resolved cleanly. No findings.

The 33 citation tags use 11 distinct section names, all of which match the upstream guide's actual section headings verbatim (verified via WebFetch against https://tenuo.ai/temporal):

Section name cited Confirmed in upstream?
How Tenuo fits
Prerequisites
Install
Configure Workers to use Tenuo
Define activities and workflows
Start an authorized workflow
Capability constraints
Child workflow delegation
Activity summaries in the Temporal Web UI
Security
How it works

All inline cross-links are full https:// URLs (https://tenuo.ai/temporal, https://tenuo.ai/docs) — no root-relative /develop/... paths.


Check 2 findings — reverse-grep audit

Result: zero unexplained grep-misses. No findings.

Token classes extracted from references/python/integrations/tenuo.md and verified:

Token class Tokens Source where confirmed
Tenuo Python symbols TenuoTemporalPlugin, TenuoPluginConfig, EnvKeyResolver, VaultKeyResolver, AWSSecretsManagerKeyResolver, AuthorizedWorkflow, SigningKey, Warrant Upstream guide
Tenuo helpers execute_workflow_authorized, start_workflow_authorized, tenuo_execute_child_workflow, tenuo_execute_activity, execute_authorized_activity Upstream guide
Tenuo constraint types Subpath, Pattern, Range, UrlSafe, Exact, Wildcard (see Check 4 for AnyOf omission) Upstream guide
Package / install tokens tenuo[temporal], tenuo, tenuo.temporal, tenuo_core Upstream guide
Environment variables TENUO_KEY_<key_id>, TENUO_KEY_agent1 Upstream guide
Temporal-side SDK symbols @activity.defn, @workflow.defn, Client.connect, Worker, WorkflowHandle, workflow.execute_activity, start_to_close_timeout, task_queue, temporal server start-dev, SimplePlugin, plugins=, workflow_run_fn, workflow_id= docs clone (develop/python/*)

Argument-name tokens used inside Tenuo helper call sites (key_resolver=, trusted_roots=, key_id=, warrant=, tools=, ttl_seconds=, summary=) all map to fields the upstream guide names explicitly.


Check 3 findings — regression on known bugs

Result: zero hits. No findings.

Universal regression patterns scanned (none present): --profile as a temporal flag, TEMPORAL_TLS_CLIENT_CERT_PATH, TEMPORAL_TLS_CLIENT_KEY_PATH, TEMPORAL_TLS_SERVER_CA_CERT_PATH, tcld service-account, --output text, --output jsonl, saas-api.tmprl.cloud:7233.

Tenuo-specific anti-patterns (the wrong forms the upstream guide itself flags as mistakes) appear only inside the ## Common mistakes section explicitly labeled as wrong — that is the intended use. They do not appear as recommended forms anywhere in the file.


Check 4 findings — independent re-verification (sampling)

Result: 8/10 sampled claims match upstream (80 %). Below the 95 % threshold by two findings. Both are word-level "subtle-wrong" — the kind Check 4 is built to catch.

Sampling method: deterministic every-3rd selection across the 33 citation tags (positions 1, 4, 7, 10, 13, 16, 19, 22, 25, 28), guaranteeing the Prerequisites / version-floor bullet is in the sample. Each sampled claim was re-derived from a fresh read of the cited upstream section before comparison.

Sample matrix

# Claim (authored file, paraphrased) Cited section Result
1 Agents are "constrained by design"; actions are cryptographically attributable How Tenuo fits ✓ Match
4 Python 3.10+, inherited from temporalio>=1.23.0 Prerequisites ✓ Match (upstream literally says this; the 1.23.0 floor reflects the SimplePlugin requirement)
7 uv pip install "tenuo[temporal]"; pulls in temporalio>=1.23.0 and tenuo_core (a compiled extension with prebuilt wheels) Install ✓ Match (upstream specifies tenuo_core is a Rust extension; omission is stylistic, not material)
10 EnvKeyResolver reads TENUO_KEY_<key_id> with key bytes base64- or hex-encoded Configure Workers to use Tenuo Mismatch — see Finding 4-A
13 Activities are standard @activity.defn functions; authorization runs in the interceptor before the function body Define activities and workflows ✓ Match
16 execute_workflow_authorized(client=, workflow_run_fn=, workflow_id=, warrant=, key_id=, args=, task_queue=) Start an authorized workflow ✓ Match (argument set matches upstream verbatim)
19 "Constraint types named on the upstream guide: Subpath, Pattern, Range, UrlSafe, Exact, Wildcard" Capability constraints Mismatch — see Finding 4-B
22 tenuo_execute_activity runs an Activity with summary= attached to the Event History so it appears in the Temporal Web UI Activity summaries in the Temporal Web UI ✓ Match (Temporal SDK's summary= parameter does this; upstream confirms summary= is the surface)
25 "Proof-of-possession is computed at schedule time (binding the exact tool and args) and verified on the activity worker before execution." How it works ✓ Match — verbatim with upstream
28 "Common mistake: from temporalio.contrib.tenuo import … — that module does not exist" Configure Workers to use Tenuo ✓ Match — upstream explicitly says Tenuo ships in the tenuo package, not in temporalio.contrib

Finding 4-A — EnvKeyResolver encoding claim is broader than upstream supports

  • File: references/python/integrations/tenuo.md:70
  • Authored text: `EnvKeyResolver` reads holder signing keys from environment variables named `TENUO_KEY_<key_id>`, with the key bytes base64- or hex-encoded.
  • Upstream text (tenuo.ai/temporal § Configure Workers to use Tenuo): `EnvKeyResolver` maps `key_id` to environment variables using the convention **`TENUO_KEY_<key_id>`** with **base64-encoded** signing key bytes.
  • Difference: the upstream says **base64-encoded** only. The or hex-encoded alternative is not supported by the upstream text.
  • Impact: an agent following the authored guidance might hex-encode a key (e.g., python -c "...print(k.secret_key_bytes().hex())"); the resolver would fail to decode it at worker startup. Real divergence in generated code.
  • Fix: drop or hex-encoded (and update the example on line 73 if it teaches anything but base64).

Finding 4-B — Capability constraint list omits AnyOf

  • File: references/python/integrations/tenuo.md:185
  • Authored text: Constraint types named on the upstream guide: `Subpath`, `Pattern`, `Range`, `UrlSafe`, `Exact`, `Wildcard`.
  • Upstream text (tenuo.ai/temporal § Capability constraints, full-list sentence): …the full list of constraint types (`Subpath`, `UrlSafe`, `Exact`, `Pattern`, `Range`, `AnyOf`, etc.).
  • Difference: the authored list swaps AnyOf (in upstream's enumerated list) for Wildcard (used in upstream as the "unconstrained but declared" type but not part of the enumerated full list). AnyOf is missing.
  • Impact: an agent following the authored guidance will not know AnyOf exists as a constraint type and would either fail to express "this argument may be any of {x, y, z}" or invent a wrong constraint expression.
  • Fix: add AnyOf to the list. Keeping Wildcard is fine — it is a real type and used in the file's example — but the sentence should say it is a constraint type, not that it is named "on the upstream guide" in the same list.

Check 5 findings — integration-layout audit

Result: all six sub-checks pass. No findings.

Sub-check Result
5.1 File at references/python/integrations/tenuo.md
5.2 Exactly one new row in references/integrations.md for Tenuo, with name + extra, language, short clause, reference path, related-topic pointer
5.3 Catalog description is a single TL;DR clause (one sentence with a colon; semicolon list of helpers). Comparable in length to the Spring AI / Spring Boot rows
5.4 No SKILL.md edit ✓ — git diff main..HEAD -- SKILL.md is empty
5.5 No per-integration bullet added to references/python/python.md ✓ — git diff main..HEAD -- references/python/python.md is empty
5.6 No oversized inline cross-link to ai-patterns.md (or anywhere) ✓ — git diff main..HEAD -- references/python/ai-patterns.md references/core/ai-patterns.md is empty

Check 6 findings — tone and scope audit

Result: zero Pattern 1 (workaround-disclosure) findings. Two minor lower-severity flags.

Pass on the mandatory pattern

No bullet in the file shows the agent how to circumvent a stated constraint. Every "Don't do X" bullet in the Common mistakes section names the supported alternative (AuthorizedWorkflow instead of plain @workflow.defn for authorized Activities, execute_workflow_authorized instead of client.execute_workflow, etc.). Negatives stop at the boundary; none open a cookie jar.

Minor flags (MINOR FIXES; can be bundled with the Check 4 fix)

Finding 6-A — Mild Pattern 8 (speculative common mistake): TENUO_SIGNING_KEY_<id> env-var bullet

  • File: references/python/integrations/tenuo.md:251
  • Text: - **`TENUO_SIGNING_KEY_<id>` env-var name.** The convention is `TENUO_KEY_<key_id>` — the key id is appended directly to `TENUO_KEY_`.
  • Why flag: the upstream guide doesn't document TENUO_SIGNING_KEY_<id> as a common typo — the bullet hypothesizes the mistake (plausibly, because the package exposes a SigningKey class). The corrective half is fully grounded; only the wrong form is invented. Borderline acceptable; recommend either dropping the bullet or grounding it.

Finding 6-B — Mild Pattern 3 (light implementation-internals inference): "Do not re-pass the parent warrant"

  • File: references/python/integrations/tenuo.md:214 and the matching common-mistakes bullet at line 252.
  • Text: Do **not** re-pass the parent's `warrant=` to the child — delegation happens through the `tools=` and `ttl_seconds=` arguments, which produce a fresh, narrowed warrant for the child.
  • Why flag: the upstream guide says workflow.execute_child_workflow() does not propagate warrant headers, and that tenuo_execute_child_workflow() should be used for authorized children — it does not literally instruct "don't pass warrant=". The helper's signature uses tools=/ttl_seconds= (no warrant= parameter), so the inference is correct; but the bullet is making the inference for the reader rather than restating the upstream rule. Keep, but consider rephrasing to "Pass tools=/ttl_seconds=; the helper has no warrant= parameter — it attenuates the parent's warrant for you" to stay closer to documented behavior.

Other patterns — no findings

  • Pattern 1 (workaround disclosure): clean.
  • Pattern 2 (in-the-weeds rationale): none.
  • Pattern 4 (multi-sentence bullets where sentence Use claude to merge Steve's, Max's, and Mason's skills.  #2 is noise): the multi-sentence Common-mistakes bullets earn the second sentence by naming the supported alternative.
  • Pattern 5 (Public Preview without admonition): the upstream guide does not mark Tenuo as Public Preview; no admonition needed. (Compare Google ADK which is marked Public Preview and carries the standard [!NOTE].)
  • Patterns 6–7 (duplicated / release-stage chatter): clean.
  • Pattern 9 (hard constraints repeated outside canonical section): the AuthorizedWorkflow constraint appears in ## Define authorized Activities and Workflows and again in ## Common mistakes, but the second appearance is the standard negation-form anti-pattern — that is the canonical place to repeat it.
  • Pattern 10 (Resources pointing at raw source trees): clean — only the upstream guide, the Tenuo product docs, and two local cross-links.
  • Pattern 11 (external links duplicating local coverage): clean.
  • Pattern 12 (DIY rebuilds of supported integrations): N/A — Tenuo is the integration.
  • Pattern 13 (repo slang / internal jargon): clean.
  • Pattern 14 (inline imports inside function bodies): clean — every from … import … in the file sits at module scope in its example.
  • Pattern 15 (ambiguous "context" references): clean.

Check 7 findings — cross-language structure

Skipped. Python-only integration; no references/core/tenuo.md expected.


Statistics

  • Citation tags scanned: 33 (11 distinct upstream sections).
  • Citation tags resolved: 33 / 33 = 100 % (Check 1 threshold: ≥ 98 %).
  • Reverse-grep token misses: 0 unexplained (Check 2 threshold: 0).
  • Universal regression-pattern hits: 0 (Check 3 threshold: 0).
  • Topic-specific regression hits in recommended-form usage: 0 (Check 3 threshold: 0).
  • Check 4 sample size: 10. Matches: 8. Match rate: 80 % (threshold: ≥ 95 %).
  • Check 5 sub-checks: 6 / 6 pass.
  • Check 6 Pattern 1 findings: 0 (threshold: 0). Other-pattern findings: 2 (mild Pattern 8 + Pattern 3).
  • Files edited outside the expected layout: 0.

Recommended next step

One small follow-up commit can close every finding:

  1. Edit references/python/integrations/tenuo.md:70 — drop or hex-encoded; ensure the example on line 73 uses base64.b64encode(...) (it already does).
  2. Edit references/python/integrations/tenuo.md:185 — add AnyOf to the constraint-type list; soften the lead-in to acknowledge Wildcard is the "unconstrained but declared" type rather than part of upstream's enumerated full list.
  3. (Optional) Tighten the two Check 6 bullets per Findings 6-A and 6-B.

No structural re-authoring is needed. The skill is grounded against a real upstream source; the diff respects the catalog convention; the regression patterns are clean; and the Common-mistakes section is honest about boundaries without disclosing workarounds.

@skill-temporal-developer-updater skill-temporal-developer-updater Bot requested a review from a team as a code owner June 5, 2026 21:06
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.

0 participants