Wizard uses a team members list to map GitHub users to personal HR repositories, track onboarding dates, and enforce PR time tracking rules.
The canonical file lives in the
holdex/hr-internal repository
(HR access only).
For production deployments, the file is fetched at build time via the
TEAM_MEMBERS_SOURCE environment variable and bundled into the server — it is
never committed to this repository.
For local development and preview deployments, TEAM_MEMBERS_SOURCE can be
left unset. Wizard then reads config/team-members.json from your working tree.
That file is gitignored and not in the repository — copy
config/team-members.json.example to
config/team-members.json to get started locally.
@holdex member onboard opens a PR against holdex/hr-internal automatically,
adding the new member's entry once the HR issue is created, and requests a
review from whoever ran the command. The PR body links back to the issue the
command was run from, so the reviewer has the original context. Updates to an
existing member (agreement URL, isManager, corrections, and anything else
not set at onboarding time) are still made by hand-editing the file in
holdex/hr-internal. Changes take effect on the next production deployment.
The file is a JSON object with an hr_team key and a members array. Each
entry in members follows the structure documented in
config/team-members.json.example:
{
"hr_team": "org/hr-admins",
"members": [
{
"repo": "org/hr-member-firstname-lastname",
"username": "github-username",
"issue": 1,
"salaryIssue": 2,
"agreement": "https://github.com/org/hr-member-firstname-lastname/blob/main/AGREEMENT.md",
"startDate": "2024-01-01",
"skipNoPrMergeReminder": false,
"requiresTimeSubmission": true,
"isManager": false,
"billingManager": false,
"isExternal": false
}
]
}
The legacy flat-array shape (just the members list, no hr_team) is still
accepted for backward compatibility.
| Field | Required | Description |
|---|---|---|
hr_team |
No | GitHub team in org/slug format, tagged on monthly invoice comments for visibility. |
members |
Yes | Array of team member entries, documented below. |
| Field | Required | Description |
|---|---|---|
repo |
Yes | Personal HR repository in owner/repo format. |
username |
Yes | GitHub login for the team member. |
issue |
Yes | Issue number of the member's main HR issue in their HR repo. |
salaryIssue |
No | Issue number of the HR: Salary sub-issue, if created. |
agreement |
No | URL to the member's agreement document. |
startDate |
No | Agreement signing date (YYYY-MM-DD). Used for leave accrual when leave.yaml is missing. |
skipNoPrMergeReminder |
No | When true, skips the "no PRs merged yesterday" message for this member. Defaults to false. The old keys skipDailyPrReminder and skipDailyReminder are still accepted as deprecated aliases. The upcoming-leave notice is unaffected and always fires, since it's a team-coordination signal, not a nag tied to PR-merge pay. |
requiresTimeSubmission |
No | When true, the member must submit PR time even if their organization is whitelisted. See Whitelist. |
isManager |
No | When true, promotes the member to product-owner responsibilities (Goals, leave approval, restricted commands where applicable). Defaults to false. |
billingManager |
No | When true, grants access to view all contractors' invoices and team-wide Cost Breakdown reports (/stats/costs). All team members can access /stats/costs for their own data only. isManager does not grant billing access on its own. Defaults to false. |
isExternal |
No | When true, this member has no Holdex agreement and is not paid by Holdex in any form (hourly, retainer, or commission): they're listed here only for delivery-team visibility, e.g. a client-side collaborator. Excluded from monthly billing (see Monthly Billing). Defaults to false. |
isExternalMembers with isExternal: true are skipped before the monthly billing task
runs for them, so no HR: Salary sub-issue is created and they never appear
in a billing run's output. This is separate from profile.yaml's
engagement_mode, which controls billing cadence for members Holdex does
pay (retainer vs employee); isExternal controls whether Holdex has a
payment relationship with the member at all.
requiresTimeSubmission.startDate when a member's leave.yaml is not yet present.repo and issue fields.hr_team is read by the monthly billing task to tag a team on invoice comments.billingManager members can run on-demand cost allocation reports for any contributor or the whole team; see Cost Breakdown. All team members can run reports for their own data.