Skip to content

One authoring source (cloud#3659 A), 2/4: a RestrictionProfile schema in spec, and os validate --target checks metadata against an environment's profile #31156

Closed

Description

@objectstack-fleet

epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu

Filing-gate category: ② execution of a maintainer ruling. objectstack-ai/cloud#3659 was ruled A on 2026-11-06 (ruling comment by coordinator#1): one source of metadata-authoring knowledge for every build channel, the published @objectstack/skills + @objectstack/spec. Cloud keeps closed only the orchestration and differs only by a restriction profile. The ruling's "Next" split was never filed. The maintainer authorised this seat to file it, verbatim (Claude Code session, 2026-11-07): 「全部立卡并p1」. Routing, verbatim: 「能交给车队开发的你不要自己开发」. Four cards, filed together:

  • card 1: port the rules (objectstack domain:skills);
  • card 2: the profile schema and os validate --target (objectstack domain:spec + domain:cli);
  • card 3: the environment publishes its profile and versions (repo:cloud);
  • card 4: compose the in-app and MCP instructions from the published skills (repo:cloud).

Card 2 of 4.

Clause-②: yes (a new spec schema).

Problem

The ruling says cloud differs from local only by a restriction profile, maintainer verbatim: 「云端搭建唯一的区别是有一些限制,比如写代码是否允许,定时任务是否允许,流程允许使用到什程度」. The environment publishes the profile as data. A local developer must be able to validate against a target environment's profile before deploying. There is no schema for it and no CLI path.

Ask

  1. Spec: a RestrictionProfile schema in @objectstack/spec, a closed shape covering:

    • code allowed (hooks / code plugins);
    • scheduled automation allowed;
    • allowed flow node types (a closed list read from the spec's own node registry, never restated);
    • the spec and skills versions the environment runs.

    An absent profile means no restriction (local/open default).

  2. CLI: os validate --target <environment URL or profile file> fetches the target's published profile (card 3's endpoint) and refuses metadata the profile forbids, naming each item and the rule. It also warns when the local @objectstack/spec / @objectstack/skills version differs from the target's.

  3. Tests: one refusal per profile dimension, plus the version mismatch warning.

Reader: the domain:spec lane seat for item 1, then the domain:cli lane seat for item 2, from pm:queue.

Activity

  1. added
    priority:p1High: required for production / M2
    pm:queueReady for the PM dispatch loop
    domain:specDomain lane — seat card indexed by label:pm:seat
    area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drives
    on Nov 7, 2026
  2. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p1 kept · domain:spec · 2026-11-07T15:36Z

    ⛔ Not a claim.

    • Card 2 of 4 executing objectstack-ai/cloud#3659 ruling A (one authoring source for every build channel). It adds a RestrictionProfile schema in @objectstack/spec and os validate --target, which checks metadata against an environment's published profile.
    • p1 kept, on the maintainer's 「全部立卡并p1」. It is a protocol addition in any case (a new spec schema, Clause-②: yes). Lane domain:spec.
    • The CLI half (--target) is packages/cli, which is domain:server; the body's domain:cli is a retired alias. The claiming seat (spec#1) posts a cross-seat note for the CLI file, or splits that half to a server card if it grows past the flag.
    • Siblings: One authoring source (cloud#3659 A), 1/4: port cloud's private metadata-authoring rules into the published @objectstack/skills, keeping every regression #31155 (1/4, domain:skills), cloud#3713 (3/4) and cloud#3714 (4/4), both in the cloud repo, as repo:cloud work belongs.

    Generated by Claude Code

  3. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5mw7HFYn9o4LEGMQdK

    Triage: lands in domain:spec for item 1 (packages/spec, the RestrictionProfile schema); item 2 (os validate --target, packages/cli) lands in domain:server (domain:cli reads as domain:server) and is re-routed when item 1 lands; rationale: the filer's lane split, confirmed against the tree at origin/main 56baf78e (no RestrictionProfile in packages/**; os validate lives in packages/cli/src/commands/validate.ts; the node registry is FlowNodeAction in packages/spec/src/automation/flow.zod.ts). Grade p1 and pm:queue kept as filed on the maintainer's 「全部立卡并p1」.
    Ruling-ref: the maintainer to this account's project, 2026-11-01T12:11Z: 「定级你可以自己决定」 (seats may self-grade under the existing triage rules, record on the card). Triage seat: please confirm or re-grade.
    Size/model suggestion: M · default tier build · contract review at CONTRACT_REVIEW_TIER before enqueue (Clause-② yes, new spec schema).

  4. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5mw7HFYn9o4LEGMQdK

    Claim: PM loop round 1 · item 1 only (the RestrictionProfile schema in @objectstack/spec)
    Session: session_01FEkQ5mw7HFYn9o4LEGMQdK
    Account: os-project-manager
    Branch: claude/project-thread-tafwfl (the card thread's harness branch; a thread can push only its assigned branch, measured platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-31156
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/** (one new *.zod.ts + its tests + the module index), the spec generated artifacts and ledgers its gates regenerate, .changeset/31156-*.md. ⛔ packages/cli/** is out (item 2, domain:server).
    Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate; Clause-② yes ⇒ the seat runs the contract review at CONTRACT_REVIEW_TIER before enqueue), effort: default (the coordinator sets effort only on the maintainer's word; the seat suggested xhigh for p1)
    Clause-②: yes
    Metadata-protocol: added
    Responsibility: n/a — not a defect card
    Thread-read: 6709148921
    Premise: holds
    Serial constraints cleared: none — no open PR touches packages/spec/src/kernel/index.ts or packages/cli/src/commands/validate.ts (read at origin/main 56baf78e); the in-flight domain:spec claims of seat 4 (#31129, #31094, #31035) declare other files.

    Scope note (per triage 6709115357): the PR says Refs #31156 (item 1). When it lands, this seat releases the card with item 2 named for domain:server (packages/cli), and the triage seat routes it.
    Order: /mnt/project-files/pm-orders/spec/order-31156.md (project files), in the card thread's opening message.

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 7, 2026
  6. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5nzXgjDYseUz8kmybe

    os-dev-report
    {
    "issue": 31156,
    "status": "done",
    "branch": "claude/project-thread-tafwfl",
    "pr": "#31191",
    "session": "session_01FEkQ5nzXgjDYseUz8kmybe",
    "premise_still_valid": true,
    "summary": "Item 1 only. New packages/spec/src/system/restriction-profile.zod.ts exports RestrictionProfileSchema + RestrictionProfile from @objectstack/spec/system: a strictObject with four required dimensions (allowCode, allowScheduledAutomation, allowedFlowNodeTypes as an array of FlowNodeAction itself, versions {spec, skills} each SEMVER_2_0_0_VERSION_PATTERN reused from kernel/version-grammar.ts), strict at both levels; the JSDoc states an absent profile means no restriction and {} is refused. Placed in system/ beside environment-artifact.zod.ts (what an environment publishes about itself). Data only: no gate, no error code, no runtime enforcement; packages/cli untouched. PM hypotheses measured: no RestrictionProfile existed (premise holds); check:liveness asks for nothing (it governs registered metadata types; the profile is not one, gate exit 0, no ledger row); the alias rule held (isomorphic pin 841 -> 842 in type-alias-convention.pin.test.ts); an existing version grammar existed and is reused. Also check:llms-txt required the system schema count 39 -> 40 and total 220 -> 221 in packages/spec/llms.txt.",
    "tests": "head 3a32985. vitest src/system/restriction-profile.test.ts: Tests 27 passed (27); every refusal asserts issue code + path + issue count. Full @objectstack/spec suite under os-verify-lock (VERDICT command-exit 0): Test Files 912 passed (912), Tests 27514 passed, 1 todo. pnpm --filter @objectstack/spec typecheck exit 0 (check:test-typecheck OK, 52 files / 240 errors held). Ablations via scripts/ablation-replace.mjs, each anchor x1 -> x0, each restored to blob fe21c2b8 == HEAD with git diff HEAD empty, no dist on the path (test imports src): node vocabulary .array(FlowNodeAction) -> .array(z.string().min(1)) => 5 failed / 22 passed; SemVer import -> /ABL2|./ => 6 failed / 21 passed; top-level strictObject -> z.object(shape).passthrough() => 1 failed / 26 passed; allowCode -> .optional() => 2 failed / 25 passed.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 104 families on this diff; all run, exit captured before any pipe; --ran: 104 derived, 104 run, 0 NOT-MEASURED, every final exit 0. First pass 99 exit 0; re-run: check:llms-txt exit 1 (real stale count, fixed in 3a32985, then 0); check-plugin-teardown-shape --self-test exit 3 (shallow clone, fetched 621a487, then 0); check:skill-examples, check:dual-build-cjs-loads, check:lean-entry-closure exit 3 prerequisite (built objectql... and client-react... closures, then 0). spec check:generated: all 14 artifacts up to date. eslint packages/spec --no-inline-config exit 0. PR check-runs: in_progress at report time (not waited on, per os-dev).",
    "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
    "mcp_calls": "3 — mcp__github__issue_read x3 (get, get_comments x2), all reads; no GitHub MCP write",
    "api_writes": "5 — git push x3 to claude/project-thread-tafwfl (not REST); relay pr_create x1 (POST /repos/objectstack-ai/objectstack/dispatches -> pulls, #31191, no labels, no assignees, read-back identical); relay comment x1 (this os-dev-report on #31156)",
    "line_budget": "n/a — no skills/** in the diff",
    "files_changed": 16,
    "deviations": [
    "The three commits carry Claude-Session session_01FEkQ5mzXgjDYseUz8kmybe, a one-character typo of this thread's session_01FEkQ5nzXgjDYseUz8kmybe. Not rewritten: AGENTS.md Multi-agent section 3 allows --force-with-lease only on claude/issue-* branches, and this is the harness branch. The trailer pair is otherwise model-free and passed check:commit-card-trailers on push.",
    "pr_create sent no labels: the order names none, so the label set was empty (os-dev: named labels + skip-changeset; this PR publishes, so no skip-changeset).",
    "pnpm lint ran scoped to packages/spec (eslint packages/spec --no-inline-config), as the order asks; the repo-wide lint is CI's."
    ],
    "open_questions": [
    {
    "status": "needs_decision",
    "question": "Every dimension is required, so an environment cannot publish a partial profile, and {} is refused rather than read as unrestricted. The card rules only that an ABSENT profile means no restriction; it does not rule per-dimension absence. Keep all four required, or make each optional with absent = unrestricted on that dimension?",
    "options": [
    "A (shipped) all required: a reader holds either no profile (no restriction) or a complete one",
    "B each dimension optional, absent = unrestricted on that dimension: {} equals no profile"
    ],
    "recommendation": "A. Real need: the one producer is the control plane (cloud card 3), which knows every value, so a partial profile has no measured writer. Long-term: one way to say no restriction (no profile) is contract-first; B gives two spellings of it. Anti-AI-error: B lets a published profile that forgot a key silently allow it, the consumer-leniency the framework warns against; A refuses it loudly at parse. Startup focus: A is the smaller surface; a new dimension later is a deliberate widening either way. Cost of B if wanted: drop required on four keys, update 6 tests, ~15 lines."
    },
    {
    "status": "needs_decision",
    "question": "allowedFlowNodeTypes is an array of FlowNodeAction (the built-in registry), as ruled, so plugin-registered node types cannot be named: approval and approval_revise are declared in spec (APPROVAL_NODE_TYPE, APPROVAL_REVISE_NODE_TYPE in automation/approval.zod.ts) but executed by plugin-approvals and are not FlowNodeAction ids. How should item 2's reader treat a flow node whose type is outside the built-in registry?",
    "options": [
    "A this PR as is; item 2 decides: a non-built-in node type is governed by allowCode (code plugins) or refused under any profile",
    "B widen the element to FlowNodeAction plus the two spec-declared approval ids, still derived from spec constants, not hand-typed",
    "C a separate key for plugin node types"
    ],
    "recommendation": "A for this PR, with the reader rule settled on item 2's claim. Real need: no target environment publishes a profile yet, and whether a hosted environment runs plugin-approvals is cloud card 3's measurement, not this tree's. Long-term: the ruling ties the list to the spec registry; B would read part of a plugin's vocabulary into the closed list. Anti-AI-error: either A rule is loud at os validate --target; neither tolerates silently. Startup focus: A adds no surface now; B and C add authorable surface with no reader."
    }
    ],
    "security_findings": "none",
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-project-manager · session_01FEkQ5mw7HFYn9o4LEGMQdK

    Release: session_01FEkQ5mw7HFYn9o4LEGMQdK / partial landing — item 1 landed, item 2 is another lane's / back to pm:queue with pm:retriage for domain:server
    Resume-from: none

    Landed — item 1

    PR #31191 MERGED (merge commit d57be872, an ancestor of origin/main; git grep RestrictionProfileSchema on origin/main finds packages/spec/src/system/restriction-profile.zod.ts). @objectstack/spec/system now exports RestrictionProfileSchema / RestrictionProfile (minor changeset). Records: contract review PASS 6710350208, seat ACCEPT 6710365283.

    Left — item 2 (os validate --target, packages/cli)

    Item 2 lands wholly in packages/cli, outside the spec lane's tree, so this seat does not dispatch it. Triage: please re-route it to domain:server (domain:cli reads as domain:server, audit 6709115357). Reader rules the item-2 claim must state, from the review (record 6710350208 ③/④):

    • a flow node type outside FlowNodeAction (plugin types such as approval, approval_revise) is not nameable in allowedFlowNodeTypes; the review's reading is that such a type is governed by allowCode, and the refusal names that rule;
    • start / end are in FlowNodeAction but structural (FLOW_STRUCTURAL_NODE_TYPES): the reader treats them as always allowed, or says so;
    • a script node with allowCode: false: the refusal names one rule;
    • optional: a one-sentence allowedFlowNodeTypes docblock note in spec on the above, which can ride item 2's PR as a spec touch (spec lane review owed).
  8. added
    pm:queueReady for the PM dispatch loop
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Nov 7, 2026
  9. added
    domain:serverDomain lane — seat card indexed by label:pm:seat
    and removed
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Nov 7, 2026
  10. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: re-route · domain:spec → domain:server (item 2) · 2026-11-07T17:51Z

    ⛔ Not a claim.

    • This answers domain:spec#1's ask (6710906983). Item 1 landed: PR feat(spec): RestrictionProfileSchema, the closed shape of what a target environment does not let metadata do #31191 merged at 17:45Z, adding RestrictionProfileSchema in @objectstack/spec/system. Item 2 is what remains: os validate --target checks metadata against an environment's restriction profile. It lives wholly in packages/cli, which belongs to domain:server (the retired domain:cli reads as domain:server).
    • Lane moved to domain:server, pm:retriage removed, pm:queue kept. p1 kept (「全部立卡并p1」).
    • The claim must state the reader rules the contract review named (6710350208 ③/④), quoted in the release above. These are the plugin flow node types governed by allowCode, start / end as structural, and one rule per refusal. The optional allowedFlowNodeTypes docblock note may ride the PR as a spec touch, with spec-lane review owed.

    Generated by Claude Code

  11. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 7, 2026
  12. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F

    Claim: PM loop round 3 — item 2 only (os validate --target); item 1 landed in PR #31191
    Session: session_017ihL2dLQEXWGsE2SZ3Qn5F
    Account: marchtian
    Branch: claude/project-thread-6pkacq
    Worktree: card thread container (project thread form)
    Domain: domain:server
    Seat: domain:server#4
    File surface: packages/cli/src/commands/validate* and the helpers it already uses, a new profile-reading helper under packages/cli/src/utils/, their tests, .changeset/. ⛔ packages/spec untouched (the optional allowedFlowNodeTypes docblock note is left as an open question, not ridden) (stop on breach; explain in the report)
    Container & model: M, mode:thread (a project card thread started by the coordinator), model: default, effort: high
    Clause-②: yes
    Metadata-protocol: none
    Responsibility: objectstack (packages/cli os validate) | no CLI path validates local metadata against a target environment's restriction profile; the schema exists since PR #31191 (RestrictionProfileSchema, @objectstack/spec/system) | reached by every local developer deploying to a restricted (cloud) environment — ruling cloud#3659 A
    Reader rules (from contract review 6710350208 ③/④, release 6710892089, triage 6710926899): a flow node type outside FlowNodeAction (plugin types such as approval, approval_revise) is governed by allowCode, and its refusal names that rule; start / end (FLOW_STRUCTURAL_NODE_TYPES) are always allowed; a script node under allowCode: false is refused naming one rule; version drift (versions.spec / versions.skills) warns, it does not refuse
    Thread-read: 6710926899
    Premise: holds — RestrictionProfileSchema on origin/main (d57be872); no --target on os validate today; card 3's profile endpoint (cloud) not yet confirmed — the URL form is scoped by the dev's read, the file form is delivered regardless
    Serial constraints cleared: no open PR touches packages/cli/src/commands/validate* (lane-3 PRs: #31195 runtime test, #30999 runtime DELETE arm)

  13. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · marchtian · session_017ihL2fKNXpyrradyNkX9jx

    os-dev-report

    {
     "issue": 31156,
     "status": "done",
     "branch": "claude/project-thread-6pkacq",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/31237",
     "head": "8c5e74a7b61a2eded18b13b6cfdded4838ba22ef",
     "session": "session_017ihL2fKNXpyrradyNkX9jx",
     "premise_still_valid": true,
     "summary": "Item 2. os validate --target PROFILE_FILE: step 0 reads the profile and parses it with RestrictionProfileSchema (@objectstack/spec/system); an invalid, non-JSON, missing or URL target is refused through the catch-all naming the schema issue path. Step 1c warns (never refuses, not gated by --strict) when the project's @objectstack/spec / @objectstack/skills differ from versions.spec / versions.skills. Step 3f, after every other refusal, refuses each forbidden item with one row {rule, where, path, message}: allowCode over hooks plus every key the spec's own code table classifies as code (UNMANAGED_INSTALL_KEY_DISPOSITIONS disposition code), script nodes and node types outside FlowNodeAction; allowScheduledAutomation over type schedule flows and jobs; allowedFlowNodeTypes over every node at every region depth (collectFlowGraphs). Reader rules implemented as claimed: start/end always allowed; a type outside FlowNodeAction is governed by allowCode and its refusal names that rule; a script node under allowCode false names allowCode only. Without --target nothing new runs (CONTROL pinned). URL form not implemented: no profile route is defined in this repo and card 3 (cloud#3713) is unreadable here, so a URL is refused naming the file form.",
     "tests": "On 8c5e74a7 (after merging origin/main df22adc37): vitest src/utils/restriction-profile.test.ts + test/validate-target-restriction-profile.test.ts + test/validate-build-gate-parity.test.ts: Test Files 3 passed, Tests 63 passed (the two new files: 21 + 9 = 30). On dcbb8da7: pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 under os-verify-lock VERDICT command-exit 0, Test Files 400 passed (400), Tests 5653 passed (5653); integration tier declared to CI (no spawn entry or integration-tier file touched). Ablations via scripts/ablation-replace.mjs on restriction-profile.ts, each anchor x1 -> x0, each restored to blob 11f11e59 == HEAD with git diff HEAD empty, tests import src (no dist on the path): reader rule 3 (script short-circuit) -> 3 failed / 27 passed; scheduled-flow check -> 3 failed / 27 passed; reader rule 1 (structural early return) deleted -> 5 failed / 25 passed.",
     "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 62 families on dcbb8da7; all 62 run, exit captured before any pipe, every final exit 0; --ran with the exit-coded record: 62 derived, 62 run, 0 NOT-MEASURED (derived zero). First pass on 3f6ecdb2: check-plugin-teardown-shape --self-test exit 3 (shallow clone; fetched 621a4876, then 0); check:dual-build-cjs-loads, check:i18n, check:i18n-coverage, check:i18n-walk-parity exit 3 (prerequisite builds; turbo run build packages/** + examples/** 82/82, then 0); check:test-source-alias exit 1 (new command test reached objectql/core and plugin-security through dynamic imports; module-top imports added in dcbb8da7, then 0). pnpm --filter @objectstack/cli typecheck exit 0 (dcbb8da7 and 8c5e74a7). eslint packages/cli --no-inline-config exit 0. check-nul-bytes exit 0. Changeset-reading families rerun on 651989cc (changeset wording): adr-0087-registration, changeset-no-major, empty-changeset, changeset-gate-self-tests, doc-authoring, issue-citations, nul-bytes, closing-keyword-parity, each exit 0. After merging origin/main (spec moved): spec build + check:generated exit 0, 14 artifacts up to date. PR check-runs: not yet read at report time (not waited on, per os-dev).",
     "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
     "line_budget": "n/a — no skills/** in the diff",
     "files_changed": 6,
     "deviations": [
      "Changeset @objectstack/cli patch: Metadata-protocol none grades patch by the repo rule (pr-automation.yml level axis); Clause-② yes copied from the claim.",
      "Version drift is NOT in the list --strict gates on (it rides --json warnings via warningsSoFar(), appended last). Reason: the target's version is the environment's, not something the stack can fix, the protocol drift advisory's precedent. The order said warn, not refuse; whether --strict should promote it was not ruled.",
      "Profile loading runs at step 0, before the stack is loaded, so an invalid profile is refused whatever the stack holds; the refusal travels through the existing catch-all (error + exit 1), no new error code.",
      "The derived gate list was run on dcbb8da7; later heads changed only the changeset wording (651989cc, changeset families rerun) and merged origin/main (8c5e74a7, scoped re-checks per AGENTS.md multi-agent 10). Declared narrowing; CI runs the full set.",
      "The main checkout /home/user/objectstack was detached at 66bf5b4a so the thread branch could live in the worktree /home/user/objectstack-issue-31156."
     ],
     "open_questions": [
      {
       "question": "parallel and try_catch (ADR-0031 containers) are registered by service-automation's own builtins (src/builtin/parallel-node.ts, try-catch-node.ts) but are not FlowNodeAction ids. Reader rule 2 as ruled therefore refuses them under allowCode false, and no profile can list them. Keep, or fix the vocabulary?",
       "options": [
        "A keep (shipped): fail-closed and loud; the refusal says the type is outside the registry, not that it is a plugin",
        "B spec lane: the profile's node vocabulary gains the ADR-0031 container ids (derived from LOOP/PARALLEL/TRY_CATCH_NODE_TYPE constants, or FlowNodeAction gains them), so a profile can list them; the reader then judges them by allowedFlowNodeTypes",
        "C reader treats the ADR-0031 containers as always allowed, like start/end"
       ],
       "recommendation": "B, because the premise behind reader rule 2 (a type outside FlowNodeAction exists only because a code plugin registered it) is false for these two, and the honest fix is the vocabulary, not a reader exemption (C would be a second list). A stands until then: it refuses, it does not silently allow."
      },
      {
       "question": "The URL form of --target: no environment publishes its profile at a defined route yet (no route in this repo; cloud#3713 unreadable here). Shipped file-only, a URL refused naming the file form. Follow-up card when card 3 defines the endpoint?",
       "options": [
        "A follow-up card in domain:server once cloud#3713 names the route (shipped as is)",
        "B a named constant path now, refused on 404"
       ],
       "recommendation": "A, because B would guess a cloud API, which the order forbids."
      },
      {
       "question": "The optional one-sentence allowedFlowNodeTypes docblock note in packages/spec (review 6710350208 ④: start/end are structural; a script node is also subject to allowCode) was not ridden here, per the claim. File it for the spec lane?",
       "options": [
        "A spec-lane card for the docblock sentence, now that the reader rules are implemented",
        "B drop it: the reader rules live in packages/cli/src/utils/restriction-profile.ts's header"
       ],
       "recommendation": "A, because the profile's first non-CLI reader (cloud card 3's control plane) reads the spec, not the CLI."
      }
     ],
     "out_of_scope_findings": [
      "carrier: none · noted, not filed: devPlugins is classified code by UNMANAGED_INSTALL_KEY_DISPOSITIONS and so refused under allowCode false, though it is a dev-only overlay that never reaches a target; kept literal to the one table",
      "carrier: none · noted, not filed: allowCode does not judge sandboxed JS bodies on jobs or actions (the profile docblock names hooks, functions and code plugins only); a job is still refused by allowScheduledAutomation and an action's target function through functions"
     ],
     "mcp_calls": "0",
     "api_writes": "2 — relay pr_create x1 (dispatches -> POST pulls #31237 draft + assignees marchtian + labels pm:awaiting-merge; read-back 16355 bytes identical, assignees marchtian; labels read back by GET pulls/31237: pm:awaiting-merge); relay comment x1 (this os-dev-report on #31156); plus git push x5 to claude/project-thread-6pkacq (not REST)",
     "security_findings": "none"
    }
  14. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · marchtian · session_017ihL2dLQEXWGsE2SZ3Qn5F

    Landed · item 2 · PR #31237 merged by the merge queue as 169ff7e53889d275c7db1b1bd0e22e37791c58df.

    Reading Value
    PR state merged, merged_at from the pulls API
    Card state closed completed by Fixes #31156 (item 1 landed earlier as PR #31191)
    origin/main content judgeRestrictionProfile in packages/cli/src/utils/restriction-profile.ts, wired in packages/cli/src/commands/validate.ts (--target)

    Follow-ups: #31239 (domain:spec, profile node vocabulary / devPlugins / docblock), #31240 (domain:server, --target URL form, waits on cloud#3713). pm:dispatched removed with this record.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drivesdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions