Appearance
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 onlyIt 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
| Bucket | Meaning |
|---|---|
not-applicable-anywhere | The item is scoped, and no active portfolio project matches it. This is the cheapest bucket to clear. |
applicable-unused | Matches at least one project, and no fleet usage event exists for it. |
applicable-used | Matches at least one project, and it was used on some project on some fleet machine. |
unscoped | Not 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.stacksis in the project's stack, and - the item's
applies_to.project_typesincludeanyor 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.
| Field | Source, 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:
| Flag | When |
|---|---|
missing-applies-to | No applies_to block. |
missing-stacks / missing-project-types | The block lacks one of the two lists. |
any-with-named-stacks | any 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
| Code | Meaning |
|---|---|
| 0 | Graded. |
| 2 | Usage error (unknown flag, unknown bucket) or unreadable input. |
Environment
| Variable | Effect |
|---|---|
BOB_SOURCE | The registry to grade. |
BOB_OPERATOR | The operator repo whose provisions/ are the portfolio. |
BOB_APPLICABILITY_USAGE | A bob-fleet-usage/1 file read instead of the snapshots (fixtures). |
BOB_APPLICABILITY_PROFILES | A JSON array of {project, stack, project_type} read instead of the manifests (fixtures). |
Related
- Tour what is provisioned: the per-project usage grades this refines.
- Session Evidence Ledger: where usage comes from, and the fleet-wide join.
- Retired Items: where a
not-applicable-anywhereitem goes if it is retired. - CLI reference: every
bob tourflag.