Add owner-gated fleet evolution

This commit is contained in:
thePR0M3TH3AN committed 2026-09-27 17:39:12 -04:00
1 parent acb4dc401d
commit d1cd79cccb
22 files changed
+888 -11

No files matched your search

+6 -1
View File
@@ -137,6 +137,7 @@ function domainFromComponent(component) {
shared_paths: [],
neighbours: [],
required_checks: [],
resources: [],
runtime: 'claude',
evidence: component.evidence,
};
@@ -162,7 +163,7 @@ function specDomain(signal, specification) {
: [`responsibilities described by ${specification.path}:${signal.line}`],
not_scope: [],
owned_paths: signal.pathReferences,
shared_paths: [], neighbours: [], required_checks: [], runtime: 'claude',
shared_paths: [], neighbours: [], required_checks: [], resources: [], runtime: 'claude',
evidence: [`${specification.path}:${signal.line}`],
design_status: signal.pathReferences.length ? 'evidence-backed' : 'needs-owner-path-review',
};
@@ -200,6 +201,7 @@ export function proposeDomains({ repository, analysis }) {
id: 'core', title: 'Core project', kind: 'development',
scope: ['initial project implementation and architecture'],
not_scope: [], owned_paths: ['**'], shared_paths: [], neighbours: [], required_checks: [],
resources: [],
runtime: 'claude',
evidence: analysis.inventory.manifests,
});
@@ -212,6 +214,7 @@ export function proposeDomains({ repository, analysis }) {
not_scope: ['implementing domain features solely to make checks pass'],
owned_paths: ['test/**', 'tests/**', 'e2e/**'], shared_paths: [], neighbours: [],
required_checks: [], evidence: graph.verificationSurfaces.slice(0, 12),
resources: [],
runtime: 'claude',
});
}
@@ -222,6 +225,7 @@ export function proposeDomains({ repository, analysis }) {
not_scope: ['feature implementation', 'deployment without configured authority'],
owned_paths: graph.operationalSurfaces.filter((path) => /deploy|release|workflow/i.test(path)).slice(0, 20),
shared_paths: [], neighbours: [], required_checks: [],
resources: [],
runtime: 'claude',
evidence: graph.operationalSurfaces.slice(0, 12),
});
@@ -333,6 +337,7 @@ export function validateApprovedProposal({ proposal, repository }) {
ids.add(domain.id);
if (!domain.scope?.length) problems.push(`domain ${domain.id} has no scope`);
if (!Array.isArray(domain.not_scope)) problems.push(`domain ${domain.id} has no not_scope list`);
if (domain.resources !== undefined && !Array.isArray(domain.resources)) problems.push(`domain ${domain.id} has an invalid resources list`);
if (!domain.owned_paths?.length) problems.push(`domain ${domain.id} has no owned paths`);
if (domain.runtime !== undefined && (typeof domain.runtime !== 'string' || !domain.runtime.trim())) {
problems.push(`domain ${domain.id} has an invalid runtime`);
+11 -4
View File
@@ -67,7 +67,9 @@ function initialFiles({ repository, projectId, createdAt, proposal }) {
shared_paths: domain.shared_paths ?? [],
neighbours: domain.neighbours ?? [],
required_checks: domain.required_checks ?? [],
resources: domain.resources ?? [],
runtime: domain.runtime ?? 'claude',
model: domain.model ?? null,
branch: domain.branch ?? null,
worktree_name: domain.worktree_name ?? null,
})),
@@ -85,6 +87,10 @@ function initialFiles({ repository, projectId, createdAt, proposal }) {
}, ...config.domains],
};
const managerPrompt = `${promptContent(
proposal.session_manager?.prompt_source,
'# TORCH Session Manager\n\nRoute owner requests, establish ownership and priority, and keep routine coordination inside the fleet.\n',
).trimEnd()}\n\n## Fleet evolution\n\nWhen recurring work has no coherent owner, or a durable specialist would materially improve context locality, ownership clarity, or verification, use \`torch_propose_domain\` to submit an evidence-backed Fleet change. Use \`torch_list_fleet_changes\` to follow its state. Never create, approve, or activate a persistent identity yourself; owner approval and CLI activation are separate. Also recommend merge or retirement when coordination cost exceeds the value of a persistent session.\n`;
const files = new Map([
['torch.yaml', jsonYaml(config)],
['roster.yaml', jsonYaml(roster)],
@@ -94,10 +100,7 @@ function initialFiles({ repository, projectId, createdAt, proposal }) {
proposal.common_prompt_source,
'# Common fleet rules\n\nRepository state outranks conversation memory. Query ownership before crossing a domain boundary.\n',
)],
['prompts/session-manager.md', promptContent(
proposal.session_manager?.prompt_source,
'# TORCH Session Manager\n\nRoute owner requests, establish ownership and priority, and keep routine coordination inside the fleet.\n',
)],
['prompts/session-manager.md', managerPrompt],
['backlog/.gitkeep', ''],
['INSTALLATION.md', `# TORCH installation\n\nInstalled ${createdAt}. Run \`torch doctor\` before starting the fleet.\n`],
]);
@@ -119,6 +122,10 @@ function initialFiles({ repository, projectId, createdAt, proposal }) {
'',
...(domain.neighbours.length ? domain.neighbours : ['None identified.']).map((item) => `- ${item}`),
'',
'## Resources',
'',
...(domain.resources.length ? domain.resources : ['No scarce resources declared.']).map((item) => `- ${item}`),
'',
'## First move',
'',
'Query live ownership, read the assigned backlog item, and report current repository evidence to the Session Manager.',
+2 -2
View File
@@ -116,7 +116,7 @@ export function planWorktrees({ repository, parentOverride } = {}) {
};
}
function ensureTaskIgnored(root, installationId) {
export function ensureTaskIgnored(root, installationId) {
const common = git(root, ['rev-parse', '--git-common-dir']);
const commonPath = isAbsolute(common) ? common : resolve(root, common);
const excludePath = join(commonPath, 'info', 'exclude');
@@ -127,7 +127,7 @@ function ensureTaskIgnored(root, installationId) {
return { path: excludePath, added: true };
}
function removeTaskIgnore(record, installationId) {
export function removeTaskIgnore(record, installationId) {
if (!record.added || !existsSync(record.path)) return;
const marker = `# TORCH ${installationId}\n.task\n`;
const content = readFileSync(record.path, 'utf8');