Skip to content

Build master @ bc50cd5bunreleased — 31 commits past v1.282.0Last reviewed Last changed Grade fresh (aging >90d, stale >180d)Source / History

Applicability ​

bob tour grades an item parked when nobody uses it. That conflates a bad item with an inapplicable one: drupal-security goes unused because no Drupal is being shipped, not because it is a poor skill. bob tour --applicability (engine scripts/bobu/applicability.js, #2900, part of Bob University #2898) grades applicability first, so an item that fits no project in the portfolio reads as a portfolio decision, not a quality one.

bash
bob tour --applicability                                  # the human table
bob tour --applicability --json                           # one bob-applicability/1 document
bob tour --applicability --bucket not-applicable-anywhere # one bucket
bob tour --applicability --no-infer                       # declared profiles only

It is read-only: nothing is written and there are no network calls. It is deterministic: the document has no timestamps and every list is sorted, so unchanged inputs give byte-identical output.

Buckets ​

BucketMeaning
not-applicable-anywhereThe item is scoped, and no active portfolio project matches it. This is the cheapest bucket to clear.
applicable-unusedMatches at least one project, and no fleet usage event exists for it.
applicable-usedMatches at least one project, and it was used on some project on some fleet machine.
unscopedNot graded. applies_to.stacks includes any (unscoped_reason: any), or the metadata is missing (missing) or implausible (implausible). The last two carry metadata_fix: true.

Items covered: every registry/skills/*/SKILL.md, registry/commands/*.md, registry/agents/*.md and registry/runbooks/*.md, including those with no applies_to at all. An item with no applies_to is a finding, not a skip.

Matching ​

The rule is the orchestrator's (recommend.js explainInclude), reduced to the two applicability facets. A project matches an item when:

  • one of the item's applies_to.stacks is in the project's stack, and
  • the item's applies_to.project_types include any or the project's type.

A project whose type is unknown cannot be excluded on type. It matches on stack alone, and the match records type: "unknown". A project with no stack matches no stack-scoped item, because applicability is never claimed without evidence. default, opt_in and recommended_for do not affect applicability. They govern what gets recommended, not what applies, and are reported as-is.

Profiles ​

There is one profile per project manifest (provisions/<project>.json), read through the operator resolver. _*.json globals and ports.json are skipped. A project with _meta.active: false is left out and named in excluded.

FieldSource, in order
stack_meta.stack when non-empty (declared), else infer-profile.js on the project's _meta.path when that checkout exists on this machine (inferred), else [] (unknown)
project_type_meta.project_type (declared), else inferred as above, else null (unknown)

--no-infer skips inference. Profiles then come from declarations only, and the result is the same on every machine.

Metadata flags ​

An item with any flag lands in unscoped with metadata_fix: true and is not graded:

FlagWhen
missing-applies-toNo applies_to block.
missing-stacks / missing-project-typesThe block lacks one of the two lists.
any-with-named-stacksany sits next to named stacks, so the names mean nothing.
any-on-stack-specific:<stacks>stacks: [any], but the item's name or description names a stack from the registry's own vocabulary (the stacks scoped items declare, minus generic ones like node, shell, typescript). An agent's <example> blocks are ignored.
unknown-project-type:<types>A project_types value outside the orchestrator's set (web-app, api, backend, cms, research, cli, library, mixed, any).

Usage ​

Usage is the fleet-wide join scripts/evidence/fleet-usage.js (#2899), matched by item name. usage_base records what the split rests on: events, machines_reporting, missing (fleet machines with no usable snapshot), and sufficient (true when no machine is missing). While a machine is missing, applicable-unused is not yet proof of non-use. The table says so.

The document ​

json
{
  "schema": "bob-applicability/1",
  "buckets": ["not-applicable-anywhere", "applicable-unused", "applicable-used", "unscoped"],
  "counts": { "not-applicable-anywhere": 2, "applicable-unused": 22, "applicable-used": 1, "unscoped": 94, "metadata_fix": 38 },
  "usage_base": { "events": 60, "machines_reporting": 1, "missing": ["macbook-air"], "sufficient": false },
  "profiles": [{ "project": "example-cms", "stack": ["drupal", "javascript", "php"], "stack_source": "declared", "project_type": null, "project_type_source": "unknown" }],
  "excluded": [{ "project": "old", "reason": "inactive (_meta.active: false)" }],
  "items": [{
    "name": "drupal-security", "type": "skill", "bucket": "applicable-unused",
    "applies_to": { "stacks": ["drupal", "php"], "project_types": ["cms", "web-app"] },
    "default": false, "opt_in": false, "metadata_fix": false, "flags": [], "unscoped_reason": null,
    "projects": [{ "project": "example-cms", "stacks": ["drupal", "php"], "type": "unknown" }],
    "usage": { "events": 0, "projects": [], "machines": [] }
  }],
  "error": null
}

--bucket filters items only. counts always cover every item. On failure, error is {code, message}: usage for a bad flag, input for an unreadable usage or profiles file. An unreadable manifest is not an error: that project is left out and named in excluded.

Exit codes ​

CodeMeaning
0Graded.
2Usage error (unknown flag, unknown bucket) or unreadable input.

Environment ​

VariableEffect
BOB_SOURCEThe registry to grade.
BOB_OPERATORThe operator repo whose provisions/ are the portfolio.
BOB_APPLICABILITY_USAGEA bob-fleet-usage/1 file read instead of the snapshots (fixtures).
BOB_APPLICABILITY_PROFILESA JSON array of {project, stack, project_type} read instead of the manifests (fixtures).