Catalog Intake
Repository scanning adds a repository to the catalog only if it already contains a
componecat.yaml descriptor. Catalog Intake is for the
repositories that don’t: you point it at your Git organizations, see what it would
do, and confirm. It then creates a component for each repository it includes and, if
you agree to it, uses AI to fill in each component from its own repository.
An intake is a one-off run, not a schedule, so run another one when you want to pick up new repositories. It can cover several Git integrations at once.
Who can use it
Section titled “Who can use it”Catalog Intake is admin-only: the Catalog Intake entry, under Curation in the sidebar, and its pages are available to organization admins and nobody else. You need at least one GitHub, GitLab, or Bitbucket integration to read repositories through.
Starting an intake depends on your plan. If yours doesn’t include it, the Catalog Intake page says which plan does. If your plan changes so that it no longer includes Catalog Intake, your intakes stay visible and you can still retry or cancel them, and a running intake pauses until the plan includes it again.
Create an intake
Section titled “Create an intake”Open Catalog Intake and select New intake. Settings marked with an asterisk (*) are required.
| Section | Setting | Meaning |
|---|---|---|
| Targets | Git integration | An integration to read through. Each one can be a target once. |
| Targets | Organizations or groups | The GitHub organizations, GitLab groups, or Bitbucket workspaces to list, separated by commas. |
| Targets | Add target | Adds another integration to read through. Once there is a target for each Git integration, it says why it can’t add another: choose an integration in each target, or, once every one is chosen, connect another in Organization settings. An intake needs at least one target. |
| Filters | Exclude archived repositories | On by default. |
| Filters | Exclude forks | On by default. |
| Filters | Exclude after months without a push | Leaves out a repository with no push in this many months. The default is 24. |
| Filters | Exclude names matching | One pattern per line, ignoring case. * matches any run of characters and ? any one. With a /, a pattern matches the full name; without one, the name after the last /. |
| Defaults | Kind | The kind a repository gets when no kind rule matches. Only kinds with a repository are offered. |
| Defaults | Owner team | The owner of a component when no team matches the repository’s CODEOWNERS. |
| Defaults | Lifecycle | The lifecycle of the components created: Experimental, Development, Production, Deprecated, or Retired. The default is Experimental. A component for an archived repository, which the intake reads only when Exclude archived repositories is off, is Retired whatever this says. With AI on, enrichment can infer another lifecycle from the repository. Components already in the catalog keep their lifecycle. |
| Defaults | Namespace | The namespace of the components created. Optional. |
| Defaults | Kind rules | Applied in order: a repository with a file matching the pattern gets that kind. For example, Dockerfile can mean service. |
| Defaults | Dependency relationship kind | The kind of relationship recorded from manifests. Without one, that step is skipped. |
| Defaults | Relationship confidence threshold | A relationship the intake finds is added to the catalog if its confidence is at least this. A lifecycle enrichment infers is applied under the same rule. A number from 0 to 1. The default is 0.8. |
Continue to preview saves the intake as a draft and starts listing the repositories. A draft is only a saved set of choices: no component exists until you confirm. You can edit a draft or discard it from its page, and a discarded draft stays in your history as canceled.
The intake’s page shows the choices under Defaults, by name, below its scope. They can be changed only while the intake is a draft, since the intake gives each component its kind, owner and lifecycle as it creates it. Once the intake has started, the section stays on its page, read-only, so you can see what it used. To use other defaults, undo the intake and start a new one.
Wait for the listing
Section titled “Wait for the listing”The repositories are listed in the background, so the page comes back at once and shows how many have been found so far and which organization or group is being listed. Thousands of repositories can take a few minutes. You can leave the page meanwhile, and the preview appears when the listing finishes. While a listing runs, the draft can’t be edited or discarded: its edit form opens read-only and says why, and opens for changes once the listing has ended. You can Stop listing, which leaves the draft and its preview as they were before the listing began. From the keyboard, focus moves to the listing’s progress when you refresh or start, and back to Refresh preview when you stop it, and screen readers hear each change of the listing.
If a provider’s rate limit holds the listing back, it waits and carries on by itself, and the page says until when. A wait that lasts longer than two hours, by default, usually means the account is blocked rather than busy, so the listing pauses and names the credential. It pauses at once when the provider asks for a longer wait than that in one go, and says until when the provider holds it back. Check the account with its provider, then select Keep waiting or Stop listing.
If the server restarts while a listing runs, the listing stops moving for a few minutes, and then carries on by itself from the last page it saved. When it has been still for a few minutes, the page says by when it carries on.
One intake takes at most 5,000 repositories by default. A listing that finds more stops there, says how
many it found, and keeps nothing, and the intake can’t start. Split the targets across
several intakes, for example one per organization or group, and run them one after another. An
administrator of the instance can change the limit with CatalogIntake:MaxRepositoriesPerIntake.
Check the preview
Section titled “Check the preview”The preview shows what the intake would do if it started now, as of the latest listing, and says when that was.
- Repositories: each one with its disposition and, unless it’s included, the reason, 25 to a page. Filter them by disposition.
- Token estimate: a range, if your organization has a chat model, such as “About 2.3M to 13.2M tokens”, with the exact numbers and how many tokens each AI step would use at most. Nothing has been read yet, so it runs from what the model calls cost on their own to what they cost with as much of each repository as a call sends. The top of the range fills in the token budget under AI steps. Once the repositories are read, the estimate is recalculated from what was read, and the AI steps wait for you to confirm it. When it estimates nothing, it says why: no step that calls a model is available, or none of the listed repositories is included, as when every one is a name conflict.
- AI steps: the model, the budget, and the acknowledgment. See Agree to the AI steps.
- Component limit: a warning if the included repositories wouldn’t fit in your plan.
- Steps: each one marked available or unavailable, with the reason.
| Disposition | What happens |
|---|---|
| Included | A component is created. |
| Linked to existing | A component already has this repository’s URL, so the intake links to it instead of creating another. |
| Has a descriptor | The repository already has a descriptor, so it’s left to repository scanning. |
| Name conflict | Another repository’s component already has this kind, namespace, and name. Nothing is created for it. |
| Excluded | A filter left it out. |
The preview decides from the repository list and the catalog, without reading any repository’s files. Reading them can still change a repository’s disposition, for example when it has a descriptor the catalog hasn’t seen.
If a target can’t be listed, for example because of a misspelled group, the preview says so and the intake can’t start until you fix it, since starting would silently leave its repositories out. Select Refresh preview to list the targets again. The preview you see stays until the new listing finishes. Editing the targets, the filters, the default kind or the namespace lists them again too.
The intake also can’t start while a required step is unavailable. A step that isn’t required doesn’t hold it up: the intake skips that step when its turn comes. Open merge requests usually shows as unavailable here, because it needs a write token you set later.
Select Confirm and start when it looks right. The repositories are listed once more at that point, in the background as before, and the intake starts once that listing finishes. If the listing finds a reason not to start, such as a target that can’t be listed now, the intake stays a draft, the page says why, and the preview shows what that listing found.
Agree to the AI steps
Section titled “Agree to the AI steps”The AI steps send each repository’s README, manifests, and file list to a chat model, and that can include private code. What the model writes becomes readable by every member of your organization, even where a repository is restricted to one team. So AI runs only once you’ve settled three things on the draft’s page, under AI steps:
| Setting | Meaning |
|---|---|
| Use AI | On by default. Turn it off to run the intake without sending anything to a model. |
| Model | The default chat model, which is your organization’s and otherwise your instance’s, or one you choose. If a model you chose is later removed or turned off, the AI steps are skipped rather than sent somewhere else, and the list asks you to select another. |
| Token budget | How many tokens the AI steps may spend. It’s filled in from the estimate and counts once saved. Type it with or without commas; it’s shown with them once you leave the field. |
The acknowledgment names the model and its provider. It covers only that model, so choosing another one asks you again. The intake can’t start with AI on until the budget is saved and the acknowledgment is given, or you turn AI off.
Save AI settings confirms the save. The budget is checked when you leave the field or save, not as soon as you turn AI on. Acknowledge doesn’t check it, so you can give the acknowledgment before there’s a budget to save.
If your organization has no chat model, AI steps asks for neither a model nor a budget. The AI steps are skipped with that reason, and the intake still runs everything else.
When a model appears after the start
Section titled “When a model appears after the start”An intake started without a chat model has no token budget, because nothing asked for one. If a model becomes available while the intake can still run its AI steps, before you go on from review, its page says the intake has no token budget and asks for the acknowledgment. The budget is filled in from the estimate for the intake’s repositories, and follows the estimate as Read repositories goes on and when it finishes, until you type a budget of your own.
- Set budget saves it. Then select Run again on each AI step that was skipped.
- Turn AI off sends nothing to a model, and the AI steps are skipped.
A skipped AI step doesn’t run again by itself, but what its row under Steps says follows the intake as it is now, so it never says there’s no chat model once there is one. It says what still stands in the way, such as the missing budget or the acknowledgment, or that AI is turned off. Once nothing does, it says the step was skipped before the intake could use a model, and runs only when you run it again. Once the intake has gone on from review, the reason stays as it was when the step was skipped.
This is offered only until an AI step has spent tokens. After that, the budget can only be raised.
Give the AI steps instructions
Section titled “Give the AI steps instructions”Each AI step can take your own instructions or context, up to 2,000 characters, in Instructions for Enrich with AI and Instructions for Relate with AI under AI steps. A counter under each field shows how much you’ve used. If pasted text goes over the limit, the counter turns red, the field says so, and the instructions can’t be saved until you shorten them. If you turn AI off before shortening them, the message stays under AI steps until you turn AI back on and fix them. The fields are hidden while AI is off, and any text you saved is kept for when you turn it back on, which the section says. Use them for what the model can’t know from a repository, for example:
- “Our services are named
<team>-<thing>-svc; the team prefix is not part of the description.” - “Repos under
platform/are shared infrastructure.” - “Treat anything mentioning PCI as tag
pci.” - “Calls through
gateway-*are not dependencies on the gateway.”
Your text is added to the step’s built-in instructions, after them and before the repository’s content. It never replaces them, so it can’t change what a step may write: the model never sets an owner or a kind, field values are still checked against the field, a description or field someone wrote is never overwritten, and the confidence threshold still decides what’s written. Instructions asking for any of that have no effect. Each step gets only its own text. On a call that would pass the size cap, the repository’s content is cut to make room for your instructions, not the other way round, and the token estimate includes them.
After the start, the intake’s page shows the instructions under AI instructions, and
you can change them with Save AI instructions until you go on from review, while no
AI step is running. While they can’t change, the card says why and when they can again.
A step that already ran keeps what it wrote; select Run again on it to use the new
text. Under Steps, an AI step whose latest call used your instructions
says With your instructions, and each AI step shows, in smaller text, the prompt version
that call used. With instructions it ends in +custom- and a short code for the text, so you
can tell which text produced which results.
Changes are recorded in the audit log like any other change to the intake’s settings.
Follow its progress
Section titled “Follow its progress”An intake’s page updates by itself while it runs. It shows the intake’s status, a row for each step with its counts, and each repository with its status per step and any error. Filter the repositories by step, status, disposition, owner team, or component kind to find the ones you care about.
Times on the page read in your own time zone, to the minute, with the month by name: Nov 7, 2026, 7:19 PM. The list of intakes says how long ago each was created, such as 6m ago, and gives the full time when you hover over it. So does the Last event of a Git integration’s webhooks.
Once an intake has started, a bar of links at the top of its page stays in view as you scroll: Overview, Scope, Repositories, Defaults, Steps, Review, Merge requests and Descriptors, each shown while its section is. Select one to go to that section. Repositories is in the Scope section, closed so the page stays short. Select its name to open or close it; going to it from the bar, or from a merge request flag, opens it. The link of the section you’re reading is highlighted. On a narrow screen the bar scrolls sideways, and a fade at its edge shows there are more links that way. Links that leave Componecat, such as View merge request, open in a new tab and show the external-link icon.
| Step status | Meaning |
|---|---|
| Pending | Waiting for its turn. |
| Running | Repositories are being processed. |
| Succeeded | Finished, with none failed. |
| Partially succeeded | Some repositories failed and others finished. The next step still runs. |
| Failed | Every repository it processed failed. The next step waits until you retry, run it again, or cancel. |
| Skipped | It didn’t run. The row gives the reason. |
Read repositories creates a component from each included repository, Enrich with AI then fills it in, and Relate from manifests and Relate with AI connect those components. When those steps have settled, the intake’s status is Awaiting review, and the components and relationships it created are in the catalog. It stops there and changes nothing in any repository: review is where you decide what goes into each descriptor. You can still retry or run its steps again. Open merge requests waits until you go on from review and release a batch.
If the intake is paused, for example because your plan no longer includes Catalog Intake or an integration it needs was removed, its page gives the reason. It continues by itself once that no longer applies.
Ask an AI agent about an intake
Section titled “Ask an AI agent about an intake”An AI agent connected to Componecat can read your intakes too, when it signs in as an organization admin. It can’t start, decide, or undo anything; those stay on the intake’s page. For anyone else, the agent is told the tools need an admin.
| Tool | What the agent gets |
|---|---|
list_catalog_intakes |
Your intakes, newest first, each with its status, when it was created, started and finished, its repository counts and its tokens used. It can ask for one status only, such as Awaiting review. |
get_catalog_intake |
One intake: its status and why it’s paused, the integrations and Git organizations it covers and its filters, the kind, owner team, lifecycle and namespace it gives new components, its kind rules, the relationship kind and confidence threshold for relationships, its AI settings, each step’s counts, and its tokens used against the budget. Kinds, the team and the relationship kind come with their names. |
list_catalog_intake_entities |
The components of one intake: the ones it created and the ones it linked because they were already in the catalog, each with its kind, owner, lifecycle, repository and review state. It can ask for only the created or only the linked ones, and for one review state, such as the created components still Pending review. A component that has since been deleted is listed by its repository and ID. Repositories that got no component aren’t listed. |
Confirm the token estimate
Section titled “Confirm the token estimate”Once Read repositories has finished, the intake knows how much each repository holds, so it recalculates the token estimate from what it read, and waits for you before it sends anything to a model. Its page shows Confirm the token estimate: the tokens the AI steps would use at most, for how many repositories, how many of them each AI step would use, your budget, and whether the estimate is over it.
- Confirm and start lets the AI steps run, within the budget.
- Raise budget and start saves a higher budget, which confirms the estimate too. Raise it when the estimate is over the budget, or the steps pause when they reach it.
- Turn AI off skips the AI steps, and nothing is sent to a model.
It doesn’t go on by itself, and it asks only once per intake. Once you’ve chosen, the page says the intake is about to continue, and it does on its next pass. By default each model call sends at most 64 KiB of a repository, about 21,000 tokens: the README and manifests first and the file list last, so a large repository costs no more than that. The repository’s review flags say when a call was cut (Prompt trimmed).
When it waits for a rate limit
Section titled “When it waits for a rate limit”Git providers and AI models limit how many requests a token or model may send. When one refuses a request because of its limit, or runs low, the repository goes back in line rather than failing, and its step says Waiting for the rate limit until a time. A repository that waits never uses up one of its retries. Every other repository that would use the same token or model waits as well, in any intake, so nothing keeps running into the limit. When the time comes, the intake carries on by itself.
This covers GitHub’s limits (the hourly limit and its secondary limits, which can answer
with a 403), GitLab’s and Bitbucket’s 429s, and a model’s 429, or a 503 that says
when to try again. A 403 that isn’t about a limit, such as a token without access, still
fails the repository with its message.
A wait that goes on for more than two hours with nothing getting through usually means the account is blocked rather than busy, so the intake pauses and names the token or model it waits on. It pauses at once when the provider asks for a longer wait than that in one go, and says until when. Componecat waits as long as the provider asks, up to 24 hours, and sends nothing with that token before then. This pause doesn’t end by itself. Check the account with the provider, then:
- Keep waiting carries on as soon as the limit lets requests through, and counts another two hours, from now or from when the provider said the limit lifts if that is later, before it pauses again.
- Cancel intake stops it, as below.
Only time spent waiting counts toward the two hours, so an intake in review or at another
pause never reaches it. An administrator of the instance can change the bound with
CatalogIntake:MaxRateLimitWaitMinutes.
How many repositories it works on at once
Section titled “How many repositories it works on at once”Each Git integration works on up to five repositories at a time, across every intake that uses it, and intakes that share an integration share those evenly. To change the number for one integration, edit it under Organization settings → Integrations and set Catalog Intake concurrency to a whole number from 1 to 50. Leave it blank for the default. Other integrations keep their own.
The AI steps don’t count toward this number, since they read nothing more from the provider. Instead, up to five repositories at a time are sent to each AI model, across every intake that uses it.
A higher number finishes sooner, but it spends the provider’s hourly rate limit faster, and once the limit runs low the intake waits for it, so it doesn’t get more done in an hour than the limit allows. A GitHub App installation usually has a higher limit than a personal access token (up to 12,500 requests an hour, depending on how many repositories and users it covers), so it can take a higher number before it waits.
Reading a repository costs few requests. On GitHub, Read repositories sends two for most
repositories: one for the list of files and one GraphQL query for everything else, which
draws on GitHub’s separate GraphQL limit. On GitLab and Bitbucket it sends a few for the
repository and one per manifest it reads. When you run the step again or retry a repository
that hasn’t changed, the provider answers most requests with “not modified” and Componecat
reuses what it read before; GitHub doesn’t count those against its hourly limit. An
administrator of the instance can change the default with
CatalogIntake:MaxConcurrentItemsPerProvider.
When it reaches the token budget
Section titled “When it reaches the token budget”When the tokens used reach the budget, the AI step pauses with its remaining repositories waiting, and the intake’s page shows what was spent. This pause doesn’t end by itself:
- Raise budget carries on with the waiting repositories.
- Skip step skips them, keeps what’s done, and moves on. You can run the step again later.
Calls already under way finish and are counted, so the total can pass the budget by what they spend.
What enrichment writes
Section titled “What enrichment writes”For each repository, one model call sees only that repository and your organization’s schema. It fills in the component’s description, its tags, and the custom fields assigned to its kind. Each value is marked Inferred by AI and names the intake.
- Values people set are kept. A field someone edited by hand, or that a descriptor or an integration set, is never overwritten, including when the step runs again.
- A component the intake only linked keeps what it has. Only its blank fields are filled in.
- A value the model repeats keeps its source. If its answer matches what a field already holds, nothing changes, including how the value is marked.
- The model doesn’t choose owners. The owner stays as the read step set it, whatever the model or the repository says. User, team, and JSON fields aren’t offered to it.
- An invalid value is dropped. A value of the wrong type or outside a field’s options is left out, and a warning on the repository’s row names the field. The other values are kept.
- A different kind is only a recommendation. Review shows it under Suggestions with the model’s reason, and the component keeps its kind unless you accept it. It’s only recommended for a component the intake created, since only that one’s kind is the intake’s to change.
Running the step again updates the values it wrote rather than adding to them. If a repository’s call fails or its answer can’t be used, only that repository fails, and retrying it runs only that one.
The lifecycle enrichment infers
Section titled “The lifecycle enrichment infers”The same model call can propose a lifecycle for a component the intake created, from what
the repository shows: README wording such as “deprecated”, “no longer maintained”,
“superseded by”, “experimental”, “proof of concept” or “WIP”; a 0.x or prerelease version
against 1.0 or later; deployment files such as a Dockerfile or a Helm Chart.yaml, or
none. Where the repository doesn’t say, the component keeps the intake’s default lifecycle.
Lifecycle describes the software, not whether anyone has reviewed the component.
- Only at or above the threshold. The lifecycle is applied when the model’s confidence is at least the intake’s Relationship confidence threshold, and it’s marked Inferred by AI on the component’s Lifecycle row and in its history. Below the threshold, or with no confidence, the component keeps its lifecycle, and review shows the suggestion under Suggestions with its confidence and the model’s reason, for you to accept.
- Only from the default. It’s never applied over a lifecycle someone changed, including while the model was answering, and never to a component the intake only linked.
- Archived repositories stay Retired. The model isn’t asked about them.
- Running Enrichment again keeps what it said. Once a lifecycle is applied, or someone has changed it, the model isn’t asked again, and review keeps the suggestion from the earlier run. When the component’s lifecycle has changed since, it says Changed since instead of saying the component has it.
- An invalid answer is dropped. Anything other than the five lifecycles is left out with a warning on the repository’s row, and the rest of the answer is kept.
With AI off, the step skipped or the token budget reached, the component keeps the default.
Relationships from manifests
Section titled “Relationships from manifests”Relate from manifests finds relationships from what repositories already declare,
without any AI. It looks at what each repository depends on and at what the others publish,
so a repository that depends on @acme/payments is related to the one whose package.json
is named @acme/payments.
| File | Publishes | Depends on |
|---|---|---|
package.json |
Its name, unless it’s private |
Its dependency sections, development ones included |
go.mod |
Its module |
Its direct require entries |
pom.xml |
Its group and artifact | Its dependencies |
*.csproj |
Its package id, assembly name, or file name, unless it isn’t packable | Its PackageReference items |
pyproject.toml |
Its project name, in the PEP 621 or Poetry form |
Its dependencies, extras, and groups |
Cargo.toml |
Its package name, unless publish = false |
Its dependency tables |
Chart.yaml |
Its name |
Its dependencies |
A local dependency doesn’t count, since it points at files rather than at something another
repository publishes: a file: or workspace: version in package.json, or a path in
Cargo.toml or a Poetry dependency.
The target can also be a component outside the intake that has a repository. Since the
intake hasn’t read that repository, it goes by what the catalog knows: a Go module path
matching its repository URL, or a package with the same name as the component or its
repository. A package with a scope or group, such as @acme/payments or com.acme:payments,
needs a repository whose owner is that scope or part of that group.
Each match gets a fixed confidence of 0.9. If that’s at or above the intake’s threshold, an inferred relationship of the intake’s dependency relationship kind is added to the catalog, unless the catalog’s rules for that kind don’t allow it. An inferred relationship is marked as such and never replaces one that a person or a descriptor declared. Raise the threshold above 0.9 to add none of them.
Whether it’s added or not, the intake records each match with the file and the name it comes from, and for a name another repository in the intake publishes, that repository and the manifest that publishes it. If two repositories publish the same name, the intake can’t tell which one is meant, so it adds no relationship and notes the ambiguity. A dependency that matches nothing, or a manifest it can’t read, is simply left out.
Running the step again updates what it found rather than duplicating it, and removes a relationship it added earlier if the manifests no longer support it.
Relationships from AI
Section titled “Relationships from AI”Relate with AI runs once Enrich with AI has finished, so it sees the enriched components. For each repository it sends a chat model what was read of the repository, along with a shortlist of up to 20 components it could relate to, from this intake and from the rest of your catalog. The model has to choose from that list.
The shortlist comes from search by meaning if your organization has it: the components nearest to this one. Otherwise it’s the components the repository mentions by name, then those sharing words with the component’s name, description, and tags. With search by meaning, the intake waits to start this step until its components have been indexed, and shows Paused with the reason in the meantime. That usually takes a minute or two. If it doesn’t finish, check your organization’s embedding model, or remove the model to use the other way of building shortlists.
A repository’s content can’t be trusted to tell the model what to do, so a proposal is thrown away unless it meets all of these:
- Its target is on the shortlist.
- Its relationship kind is allowed between the two components’ kinds.
- It cites a file that was read from the repository.
Nothing is kept for a proposal that’s thrown away, and the step’s row says how many there were.
Each proposal that’s left is recorded with the model’s confidence, the file it cites, and its reasoning. If its confidence is at or above the intake’s threshold, an inferred relationship is also added to the catalog, unless the catalog’s rules for that kind don’t allow it. Below the threshold, it stays a proposal and adds nothing to the catalog. A relationship that a person or a descriptor declared stays as it is, and so does one another step has already inferred.
Running the step again updates what it proposed rather than duplicating it, and removes a proposal and its relationship if the model no longer makes it or its confidence has fallen below the threshold. A proposal someone has rejected isn’t proposed again, whichever step or intake it came from.
If your organization has no chat model, or AI is off on the intake, the step is skipped with that reason.
Review before anything leaves Componecat
Section titled “Review before anything leaves Componecat”Everything an intake has done so far stays inside Componecat, and can be undone there. A descriptor goes into other teams’ repositories, so a person decides what it says. The Review section of an intake’s page appears when the intake reaches Awaiting review, and stays while merge requests are being opened and followed. It goes away once the intake has ended, because there’s nothing left to review. Only admins can use it.
Each repository’s row says how many of its suggestions are still to decide, such as 2 suggestions to decide, or No suggestions, so you can see where the work is without opening it. Select a repository’s name to open it. What opens is indented under the name, on a background of its own, and ends with End of and the repository’s name and a Close button. You see:
- The rendered
componecat.yaml, as it would be committed now, without the first line that points editors at the kind’s schema (the committed file keeps it). It changes as you decide: an approved relationship goes into itsrelationships, and an accepted lifecycle into itslifecycle. - Its suggestions, below the YAML, under To decide and then Decided. They’re everything the intake suggests for the repository: a kind and a lifecycle the model proposes, and the relationships the steps propose. A repository with nothing suggested has no Suggestions section. Each suggestion reads as the change it would make: Kind or Lifecycle and the value, or the kind of relationship and the component it points to. Under that are its confidence, as a percentage and as a bar with the intake’s threshold marked on it, where it came from, and for a relationship how many citations it has. One below the threshold has a dashed amber edge and says Below threshold: a relationship like that isn’t in the catalog unless you approve it, and a lifecycle isn’t on the component unless you accept it. Its decision is at the end of each row: Accept for a kind or a lifecycle, Approve and Reject for a relationship. Select Why? to see what it rests on: the model’s reason for a kind or a lifecycle, and for a relationship the manifest and the name it declares, or the files the model cites and its reasoning.
- Its flags, which show on its row whether it’s open or not. Select a flag to see what it means and what to check. Partly read and Prompt trimmed are warnings, shown in amber with a warning icon, because the description or relationships may be missing something:
| Flag | What it means | What to check |
|---|---|---|
| Likely monorepo | The repository looks like a monorepo, but it’s still one component. | That one component describes it. |
| Partly read | Part of the repository wasn’t read because it went over a size limit. | Its description and relationships, which may be missing something. |
| Prompt trimmed | What an AI step sent to the model was cut to fit the prompt size limit, keeping the README and manifests first. | Its description or relationships, which may be missing something. |
Decide on a relationship
Section titled “Decide on a relationship”| You | What happens |
|---|---|
| Approve | The relationship becomes manual, with you as the person who declared it, and it goes into the YAML. If it was below the threshold, this is what adds it to the catalog, unless the catalog’s rules for that kind don’t allow it. |
| Reject | The relationship is deleted and the proposal stays rejected, so running the relationship steps again doesn’t propose it. |
| Neither | A relationship already in the catalog stays there, marked as inferred, and stays out of the YAML. Repository scanning never removes it. |
A proposal below the confidence threshold is only in review: it isn’t in the catalog as unconfirmed, and nothing but your approval adds it. You can change your mind on a decision. If someone later removes an approved relationship from the component, the proposal says so, and approving it again puts it back. A proposal the intake held back, because two components could answer to its name or it’s below the threshold, says why while it’s undecided. Once you approve it, it reads as approved like any other, and its relationship gets the same description as one the intake added itself, such as “Declared in package.json as @acme/payments.” If a person or a descriptor has already declared the relationship, there’s nothing to decide, and the proposal says so. Change it on the component instead. That includes a relationship someone removed after it was approved and then added back by hand, since it’s theirs now.
Approve repositories
Section titled “Approve repositories”Only an approved repository’s descriptor goes into the archive or a merge request. Select repositories and choose Approve selected, or use Approve on one. To decide every repository that matches the filter, across every page, see Decide everything that matches.
Approving a repository also approves its relationships at or above the threshold, which puts them in its YAML. The confirmation says how many, and how many other proposals stay undecided, before anything changes. Those are the ones below the threshold, and the ones the intake didn’t add to the catalog, such as a name two components could answer to. They only ever get a decision of their own, so approving a repository never adds a relationship the catalog doesn’t already have.
A repository with no proposed relationships at all is approved at once, without a confirmation, because there’s nothing in it to warn about. The same goes for Approve selected when none of the selected repositories has one.
Reject keeps a repository’s descriptor out of the archive and merge requests, and leaves its relationships as they are. You can approve it later.
Share the review out by team
Section titled “Share the review out by team”A large review can be shared out, so each team reviews its own repositories. By owner team
lists each team that owns a component of the intake, with how many of its repositories are
pending, approved and rejected, so you can see what’s left per team. A repository whose
CODEOWNERS matches no team belongs to the intake’s default owner team, and is counted and
filtered under that team like any other.
Select a team to filter the review to its repositories. The filter is in the page’s address, so you can copy a team’s link and send it to them. Anyone who opens it needs to be an admin, as for the rest of the review. If a link’s owner team or component kind isn’t one the review can read, for example because the link was cut short, the review says so and shows any team or kind instead.
Filter the review by Owner team, Component kind and Decision, under Repositories in the Decide by filter section above the list. The filters combine, and they choose both which repositories the list below shows and what Approve all matching repositories and Reject all matching repositories, in the row below them, decide, so filtering to one team and approving all matching approves only that team’s repositories. The Repositories list under Scope has the same owner team and component kind filters.
The list itself, under Decide repositories, is for deciding a page at a time: select repositories, or Select all on this page, and Approve selected, or decide one repository where it’s open.
Owner teams come from CODEOWNERS, and only synced teams match. A team someone
made by hand never does, so its repositories fall back to the default owner.
Decide everything that matches
Section titled “Decide everything that matches”A large intake is easier to review by filter than a page at a time. Everything that decides by filter is in one section, Decide by filter, above the list of repositories, apart from what acts on a page. Under Repositories, Approve all matching repositories and Reject all matching repositories decide every repository the review’s filters match, by Decision, Owner team and Component kind, on every page, not just the one you see. They’re unavailable, with the reason beside them, when the list shows no repositories, and one of them is when the Decision filter shows only repositories that already have that decision.
Under Relationships, in the same section, the filters are separate from the repository filters and don’t change the list. Approve all matching relationships and Reject all matching relationships decide the undecided relationships of every repository in the intake, by kind, by the step that proposed them, and at or above a confidence you enter, from 0 to 1.
The confirmation states the exact count, such as “Approve 3,000 repositories?”, and names the filters it applies, such as “every pending repository owned by Squad 03 of kind Library”. Nothing is decided unless the filters still match that many when you confirm. If nothing matches, the confirmation says so and offers only Close. If the filters no longer match the count, it says so, the review’s counts and list catch up with what changed, and you can check again. The decision then runs in the background, and the review shows how far it has come. Its pending, approved, rejected and undecided counts keep up as it goes, and the list of repositories is read again when it ends. You can leave the page while it runs, and only one runs on an intake at a time.
A decision by filter follows the same rules as one made by hand:
- Approving a repository also approves its relationships at or above the threshold.
- Only repositories whose decision would change are counted, so approving all matching leaves out those already approved.
- A repository whose merge request has opened isn’t matched, since its decision can’t change after that.
- Approving relationships leaves out one the intake held back because two components could answer to its name. Decide those one at a time. A relationship below the threshold is added to the catalog, unless the catalog’s rules for its kind don’t allow it.
- A relationship that two steps proposed counts once, and both proposals are decided together.
Anything that changes while it runs is left as it is and counted as skipped, not failed: a repository someone decides by hand, one whose merge request opens, or one whose component was recreated under another kind. When it ends, the review says how many were decided and how many were skipped. If the intake stops being reviewable while it runs, for example because it’s canceled, the rest is skipped and the review says why. That line describes the filters it ran under, so it goes away once you change the owner team, component kind or decision filter.
See what still awaits review
Section titled “See what still awaits review”The intake creates its components before review, so they’re in the catalog, its search and the MCP server while you decide. Until you approve one, it carries an intake review badge everywhere it’s shown: the header of its page, its row in the catalog’s list and tree, its details in the graph, and the home page’s recently updated list. The badge has a dashed outline so it doesn’t read as a lifecycle, which describes the service or library rather than whether anyone has checked its catalog entry.
| Badge | When |
|---|---|
| Awaiting intake review | The intake created the component and nobody has approved or rejected its repository yet. |
| Rejected in intake review | Its repository was rejected. The component stays in the catalog, so the badge tells readers a reviewer turned it down. |
There’s no badge once the repository is approved, once the intake has ended (Completed, Canceled or Undone), or on a component the intake only linked because it was already in the catalog. An intake that’s paused or running a step again hasn’t ended. When a component is recreated under a recommended kind, the badge moves to the new one. Deciding, finishing, canceling and undoing update open pages without a reload.
Screen readers and voice control use the badge’s own words, “Awaiting intake review” or
“Rejected in intake review”. On a component’s page, under its name, and in its details in the
graph, a line says why it has the badge, what an admin can do about it and when it clears, for
example “Created by intake “Acme repositories” and not reviewed yet. Open the intake’s review to
approve or reject it. The badge clears once it’s approved or the intake ends.” In the catalog’s
list and tree and on the home page, screen readers read the same line as the badge’s description,
and it shows when you hover over the badge. For admins, the badge on a component’s page and in the
graph is a link to the intake’s review, filtered to the component’s owner team and kind. Anyone
else sees the badge without the intake’s name, and the line says an organization admin decides it
in the intake’s review. In the graph, a component’s node also says “awaiting intake review” or
“rejected in intake review” to screen readers, after its kind. To list them all, search for intakeReview:pending or intakeReview:rejected
(see Searching the catalog). AI agents read the same state from the MCP server’s
catalog tools.
Accept a lifecycle suggestion
Section titled “Accept a lifecycle suggestion”A lifecycle the model suggested below the threshold waits under To decide until you decide. Accept gives the component that lifecycle, marked Inferred by AI, as if its confidence had cleared the threshold, and the YAML is rendered again. It’s refused, with the reason, if someone or a descriptor has set the lifecycle since, or a step is still working on the repository. Once the component has the lifecycle it moves to Decided as Applied, and one the component has moved on from says Changed since: the lifecycle on the component is the one that counts.
Accept a kind recommendation
Section titled “Accept a kind recommendation”A component’s kind is part of its identity in the descriptor, so accepting a recommendation replaces the component: Accept asks first, then creates a new one of that kind, moves the old one to the Trash, and renders the YAML again. Webhooks report a delete and a create. The new component keeps the old one’s name, description, tags, owner, and repository, the custom fields its kind has, and the relationships its kind allows. An approved relationship its kind doesn’t allow goes back to undecided, and the repository needs approving again, since its file has changed.
Accepting is refused, with the reason, if:
- Someone has edited the component, declared a relationship on it, added interfaces or documentation to it, written in its activity log, or put it in a collection.
- Its repository has an open or merged merge request, or its component is synced from a descriptor.
- An integration manages the component.
- The intake only linked the component rather than creating it.
- The kind has no repository, or the name is already taken under that kind.
Go on to merge requests
Section titled “Go on to merge requests”Go on to merge requests ends the wait at review. It opens nothing by itself, and the steps before review can’t run again afterward. It needs at least one approved repository on an integration that can take merge requests, and review says why not if that’s missing. Its confirmation counts only the approved repositories a batch can reach, and says how many are on an integration that can’t take merge requests. You can keep deciding on relationships and repositories after this.
If your organization doesn’t want Componecat writing to repositories, leave the intake here and commit the descriptors yourself.
Open merge requests
Section titled “Open merge requests”The Merge requests section of an intake’s page opens a merge request in each approved repository. That means a pull request on GitHub and Bitbucket. It appears when the intake reaches Awaiting review. Once the intake is Completed it stays, to show what happened to each repository, with nothing left to act on. Only admins can use it.
Nothing is opened until an admin releases a batch. Each merge request adds componecat.yaml at the
root of the repository, on the branch componecat/add-descriptor, against the default branch. Where
an earlier merge request on that branch was closed by an intake’s undo, or when you
reopen one, a number is added: componecat/add-descriptor-2,
then -3 and so on. Each repository’s row shows the branch it uses. Your provider’s branch
protection applies as usual. The title and description are the same for every
repository: what the file does, a link to the component, and that merging makes the file the
source of truth for that component. Nothing a model wrote appears in them. It can only reach the
repository through the YAML you reviewed.
What merge requests need
Section titled “What merge requests need”Each integration the intake covers is listed with what it still needs. An integration that can’t take merge requests leaves only its own repositories out. Their YAML stays available, and the intake’s other integrations carry on.
| It needs | Why |
|---|---|
| A write token | Set one under Merge requests. It belongs to this intake and this integration, and it’s deleted when the intake ends. Each integration needs its own. |
| Repository scanning on | A merged file is read only through repository scanning, so without it nothing would ever pick up the file. |
| Writes supported for its provider | If a provider isn’t supported yet, the section says so. |
Release a batch
Section titled “Release a batch”Choose a Batch size, 25 by default and up to 100, then select Release batch. Until the size is a whole number in that range, Release batch and Check the next batch stay disabled and the field says why. Each merge request notifies people, so you can try ten repositories, see how they’re received, and continue. The merge requests are opened one at a time per integration, a few seconds apart, in repository name order. Approved repositories past the batch size wait for another release, and the intake’s status stays Opening merge requests until none are left. It then moves to Monitoring, and a repository you approve after that can still be released.
Check the next batch shows what the next release would find, without writing anything. A release checks every repository again anyway, in case something has changed.
Release everything, paced
Section titled “Release everything, paced”To open merge requests for every approved repository without releasing batch after batch, use Release all approved repositories, paced in the same section. Componecat then opens them by itself, one at a time per integration at the rate you set, until none is left. It takes them team by team, by owning team and then by repository name, so each team’s merge requests arrive together.
- Rate. Set how many merge requests an hour each integration opens. The default is what that account’s budget holds (below): 80 an hour on GitHub, 160 on GitLab and 120 on Bitbucket. Leave the field empty to use it. The fastest is one every few seconds, 720 an hour by default. You can change the rate while it runs and select Save rates.
- Start. Start paced release asks first, saying how many repositories it releases and about how long that takes. Select Release n repositories in the confirmation to start it.
- Progress. The section shows how many merge requests Componecat has opened, how many approved repositories are left, and when the last should go out at the rates set, in your own time. A repository whose merge request a team closed before isn’t opened again, so it isn’t counted as opened. When it is waiting, it says what for and until when. While the intake itself is paused on a rate limit, the release is held with it: the section says so, with the provider’s time, and gives the finish as the earliest it can be. It goes on once you choose Keep waiting on the intake.
- Pause, resume and stop. Pause stops new merge requests, and one already started finishes. Resume carries on from where it was, with the next merge request at the next slot of its rate. Stop ends it, and the rest wait for a batch you release by hand or for a paced release you start again. Canceling or undoing the intake stops it too.
While a paced release runs, Release batch is unavailable; pause or stop it first. A paced release asks for no extra plan or setting, and what can happen to each repository is the same as for a batch.
The account’s budget
Section titled “The account’s budget”GitHub limits each account to about 500 requests an hour, and 80 a minute, that create content, such as commits, pull requests and comments, whatever sends them. One merge request takes about six of them on GitHub, three on GitLab and four on Bitbucket. So Componecat keeps one budget per account, 480 an hour and 75 a minute, that everything it writes with that account draws on, across all your intakes: merge requests, paced or released by hand, the checks before them, the commits that keep them current, and an undo’s closes. Whatever would go past the budget waits for room rather than being refused, and an undo’s closes go first, so a release never holds up an undo. When the provider refuses anyway, for example because the same account was busy outside Componecat, the release waits as described in When it waits for a rate limit, and no repository fails because of it.
An administrator of the instance can change the budget with CatalogIntake:ContentCreationPerHour and
CatalogIntake:ContentCreationPerMinute, and the shortest gap between merge requests with
CatalogIntake:MergeRequestIntervalSeconds.
What can happen to a repository
Section titled “What can happen to a repository”| Result | What it means |
|---|---|
| Open | The merge request is open, and its link is on the row. |
| Not opened, no write access | The token is valid and lacks what it needs in that repository, such as a scope or a role. Fix the token’s access, then select Retry, or copy the YAML. |
| Not opened, token rejected | The provider rejected a token itself, because it’s invalid, expired, or revoked. It’s the intake’s write token, or the integration’s own credential that the repository is read with first. Replace whichever it is, the write token under Integrations in this section or the credential on the integration, then select Retry. Check the next batch shows this as Token rejected. |
| Not opened, archived | Nothing can be pushed to an archived repository. |
| Not opened, has a descriptor | A descriptor appeared after the intake read the repository, so the repository is left to repository scanning, which adopts the component by kind, namespace, and name. |
| Not opened, branch exists | componecat/add-descriptor already exists and holds something else. Nothing is overwritten. Delete the branch and select Retry, or copy the YAML. |
| Closed without merging | Someone closed the merge request, or the branch already had one that someone closed. It isn’t opened again unless you reopen it. A merge request that an earlier intake’s undo closed doesn’t count: Componecat closed it, not a team, so a new intake opens a fresh one on the next branch, such as componecat/add-descriptor-2. |
| Merged, waiting to be read | The file is on the default branch, and repository scanning hasn’t read it yet. |
| Merged, ingestion failed | The file couldn’t be read into the catalog, and the row says why. |
| Merged, ingestion failed, no longer checked | Every try to read the file has failed for a day, so the intake stopped checking it. The row says why. |
| Ingested | The file was read, and the component now comes from it. |
One repository failing doesn’t affect the others in its batch. Retry next to a repository, or Retry failed on the step, tries again and leaves the others alone. Copy YAML works on every row, so a repository the token can’t reach can still get its file by hand.
Follow a merge request
Section titled “Follow a merge request”Componecat follows each open merge request from your Git provider’s webhook, so a merge or a close shows on the intake’s page within seconds. Send the integration’s webhook the pull request or merge request events as well as pushes, as Connect the webhook describes for each provider:
| Provider | Events to send |
|---|---|
| GitHub | Pushes and Pull requests |
| GitLab | Push events and Merge request events |
| Bitbucket | Repository: Push, and Pull Request: Created, Updated, Merged and Declined |
These events need no extra scope on any token. Each delivery is checked against the integration’s webhook secret, or its signing token on GitLab, as a push is.
Pull request and merge request events count toward the same limit on webhook deliveries as pushes,
and an organization-level webhook sends many of them. If your Git provider’s webhook log shows a
delivery answered 429, see Troubleshooting under
repository scanning for what is caught later and what to redeliver.
Componecat also checks each open merge request itself, with the integration’s own read token, not the write token, so this carries on after a write token is deleted. That check is the backstop for an event that never arrived. Webhook events, under Merge requests, shows for each integration whether its events are arriving and how often its open merge requests are checked:
- Events arriving: the integration’s webhook has delivered a pull request or merge request event, from any repository, in the last day. Each open merge request is also checked every 6 hours, in case an event is missed.
- No events arriving: none has arrived in the last day, or ever, so tracking falls back to checking each open merge request every few minutes, as it does with no webhook at all. The row names the events to turn on in that integration’s Git provider.
Add the webhook at the organization or group level, or on every repository the intake targets. Whether events are arriving is judged for the whole integration, so an event from any one repository counts for all of them, and a merge request in a repository with no webhook is then checked only every 6 hours.
A merge request reopened after Componecat recorded it closed stays closed here, whatever its events say. To ask again, reopen it from its row.
When one is merged, the push reaches repository scanning, through your webhook or the next scan. Scanning finds the component by kind, namespace, and name, and links it to the file, so no second component appears. Relationships the file declares now come from the file. If one names a component that doesn’t exist yet, it’s resolved when that component appears, so merge requests can merge in any order. Then the repository reads Ingested.
If the file can’t be read, for example because the owner it names no longer matches a team, the repository reads Merged, ingestion failed, with the reason, and it isn’t ingested. Fix the file in its repository, and the next push or scan tries again. If every try fails for a day, the repository reads Merged, ingestion failed, no longer checked: the intake keeps the reason and stops waiting for it, so it no longer holds the intake open. A fixed file is still read into the catalog by the next push or scan, and the component comes from it as usual, but the intake doesn’t record it as ingested.
If Componecat can’t tell, because the merge request can’t be found or the provider refused the integration’s token, the row says so, and the merge request is treated as still open.
Reopen a declined merge request
Section titled “Reopen a declined merge request”A merge request that someone closes without merging is recorded, and nothing opens it again by
itself: running the step again doesn’t, and neither does retrying. If you want to ask again, select
Reopen on its row. That opens a new merge request on a new branch, componecat/add-descriptor-2
for the first reopen, because the closed one keeps its branch. It’s checked and throttled like any
other, and it needs the integration’s write token, so it isn’t offered once the intake has ended.
Finish an intake
Section titled “Finish an intake”An intake is Monitoring while there’s something still to come, and moves to Completed by itself once every repository is settled: ingested, closed without merging, rejected in review, or skipped. That deletes its write tokens.
Anything that could still go somewhere keeps it in Monitoring: an open merge request, a merged file that hasn’t been read, a repository not yet decided on in review, an approved repository not yet released, and one that failed to open and can be retried.
Finish on the intake’s page ends it sooner, from Awaiting review onward. The intake becomes Completed, and its write tokens and what it read from repositories are deleted.
- Open merge requests stay open. Nothing is closed, and Componecat keeps following them, so one merged later is still read and shows as Ingested. The intake’s page keeps updating by itself while a merge request is open or merged and not yet read.
- They can no longer be kept current, with no token to write with. A merge request merged long after the intake finished can overwrite newer edits to its component, because what’s in the file replaces what’s in the catalog.
- Nothing more can be opened or reopened. A repository without a merge request still has its YAML.
If a merge request is being opened at that moment, Finish is refused so that it isn’t lost, but the rest of the batch stops right away. Try again in a moment.
Keep merge requests current
Section titled “Keep merge requests current”A merge request can stay open for a long time, and the catalog keeps changing while it does. Merging a stale file
does damage: it replaces what the catalog holds, so values edited since it was opened go back to
what the file says, and any relationship added since is removed if the file declares relationships of that kind. So while
a merge request is open, Componecat keeps its componecat.yaml up to date.
About once a minute, Componecat looks at the open merge requests whose component, declared relationships, or review decision have changed. It
also looks at each of the others about once an hour, which picks up what it can’t see as a change on the component, such as a
removed relationship or a renamed owner team. A large intake is worked through a few at a time, so a change can take a few
minutes to reach the branch. If the file would come out different from what’s on the branch, Componecat commits the new one to
componecat/add-descriptor. If it would come out the same, nothing is committed and nobody is notified. Inferred
relationships stay out of the file, as they do when it’s first opened, and a repository rejected in review
isn’t written to.
When Componecat can’t keep a merge request current, the top of the intake’s page says what that means, once, and each affected repository’s row carries the flag, with its own reason and what you can do there. Show the repository (or Show the 3 repositories, with their count) at the top sets the Merge request filter under Repositories to that flag, opens the list and takes you there. Both flags go away once the merge request is merged or closed.
| Flag | What it means | What clears it |
|---|---|---|
| Edited by someone else | Someone committed to the branch after Componecat last did, or the branch already held another file when Componecat found it. With the webhook’s push events arriving, it appears within a minute of their commit, and otherwise within the hour. Their work wins: nothing is committed to the branch, and their changes are intact. The file there may fall behind the catalog. | The branch going back to the commit Componecat left it at, or you selecting Acknowledge. |
| Can’t be kept current | Componecat can’t update this merge request, and the row says why: the write token was deleted or can’t write to the repository, the branch is gone, the component was deleted, or the repository is no longer approved. Nothing is attempted. | Fixing what the row names, such as setting a token that has access. The next look clears it and catches up. |
Acknowledge means you’ve seen the edit and Componecat should carry on from it. The commit stays, and the next time the
component differs from the file, componecat.yaml is replaced on top of that commit, including anything the person changed in
that file. Their changes to other files stay. If they should keep the file, leave the flag on, and treat what’s on the branch
as theirs to finish. A further commit on the branch flags it again.
After an intake ends
Section titled “After an intake ends”Ending an intake, whether you finish it, cancel it, or undo it, deletes its write tokens. An undo deletes them last, once it has closed what it could (see Undo an intake). Open merge requests a finish or a cancel leaves stay open, since they’re in other teams’ repositories, and Componecat can no longer update them. They’re all flagged Can’t be kept current, on the intake’s page as on each row.
This is a real gap: a merge request left open after its intake ends can still be merged, and then it overwrites newer edits and removes newer relationships. Before you end an intake, merge or close what’s open if you can. Afterward, close the ones you don’t want, or copy each one’s current YAML from its row and commit it to the branch before merging.
When something goes wrong
Section titled “When something goes wrong”- Retry failed on a step queues that step’s failed repositories again and leaves the others alone. Retry next to a repository queues only that one.
- Run again on a finished step processes the repositories that didn’t succeed, or all of them if every one succeeded. Results are updated rather than duplicated.
- Cancel intake stops it: no further step starts, and repositories not yet finished are skipped. Components it already created stay in the catalog. Its write tokens are deleted, so merge requests already open can no longer be kept current, and the confirmation says so. If a merge request is being opened at that moment, the cancel is refused so that it isn’t lost, but the rest of the batch stops right away. Try again in a moment. A paced release that is running or paused stops with the intake, and the confirmation says that too.
Past and current intakes stay listed on the Catalog Intake page. Each one’s progress names the step being worked on, or the last step that did any work, with that step’s counts. For an intake canceled part-way through a step, that’s the step it stopped in, with how many repositories it finished and how many it skipped. Failures in an earlier step are listed under it with the step’s name, such as “5 failed in Enrich with AI”.
Undo an intake
Section titled “Undo an intake”Undo intake on an intake’s page reverses it, for any intake that has started. It works on the whole intake, not on selected repositories, and it can’t be run on a draft, which has created nothing. It first lists what would be removed, and what would stay and why, so you can decide before anything happens. It says how many components go to Trash and how many relationships are removed, and shows each of them a page at a time, as it does what stays.
Confirming returns at once: the intake’s status becomes Undoing, and the undo carries on in the background, with its progress on the intake’s page. It can take a while for an intake with many open merge requests, and it carries on where it stopped if Componecat restarts: after a restart, the page says the undo stopped and when it carries on, a few minutes later. Once it’s done, the status is Undone and the page keeps the list of what stayed. Both lists of what stays, before and after, say how many components and relationships there are and show the components a page at a time, since an intake that linked many existing components keeps them all.
An undo does this, in this order:
- It stops the intake. No further step starts, and repositories not yet finished are skipped. If the intake was still running, it’s as if you’d canceled it first, so if a merge request is being opened at that moment, the undo is refused and the rest of the batch stops. Try again in a moment. While it’s undoing, the intake can’t be canceled or finished, and its write tokens can be replaced but not removed.
- Open merge requests are closed first, while its write tokens still exist. Each one is closed with its own integration’s token, and its branch stays. The page shows how many are closed, merged, still to close, and kept open. One someone merges in the meantime is recorded as merged, and keeps its component. If a token’s rate limit is reached, those closes wait for it, and waiting doesn’t count as a failure. A close that fails for another reason is tried a few more times first, five tries in all, a minute apart and then two, four, and eight minutes apart, so one whose provider keeps failing, with a server error for example, is kept open about a quarter of an hour after its first try. Until then the page counts it as still to close. A provider that’s slow to answer may still have closed it, so before trying again the undo asks the provider whether it’s closed, and never closes one twice.
- It waits for you about any it can’t close. One whose integration has no token, whose
token is refused or isn’t allowed to close it, whose integration is gone, or whose provider
keeps failing is kept open, and the page names it with the reason and a link. The undo then
waits, and removes nothing, until you choose one of these. If one of them is merged or
closed in its repository while the undo waits, the page counts it that way, and once none is
left open, Carry on lets the undo go on.
- Retry the kept-open ones, typically after you replace the write token under Merge requests. The undo tries them again, and goes on once they’re closed.
- Keep them open. The undo goes on without them, and the list of what stayed names them so you can close them in their repositories.
- Components it created go to Trash. Each delete counts as any other: outgoing webhooks report it, and it’s in the audit log under the name of the admin who started the undo (or as Catalog-intake if that admin’s account no longer exists). You can restore a component from Trash, but it comes back without the relationships the undo removed.
- Relationships it added are removed. That’s its inferred relationships and the ones approved in its review. Any other relationship on a component going to Trash goes with the component, as in any delete, unless someone declared it, in which case the component stays.
- Last, what it read from repositories and its write tokens are deleted, and the intake is Undone.
If a write token’s rate limit holds the closes back for a long time, which can mean the account is blocked rather than busy, the undo pauses and says which token it’s waiting on. It pauses at once when the provider asks for a longer wait than that in one go, and says until when. Choose Keep waiting to carry on as soon as the limit allows, or Stop waiting to keep the waiting ones open, which you can then retry or keep open as above. If the undo keeps failing for some other reason, it stops and says why. Carry on starts it again from where it stopped.
A component the intake created stays, with the reason listed, if any of these is true:
| Reason | What it means |
|---|---|
| Someone edited a field | A person changed a value, and the list names the fields. A value the intake or the AI step wrote doesn’t count. |
| A descriptor is linked | The component is synced from a componecat.yaml in its repository. |
| Its merge request was merged | The repository has adopted the file. |
| Someone declared a relationship | A person or a descriptor declared a relationship on it, other than one approved in this intake’s review. |
| An integration manages it | Release it from the integration first if you want it gone. |
| A relationship blocks the delete | A relationship kind’s delete policy refuses it, and the undo isn’t removing that relationship. |
A few other things stay too:
- A component the intake only linked. Undo never deletes it, though relationships the intake added to it are removed. Values the AI step filled in on it stay.
- A relationship the intake proposed that isn’t its own. One that someone added by hand, even after the intake proposed it, that a descriptor now declares, or that another source had inferred first.
A relationship approved in this review is removed even if a component at either end stays, and it’s never the reason a component stays. Interfaces and documentation someone added to a component don’t keep it, and they go to Trash with it. The list marks the components that have them, so check it before you confirm.
Once an intake is undoing or undone, the page no longer offers Undo intake, and running it again on an undone intake changes nothing. To have merge requests again for the same repositories, start a new intake over them: a merge request this undo closed doesn’t keep a repository from getting a fresh one, while one a team closed still does.
Use the descriptors yourself
Section titled “Use the descriptors yourself”A component created by an intake lives only in the catalog until its repository has a
componecat.yaml. You can get that file from an intake and commit
it yourself, with no write access for Componecat, instead of opening merge requests. Once it’s on the default branch and
repository scanning is on for that integration, scanning
adopts the component it describes: it matches by kind, namespace, and name, so no second
component appears.
- Copy YAML next to a repository puts its file on the clipboard. It works for any repository that has a component, approved or not. If your browser blocks copying, for example because the page isn’t served over HTTPS or clipboard permission is denied, the YAML appears under the button, already selected, so you can copy it yourself.
- Download approved descriptors saves a zip archive with one file per approved
repository, at
<integration>/<repository full name>/componecat.yaml, so repositories with the same name on two integrations stay apart. Repositories that aren’t approved are left out.
Put each file at the root of its repository, under the name componecat.yaml.
The file holds what the catalog says now: the component’s identity, owner, fields, interfaces, documentation, and the relationships someone has declared or approved. Relationships Componecat only inferred stay out of it. Its first line points your editor at the schema for the component’s kind. Each time you copy or download, the file is rendered again from the catalog.
Committing a descriptor makes it the source of truth for that component, so what’s in the file replaces what’s in the catalog each time it’s read. Copy or download again if the component has changed since. Private interfaces are included, because leaving one out would remove it from the catalog when the file is read, so check who can read the repository before you commit a file that has any.
Some repositories can’t have a file, and the page says why:
- It has no component, for example because of a name conflict.
- Its component is managed by an integration, which can’t also be synced from a descriptor.
- Its component’s name isn’t one a descriptor can carry, because the file would be read as a different component. Rename the component, then try again.
- Its component’s kind has been retired.
An archive lists any approved repository it left out, with the reason, and still contains the others.