Active work
Iemand met coding agents draait meerdere sessies tegelijk, en een team vermenigvuldigt dat. De agents van twee mensen kunnen hetzelfde bouwen op twee branches die geen enkel bestand delen, zodat geen mergeconflict het ooit laat zien. Active work maakt van de pushes die fremforge toch al ontvangt een beeld van het lopende werk, en waarschuwt wanneer twee stukken werk op elkaar lijken.
Geen enkele agent hoeft mee te werken. Active work leest wat de forge al ziet: branches, pushes, pull requests en de trailers die agents al schrijven.
Wat het vastlegt
Wordt een branch voor het eerst gepusht, dan maakt fremforge een item voor lopend werk aan en werkt het bij bij elke push en elke wijziging van de pull request:
| Veld | Komt van |
|---|---|
| Persoon | Wie pushte, of de auteur van de pull request. Agents handelen namens hun persoon, dus wordt altijd de persoon genoemd. |
| Agentsessies | Links Claude-Session: (of elke <Tool>-Session:) en trailers Co-Authored-By: in commitberichten en de body van de pull request. Alleen de naam van de co-auteur wordt bewaard, nooit het e-mailadres. |
| Titel en bedoeling | De titel van de pull request, het begin van de beschrijving, de branchnaam en de onderwerpregels van de commits. |
| Gebieden | De mappen op het hoogste niveau die de branch wijzigt, of de module onder mappen als apps/, packages/ of services/ (apps/api, packages/db). |
Een item is actief zolang er binnen 7 dagen naartoe wordt gepusht. Het is klaar wanneer de pull request wordt gemerged of de branch wordt verwijderd, en verlaten wanneer de pull request zonder merge wordt gesloten. Pushes naar de standaardbranch, en branches die door de eigen bots van fremforge of door Renovate zijn gepusht, worden niet vastgelegd.
Hoe werk wordt vergeleken
Elke keer dat een item verandert, vergelijkt fremforge het met de andere actieve items in dezelfde repository. Twee items worden gemeld als mogelijk hetzelfde werk wanneer hun titels de meeste betekenisvolle woorden delen (bijvoorbeeld “Rate limit the login endpoint” en “Add rate limiting to the login API”), of wanneer hun bredere tekst sterk overlapt en ze hetzelfde gebied raken.
De vergelijking is tekstmatching in de eigen database van fremforge. Er wordt geen AI-model gebruikt en er verlaat geen code of tekst fremforge, tenzij een eigenaar van de organisatie ook semantisch vergelijken met je eigen model aanzet, dat standaard uitstaat. Woorden die elke wijziging gebruikt (“fix”, “update”, “add”) en woorden die veel voorkomen in het werk van de repository zelf, worden genegeerd, zodat twee wijzigingen niet aan elkaar worden gekoppeld alleen omdat ze allebei over hetzelfde product gaan.
Over repository’s heen
Werk wordt ook vergeleken met lopend werk in de andere repository’s van de organisatie, alleen op titel en bedoeling (een gebied zoals apps/api in de ene repository zegt niets over een andere). Dezelfde regels voor paren die geen nieuws zijn, gelden ook hier. Een overeenkomst over repository’s heen:
- wordt alleen getoond aan mensen die beide repository’s kunnen lezen: op de pagina Active work, in de mail, op de antwoordpagina en in de leestools;
- krijgt nooit een opmerking op een pull request en wordt niet op de gebeurtenisfeed verstuurd, omdat de opmerking zichtbaar is voor iedereen die één van de repository’s kan lezen;
- noemt het andere werk als
org/repo#12, oforg/repo:branchvoor een branch zonder pull request.
Semantisch vergelijken met je eigen model
Tekstmatching vindt werk dat hetzelfde zegt in dezelfde woorden. Semantisch vergelijken vraagt daarnaast de eigen AI-provider van je organisatie of twee stukken lopend werk hetzelfde werk zijn wanneer hun woorden verschillen (“SSO button on the sign-in page” en “Log in with the company account”). Het is optioneel en staat standaard uit, en het vult tekstmatching alleen aan:
- het kan een overeenkomst toevoegen die de tekst niet vond, of de score verhogen van een die hij wel vond. Het verlaagt of wist nooit een overeenkomst;
- het vergelijkt alleen werk in dezelfde repository, nooit over repository’s heen;
- mislukt een aanroep, is hij traag of zou hij je limieten overschrijden, dan gaat het vergelijken gewoon door met alleen tekst.
Je eigen provider, en verder niets
Semantisch vergelijken gebruikt een AI-provider die je organisatie heeft ingesteld onder AI-integraties, met je eigen sleutel en je eigen contract met die leverancier. fremforge heeft er zelf geen sleutel voor en geen terugvaloptie: zonder je provider is er geen semantisch vergelijken. De leverancier is jouw verwerker, geen subverwerker van fremverk (DPA-bijlage B §B.8).
Aanroepen verlaten fremforge alleen via een beperkte uitgaande proxy, en alleen naar de host van je provider zoals die is gecontroleerd en vastgepind toen je de provider opsloeg. Verandert het adres van de provider naar een andere host, dan schakelt semantisch vergelijken zichzelf uit tot een eigenaar het weer aanzet, en dat wordt in het auditlog vastgelegd.
Wat wordt verstuurd
Wanneer een stuk werk, of het andere werk waarmee het wordt vergeleken, is veranderd (en hoogstens eens per 10 minuten per stuk werk), stuurt fremforge je provider voor dat stuk werk en voor hoogstens 15 andere stukken lopend werk in dezelfde repository:
| Verstuurd | Niet verstuurd |
|---|---|
De titel, zonder voorvoegsel type(scope): | Code, diffs en bestandsinhoud |
| Het begin van de beschrijving van de pull request (tot 600 tekens) | Bestandspaden onder de map op het hoogste niveau |
De branchnaam, zonder een <login>/ aan het begin | Onderwerpregels van commits, nummers van pull requests, links naar agentsessies |
| De mappen op het hoogste niveau die de branch wijzigt | Iemands login, naam of e-mailadres, behalve wat mensen zelf in een titel of beschrijving schreven |
De andere stukken werk worden in het verzoek aangeduid als c1, c2, …, nooit met een id of een persoon.
Een veld waarin een credential staat, wordt weggelaten. Voordat er iets wordt verstuurd, wordt elk veld gescand met de eigen regels van de push-bescherming: de standaardregels van gitleaks voor de versie die fremforge draait, plus de eigen regels van fremforge (frem.sh-tokens, Europese cloudproviders, connection strings, wachtwoorden in configuratie). Een veld dat matcht, wordt uit het verzoek gehaald, niet gemaskeerd. Kan de scan niet draaien, dan wordt er helemaal niets verstuurd.
Wat wordt bewaard
fremforge bewaart het verzoek en het antwoord van de provider niet. Per paar stukken werk bewaart het alleen of het antwoord als hetzelfde werk telde en een betrouwbaarheidsscore, plus een eenrichtingshash van het verzoek zodat hetzelfde verzoek niet twee keer wordt verstuurd. Die worden samen met het werk en zijn overeenkomsten verwijderd: 90 dagen nadat het werk klaar was (pull request gemerged of gesloten, of branch verwijderd), of 30 dagen nadat Active work voor de organisatie is uitgezet. Elke aanroep wordt vastgelegd zoals de aanroep van elke AI-functie (functie, provider, aantallen tokens, latency), nooit de inhoud.
Eerst schaduw, dan meldingen
Semantisch vergelijken begint in schaduwmodus: oordelen worden vastgelegd en gemeten, en niemand krijgt er iets over te horen. Op basis van die oordelen worden drempels ingesteld voordat overeenkomsten die het vindt, worden getoond. Zodra het meldt, zegt een opmerking op een pull request of een mail over een overeenkomst die semantisch vergelijken vond of bevestigde dat ook, en noemt die de AI-leverancier en het model dat antwoordde.
Limieten
- Hoogstens één aanroep per stuk werk per 10 minuten, en alleen als wat zou worden verstuurd, is veranderd.
- Hoogstens 30 aanroepen per organisatie per 10 minuten en 500 per dag, bovenop de AI-uitgavenlimiet van je organisatie.
- Vijf mislukte aanroepen op rij pauzeren semantisch vergelijken voor de organisatie 15 minuten lang (auditactie
active_work.semantic.paused).
Semantisch vergelijken aanzetten
Een eigenaar van de organisatie zet het aan onder Organisatiebeheer → AI-integraties → Active work: semantisch vergelijken. De schakelaar weigert tot:
- Active work aanstaat voor de organisatie (Aanzetten);
- de organisatie een eigen AI-provider heeft;
- die provider een gecontroleerde, vastgepinde host heeft (sla de provider opnieuw op als hij vóór 26 oktober 2026 is toegevoegd en de schakelaar daarom vraagt).
Aan- of uitzetten wordt in het auditlog vastgelegd als active_work.semantic.enabled of active_work.semantic.disabled, met de persoon, de provider en de vastgepinde host. Deze functie testen wordt voor semantisch vergelijken niet aangeboden: het verstuurt alleen de tekst van lopend werk. Het wordt alleen in de console aangezet; de REST-API configureert het niet.
Markeer je contracten
Sommige bestanden zijn beloftes waarop ander werk bouwt: een API-specificatie, databasemigraties, gedeelde types. Markeer ze in .fremforge/contracts op de standaardbranch van de repository, één patroon per regel:
# API and schema contracts
apps/api/openapi.yaml
packages/db/migrations/**
proto/**/*.proto* matcht binnen één map, ** over mappen heen, en een regel die op / eindigt, dekt alles daaronder. # begint een opmerking. Zonder het bestand wordt niets als contract behandeld.
Wijzigt een merge naar de standaardbranch een contractbestand, dan krijgt elk stuk lopend werk in hetzelfde gebied dat vóór de wijziging begon, een onderdeel Contract changed in zijn Active work-opmerking, met het bestand en de merge. what_changed_since en list_active_work tonen het ook. Er wordt niets geblokkeerd: het is een herinnering om te rebasen en opnieuw te controleren. De registratie van wie de wijziging mergede, wordt 90 dagen bewaard.
Echte conflicten: een proefmerge
Twee branches die geen enkel idee delen, kunnen toch in dezelfde bestanden botsen. Verandert een stuk werk, dan doet fremforge binnen Forgejo een proefmerge met het andere open werk dat hetzelfde gebied raakt (of dat op hetzelfde werk lijkt), head tegen head. De proefmerge schrijft niets in de repository en verplaatst geen branch.
Conflicteren de twee heads, dan toont de Active work-opmerking van beide pull requests het andere werk en de conflicterende bestanden, voordat een van beide is gemerged. Wie als tweede merget, moet het oplossen, dus spreek af wie eerst gaat, of rebase nu op het andere werk. Beweegt een van beide en mergen ze weer schoon, of is een van beide klaar, dan verdwijnt het conflict uit de opmerking. list_active_work geeft ook de open conflicten terug (conflicts).
Elk paar wordt één keer per paar heads gemerged, hoogstens 10 keer per minuut per repository, en alleen voor repository’s kleiner dan 2 GiB. Is de proefmerge niet beschikbaar, dan is er gewoon geen conflictsignaal; er wordt nooit iets geblokkeerd.
Paren die geen nieuws zijn
Sommige paren lijken op hetzelfde werk, maar zijn voor niemand nieuws. Ze verschijnen met een label op de pagina Active work, en niemand krijgt een mail of een waarschuwing op de pull request:
| Label | Wanneer |
|---|---|
| Terugdraaien voorbereid | Beide zijn van jou en een ervan draait je wijziging terug: een branch revert/ of rollback/, of een titel of nieuwste commit die begint met revert(, revert: of Revert ". |
| Dezelfde sessie | Beide hebben dezelfde agentsessie-trailer (Claude-Session: of een andere <Tool>-Session:): het eigen werk van één sessie. |
| Hoort erbij | Beide zijn van jou en het ene noemt het andere: zijn pull request (#12, org/repo#12 of een link ernaartoe, in de beschrijving) of zijn branchnaam (in de titel of het begin van de beschrijving). |
| Bijbehorende repository | Twee repository’s, waarvan er één documentatie, juridische tekst of runbooks bevat: een repository met de naam docs, documentation, legal of runbooks, een naam die eindigt op -docs, of een repository met het Forgejo-topic docs, documentation, legal of runbooks. De documentatie bij een functie is geen tweede functie. |
| Mogelijk verwant | Twee repository’s, geen gemeenschappelijke map en een score onder 0,85. Over repository’s heen kunnen alleen de woorden overeenkomen, en veelvoorkomende woorden komen te makkelijk overeen. |
| Gestapeld | De ene branch bevat de head-commit van de andere: hij is erop gebaseerd. |
| Dezelfde wijziging | Beide branches hebben commits die nog niet op de standaardbranch staan: beide zijn op dezelfde featurebranch gebaseerd. |
Elk ander paar van twee verschillende mensen wordt gemeld, ook als een van hen het werk van de ander noemt: dat laat zien dat één van jullie het weet, niet allebei. Wil je een repository als documentatie markeren zonder hem te hernoemen, geef hem dan een van die topics onder zijn Instellingen.
Over een overeenkomst wordt ongeveer drie minuten na het vinden gemaild, zodat een agentsessie-trailer die pas met de beschrijving van de pull request binnenkomt, het paar eerst nog als het eigen werk van één sessie kan markeren.
Levert één wijziging tegelijk meerdere nieuwe overeenkomsten voor je op, dan krijg je één mail met een lijst, elk met een link Antwoorden, niet één mail per paar.
De opmerking op de pull request
Wordt een overeenkomst gevonden, dan krijgt elke betrokken pull request één opmerking van fremforge-bot:
- Die noemt het andere werk: de pull request of branch, de persoon, en de woorden en gebieden die ze delen.
- Die wordt ter plekke bewerkt wanneer de overeenkomsten veranderen en nooit herhaald. Wordt het andere werk gemerged of gesloten, dan zegt de opmerking dat er geen overlap meer is.
- Tekst uit het andere werk wordt als platte code getoond, nooit als links of vermeldingen, en is gemarkeerd als gegevens. Een agent die de pull request leest, leest het als informatie, niet als instructies.
De opmerking blokkeert nooit iets. Is het hetzelfde werk, spreek dan met de ander af wie verdergaat.
Mail aan beide mensen
Beide mensen krijgen per overeenkomst één mail, in hun eigen taal, met het andere werk, de persoon, en de woorden en gebieden die ze delen, plus een link naar de andere pull request of branch. Zijn beide kanten twee van je eigen sessies, dan krijg je één mail die dat zegt. Iedereen kan Active work-mail uitzetten in zijn meldingsinstellingen; een eigenaar van de organisatie kan mail voor de hele organisatie uitzetten (email_notify). Niemand wiens mailvoorkeur in Forgejo op “disabled” staat, krijgt mail.
Een overeenkomst beantwoorden
Elk van beide mensen kan zeggen wat een overeenkomst is:
| Antwoord | Betekent | Wat er gebeurt |
|---|---|---|
Niet hetzelfde werk (different) | Vals alarm. | De overeenkomst verdwijnt direct uit beide opmerkingen op de pull requests, de pagina en de leestools, en blijft afgewezen als het werk later verandert. Telt mee in hoe vaak Active work het mis heeft. |
Hetzelfde werk, we voegen het samen (same) | Jullie voegen samen. Geef eventueel aan wiens werk doorgaat. | Beide opmerkingen tonen “Same work, joining” en wie doorgaat. |
Het werk verdelen (split) | Jullie verdelen het werk. Zeg wie het gedeelde deel voortzet. | Beide opmerkingen tonen “Split” en wie doorgaat. |
Antwoord waar je de overeenkomst tegenkomt:
- Op de pull request: de link Antwoorden in de opmerking opent de antwoordpagina (aanmelden vereist).
- In de mail: dezelfde pagina, via Answer here. De link openen verandert niets; alleen het opslaan van het formulier legt een antwoord vast.
- Op de pagina Active work: de link Antwoorden naast een mogelijk duplicaat, voor de twee mensen van het paar.
- Met de API:
POST /_app/api/v1/orgs/<org>/repos/<repo>/active-work/matches/<id>/responsemet{"response": "split", "continued_by": "<login>"}(findings:write, leestoegang tot de repository).GET …/matches/<id>leest één overeenkomst en het antwoord erop, enlist_active_workgeeft voor elke open overeenkomstmatch_id,responseencontinued_byterug.
Alleen de twee mensen van wie het werk is, kunnen antwoorden, nooit iemand namens hen: een token dat voor niemand handelt, krijgt no-principal, iedereen anders not-a-party. Een antwoord kan worden gewijzigd; het laatste telt. Elk antwoord wordt in het auditlog vastgelegd als active_work.match.responded, met het vorige antwoord en waar het is gegeven. Een agent kan voor zijn persoon antwoorden via de API, of via de MCP-schrijftool answer_active_work_match zodra de persoon daarmee heeft ingestemd en de organisatie schrijfacties via connectoren toestaat. Het antwoord geeft previous_response terug, het antwoord dat het verving.
Overdrachtsnotities
Werk wisselt van eigenaar: iemand anders pusht naar de branch, opent de pull request ervoor, of het werk stopt gewoon. Active work merkt beide op, en houdt wat de eerste persoon of diens agent wist bij het werk.
Wanneer fremforge een overdracht opmerkt:
- Van eigenaar gewisseld. Een push door iemand anders dan de laatste die pushte, of een pull request die is geopend door iemand anders dan de laatste die pushte. Meerdere sessies van één persoon zijn geen overdracht.
- Inactief. Een open pull request zonder push gedurende 7 dagen (eens per dag gecontroleerd). Er wordt eenmaal per inactieve periode naar gevraagd; de volgende push verandert de opmerking in “werk hervat”.
De pull request krijgt dan één overdrachtsopmerking van fremforge-bot, ter plekke bewerkt en nooit herhaald:
- wie aan wie overdroeg, of sinds wanneer het werk stilligt;
- Done: de overdrachtsnotitie als die is geschreven, anders de onderwerpregels van de commits;
- Next en Open questions uit de notitie (of een regel
Handoff:); - de links naar de agentsessies bij het werk. Een link
https://claude.ai/code/session_…wordt als link getoond; hij opent alleen voor de persoon van wie de sessie is, zodat die haar daar kan hervatten. Alle anderen werken vanuit de notities.
Alles in de opmerking wordt als platte code getoond en gemarkeerd als gegevens, net als de opmerking over overlap hierboven. Ze volgt de instelling pr_comment van de organisatie.
Schrijf de notitie als onderdeel Handoff in de beschrijving van de pull request (of in een commitbericht). Dit is het blok om aan je sjabloon voor pull requests toe te voegen (.forgejo/PULL_REQUEST_TEMPLATE.md):
## Handoff
Done:
-
Next:
-
Open questions:
- De nieuwste notitie wint: de beschrijving bewerken vervangt haar, en een commitbericht met een onderdeel Handoff vervangt haar ook. Een leeg sjabloon is geen notitie. De notitie wordt niet als bedoeling vergeleken, dus een notitie schrijven leidt nooit tot een waarschuwing over overlap. list_active_work en find_related_work geven haar terug onder written.handoff (done, next, open_questions, wie haar schreef en waar), en de overdracht zelf als handoff (changed_hands of idle, from, to, at, resumed).
Een regel voor je AGENTS.md of CLAUDE.md:
When you stop working on a pull request, or hand it to someone else, add or update the "## Handoff" section of its description: Done, Next, Open questions. When you continue someone else's pull request, read written.handoff from list_active_work first.Live, op de gebeurtenisfeed
Elke nieuwe overeenkomst is ook een gebeurtenis activework.warning op de gebeurtenisfeed, zodat een agent die de feed al volgt ervan hoort zonder te pollen.
Stilliggend werk: een dagelijkse herinnering
Agentsessies eindigen en laten branches en concept-pull-requests achter. Eens per dag stuurt fremforge iedereen één mail met hun open pull requests en branches zonder push in 14 dagen, inclusief het werk dat hun agents voor hen deden. Voor elk stuk werk zijn er drie antwoorden:
| Antwoord | Wat er gebeurt |
|---|---|
| Doorgaan | 7, 14 of 30 dagen geen herinnering erover. Een push zet het sowieso terug. |
| Overdragen | Noem de volgende persoon (die schrijftoegang tot de repository nodig heeft) en voeg desgewenst een notitie toe. Het werk wordt van die persoon en staat met je notitie in diens volgende overzicht. Op een pull request komt de notitie ook in de overdrachtsopmerking, ter plekke bewerkt. |
| Sluiten | Sluit de pull request (de branch blijft bestaan, dus hij kan worden heropend) of verwijdert, bij een branch zonder pull request, de branch. |
Elk item in de mail linkt naar zijn antwoordpagina (/_app/settings/work/idle/<id>). Je moet aangemeld zijn: alleen de persoon van wie het werk is, of een eigenaar van de organisatie, kan het zien of beantwoorden, dus een doorgestuurde mail kan niemands werk sluiten. De link openen verandert niets. Eigenaren van de organisatie vinden op de pagina Active work ook een link Doorgaan, overdragen of sluiten naast stilliggend werk. Elk antwoord staat in het auditlog als active_work.idle.continue, active_work.idle.handover of active_work.idle.close, met de persoon die het gaf.
Hoe zelden de mail komt:
- hoogstens één mail per persoon per dag, nooit één per pull request;
- voor elk stuk werk komt er een herinnering na 14 dagen zonder push, nog één keer 14 dagen later als niemand antwoordde, en daarna niet meer tot iemand ernaartoe pusht;
- een pull request die op een gevraagde reviewer wacht, wordt overgeslagen: de volgende stap ligt niet bij jou;
- bots (Renovate en andere botaccounts) krijgen nooit een herinnering.
Werk dat al bestond voordat je organisatie Active work aanzette, wordt bij de eerste dagelijkse run ook meegenomen.
Iedereen kan de mail uitzetten onder Herinneringen over stilliggend werk in zijn meldingsinstellingen, of met de link om je met één klik af te melden in de mail. Elk item in een overzicht is ook een gebeurtenis work.idle op de gebeurtenisfeed, zodat de eigen agents van de persoon het kunnen zien.
Stilliggende pull requests automatisch sluiten
Een eigenaar van de organisatie kan auto_close aanzetten. Het staat standaard uit. Een pull request wordt dan automatisch gesloten als aan al deze voorwaarden is voldaan:
- geen push gedurende
auto_close_days(minstens 60, standaard 90); - een herinnering erover bleef minstens een week onbeantwoord;
- de pull request heeft geen goedkeuring, geen gevraagde reviewer en geen review die om wijzigingen vraagt.
De branch blijft bestaan, dus iedereen kan de pull request heropenen. De persoon hoort het in het overzicht van die dag, en de pull request krijgt een opmerking met de reden. Branches zonder pull request worden nooit automatisch verwijderd.
De pagina Active work
Eigenaren van de organisatie zien al het lopende werk onder Bouwen en uitrollen › Active work: één kaart per repository, werk gegroepeerd per gebied, de agentsessies van elke persoon, en elk mogelijk duplicaat met naam en link en het antwoord erop. De schakelaar voor de organisatie staat op dezelfde pagina.
Wie er nu werkt (aanwezigheid)
Werk verschijnt hier bij de eerste push. Aanwezigheid laat het eerder zien: wanneer de AI-assistent van iemand via de MCP-server in een repository werkt (daar bestanden, pull requests of Active work leest), zien mensen die die repository kunnen lezen dat die persoon er nu werkt.
- Wat wordt getoond: alleen logins. “Werkt hier nu: alice, bob” op de kaart van de repository, een kaart voor repository’s waar iemand werkt en nog niets is gepusht, en
working_nowinlist_active_work. - Wat wordt bewaard: één regel per persoon en repository, overschreven bij elke aanroep en verdwenen 60 minuten na de laatste aanroep van de persoon. Geen geschiedenis, geen aantallen en er worden geen tijden getoond. Aanwezigheid is geen maat voor iemands activiteit.
- Alleen een geslaagde aanroep telt: een repository noemen die de persoon niet kan lezen, legt niets vast, en een API-token dat voor geen enkele persoon handelt, telt nooit mee.
- Wie het ziet: mensen die de repository kunnen lezen: de eigenaren en auditors van de organisatie op de pagina Active work, en iedereen met leestoegang via
list_active_work. - Uitzetten: een eigenaar van de organisatie met de instelling Tonen wie er nu in een repository werkt op deze pagina (of
presence: falsein de settings-API); iedereen voor zichzelf met Laten zien dat ik werk in zijn meldingsinstellingen. Elk van beide verwijdert de aanwezigheid direct.
Status: beschikbaar voor elke organisatie. Een organisatie waarin Active work uitstaat, de standaard, legt geen aanwezigheid vast en toont er geen.
Een concept-pull-request bij de eerste push
Werk wordt vanaf de eerste push vergeleken, maar een branch zonder pull request zie je makkelijk over het hoofd. Staat Concept-pull-request bij de eerste push aan, dan opent fremforge, wanneer iemand een nieuwe branch pusht, er direct een concept-pull-request voor, namens die persoon: het werk is zichtbaar op de forge, op de pagina Active work en voor ieders agents voordat iemand anders aan hetzelfde begint.
- Standaard aan voor organisaties die op of na 12 november 2026 zijn aangemaakt, uit voor oudere. Een eigenaar van de organisatie zet het aan of uit onder Bouwen en uitrollen › Active work (of
auto_draft_prin de settings-API). Iedereen kan het voor zichzelf nog uitzetten onder Concept-pull-request bij mijn eerste push in zijn meldingsinstellingen. - De pull request is van de persoon. Hij wordt op diens naam geopend met een titel
WIP:, de onderwerpregel van de eerste commit en een korte beschrijving die zegt hoe je dit uitzet. Hij blijft een concept en kan dus niet worden gemerged tot de persoonWIP:weghaalt en hem gereed markeert. Er wordt nooit iets voor hen gemerged of ingeschakeld. - De CI ervan wacht tot hij gereed is. Zolang de titel met
WIP:begint, draaien depull_request-workflows van het concept niet, dus een concept kost geen runnerminuten. Markeert de persoon hem als gereed (haaltWIP:weg in de web-UI, door de titel te bewerken, of via de API), dan draaien de controles voor de huidige head-commit, zodat de vereiste controles altijd bestaan voordat hij kan worden gemerged. Wil je ze eerder draaien, dan drukt iemand met schrijftoegang op Controles uitvoeren op de pull request (of roeptPOST /api/v1/repos/{owner}/{repo}/pulls/{index}/fremforge/run-checksaan): één keer per head-commit, en een tweede verzoek voor dezelfde commit antwoordt met409. Push-workflows en de eigen scans van fremforge op pull requests (secrets, licenties, beveiliging) draaien gewoon. Alleen de concepten die fremforge opent, worden geraakt: Forgejo legt dat vast wanneer het concept wordt geopend via het ene platformaccount dat ze kan openen, en niets wat in een titel of beschrijving staat, kan er een maken of ongedaan maken. Een pull request die je zelf alsWIP:markeert, draait CI zoals altijd, net als elke pull request vanuit een fork. Draaien de controles bij gereed of bij Controles uitvoeren, dan draaien ze als de persoon van wie het concept is, zodat goedkeuringsregels voor die persoon gelden, niet voor wie op de knop drukte. - Alleen de eigen nieuwe branch, één keer. Een push naar een bestaande branch, een branch die al een pull request heeft, bots, deploysleutels en Forgejo Actions krijgen er nooit een. Hoogstens 10 per minuut per organisatie op elke api-instantie.
- Hoe het gebeurt, en wat het begrenst. fremforge opent de pull request via het
Sudo-mechanisme van Forgejo met één apart platformaccount waarvan het token niets anders kan: de scopewrite:fremforge-draft-prlaat het een work-in-progress-concept openen vanaf een branch van dezelfde repository, namens een actieve persoon met schrijftoegang, en elk ander verzoek ermee weigert Forgejo zelf. Elk concept wordt in het auditlog vastgelegd alsactive_work.draft_pr.opened, met de persoon als actor.
Vraag het voordat je begint: tools voor agents
Agents maken Active work beter, maar zijn nooit vereist. Een regel Handoff: in een commitbericht of de beschrijving van een pull request wordt bij het werk bewaard als notitie voor de volgende persoon of sessie (zie Overdrachtsnotities). Drie tools met alleen leestoegang, beschikbaar in de MCP-server van fremforge en als REST-endpoints, laten een agent controleren voordat hij begint:
| MCP-tool | REST | Antwoordt |
|---|---|---|
list_active_work | GET /_app/api/v1/orgs/<org>/repos/<repo>/active-work | Wie nu wat bouwt in deze repository, per gebied (?area=apps/api), met de open overeenkomsten. Items zonder push in 7 dagen worden weggelaten, tenzij include_idle=true. |
what_changed_since | GET /_app/api/v1/orgs/<org>/repos/<repo>/active-work/changes?item=… (of branch=, areas=; since= of cursor=) | Het controlepunt midden in het werk: wat er onder een stuk werk is bewogen sinds de eerste push, een tijdstip, of de cursor van de laatste aanroep. Pull requests die in de standaardbranch zijn gemerged en dezelfde gebieden raken, met de bestanden; wijzigingen in de bestanden die de repository als contracten markeert in dezelfde gebieden; nieuwe overeenkomsten; en nieuw werk van anderen in dezelfde gebieden. |
find_related_work | GET /_app/api/v1/orgs/<org>/repos/<repo>/active-work/related?description=…&paths=… | Lopend werk dat lijkt op een beschrijving van werk dat nog niet is begonnen, of dat dezelfde gebieden raakt. likely_same_work is true als de vergelijking hierboven het zou melden. |
list_active_work geeft ook working_now terug: de logins van mensen die nu in de repository werken (zie aanwezigheid).
Alle drie vereisen findings:read en leestoegang tot de repository. Tekst die mensen en agents schreven (titels, branchnamen, bedoeling, onderwerpregels van commits, sessiegegevens, overdrachtsnotities) wordt alleen teruggegeven binnen een object written, met written_by en at ernaast, en elk antwoord bevat een melding dat het gegevens zijn, nooit instructies.
Meld het aan voordat je pusht. In de console vraagt Bouwen en uitrollen › Active work › Werk starten (of /_app/settings/active-work/start) om de repository, een titel en optioneel de bedoeling, gebieden en branch, en toont daarna de branch die je moet aanmaken en werk dat verwant lijkt. Met de CLI:
fremforge work start acme/web --title="Rate limit the login endpoint" --areas=apps/api
fremforge work list acme/web --area=apps/apiEr wordt niets gereserveerd en niets geblokkeerd: werk aanmelden maakt het alleen eerder zichtbaar. Vanuit een agent legt start_work (POST /_app/api/v1/orgs/<org>/repos/<repo>/active-work/start, findings:write en schrijftoegang tot de repository) je werk vast voordat er iets is gepusht: een title, je intent, en optioneel de areas en de branch. Zonder branch stelt het er een voor, zoals alice/rate-limit-the-login-api. Het werk wordt direct vergeleken, dus wie al met hetzelfde bezig is, hoort het volgens de instellingen van de organisatie, en het antwoord noemt het verwante werk. Push naar de branch die het noemt: de eerste push werkt hetzelfde item bij. Lopend werk van iemand anders op die branch wordt geweigerd (409). Via MCP is start_work een schrijftool: je connector heeft er jouw toestemming voor nodig, en de organisatie moet schrijfacties via connectoren toestaan.
Een regel voor je AGENTS.md of CLAUDE.md:
Before starting work in a repository, call find_related_work with a one-sentence description and the paths you expect to change. If an item has likely_same_work, stop and tell the person before building.
At each push, call what_changed_since for your branch with the cursor from the last call. If a migration or shared contract you depend on changed, rebase and re-check before building further.Wie het kan zien
De opmerking op de pull request noemt alleen werk in dezelfde repository, dus ze toont ander werk alleen aan mensen die die repository al kunnen lezen. Een overeenkomst over repository’s heen wordt alleen getoond aan mensen die beide kunnen lezen. Privérepository’s blijven binnen de organisatie privé.
Aanzetten
Eigenaren van de organisatie zetten Active work voor de organisatie aan met de API:
curl -X PUT https://frem.sh/_app/api/v1/orgs/<org>/active-work/settings \
-H "Authorization: Bearer $FREMFORGE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'| Instelling | Standaard | Betekenis |
|---|---|---|
enabled | false | Lopend werk vastleggen en vergelijken. |
pr_comment | true | Een opmerking plaatsen op de pull requests die bij een overeenkomst horen. |
email_notify | true | Beide mensen mailen over een overeenkomst. |
idle_nudge | true | Iedereen een dagelijks overzicht sturen van zijn stilliggende werk. |
auto_close | false | Stilliggende pull requests automatisch sluiten, na een onbeantwoorde herinnering en nooit met een goedkeuring of een open review. |
auto_close_days | 90 | Hoe lang een pull request zonder push moet zijn voordat auto_close hem sluit: 60 tot 365. |
presence | true | Tonen wie er nu in een repository werkt (aanwezigheid). |
auto_draft_pr | false | Een concept-pull-request bij de eerste push van een nieuwe branch openen, namens de persoon die pushte. |
Voor het lezen van de instellingen is policy:read nodig, voor het wijzigen policy:write. Elke wijziging wordt in het auditlog vastgelegd als active_work.settings.updated, met de persoon die haar maakte.
Je eigen schakelaars
Iedereen heeft drie eigen schakelaars, in zijn meldingsinstellingen of via de API:
| Instelling | Standaard | Betekenis |
|---|---|---|
presence | true | Voor het hele account: anderen zien dat je nu in een repository werkt. Uitzetten verwijdert het direct. |
orgs.<org>.mail | true | Active work-mail in die organisatie. |
orgs.<org>.auto_draft | true | Een concept-pull-request bij je eerste push, waar de organisatie het aan heeft staan. |
curl https://frem.sh/_app/api/v1/users/me/settings/active-work \
-H "Authorization: Bearer $FREMFORGE_TOKEN"
curl -X PUT https://frem.sh/_app/api/v1/users/me/settings/active-work \
-H "Authorization: Bearer $FREMFORGE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"presence": false, "orgs": {"acme": {"mail": false}}}'Deze instellingen zijn persoonlijk, dus ze vereisen een credential met jouw identiteit: het token van fremforge auth login, je bench, of een AI-connector (alleen lezen, als de tool get_my_settings). Een API-token van een organisatie wordt geweigerd met user-identity-required. Lezen vereist orgs:read, wijzigen orgs:write. Alleen organisaties waarvan je nu lid bent, worden getoond of kunnen worden gewijzigd (namen worden zonder onderscheid tussen hoofd- en kleine letters vergeleken), en een AI-connector ziet geen organisaties waarvan de eigenaren AI-connectoren hebben geblokkeerd. Elke wijziging wordt in het auditlog van die organisatie vastgelegd als notifications.preference.self_updated, met jou als actor.
Alle instellingen in één keer lezen
GET /_app/api/v1/orgs/<org>/settings (orgs:read), ook de MCP-tool met alleen leestoegang get_org_settings, geeft de flow-control- en AI-instellingen van de organisatie in één antwoord terug. Wat het toont, hangt af van wie het vraagt:
- Leden zien wat voor hun eigen werk geldt: de schakelaars van Active work, welke branches merges tegenhouden (alleen in repository’s die ze kunnen lezen), en of AI-connectoren mogen lezen of handelen.
- Eigenaren en auditors zien daarnaast de instellingen voor releasetreinen, risiconiveaus en op hol geslagen CI, de volledige instellingen van Active work, en elke AI-functie met haar model en de naam en leverancier van de provider.
Het geeft nooit een providersleutel, fingerprint van een sleutel, endpointadres, promptaanvulling of token terug. Er is geen schrijfversie, niet via de API en niet in MCP.
Meten
GET /_app/api/v1/orgs/<org>/active-work/metrics?days=30 (policy:read) geeft alleen aantallen en tijdsduren terug, nooit de tekst van iemands werk:
matchesenmatches_both_notified;notify_seconds_p50ennotify_seconds_p90: de tijd van de eerste push van de tweede persoon tot het moment dat beide mensen de overeenkomst te zien krijgen (het doel is minder dan 5 minuten);false_positive_rate: het aandeel beantwoorde overeenkomsten dat als “different” is gemarkeerd;dismissed_share_of_notified: overeenkomsten beantwoord met “different” van alle overeenkomsten die beide mensen te zien kregen, beantwoord of niet (het doel is minder dan 30%), enresponse_rate;responses_by_kindenresponses_by_via(api,page,pr_comment,mail).
De pagina Active work toont dezelfde maat voor de afgelopen 30 dagen.
Zie de API-referentie voor de volledige schema’s.