Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions packages/software-factory/realm/Wiki/adjust-mortgage-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"data": {
"meta": {
"adoptsFrom": {
"name": "Wiki",
"module": "../wiki"
}
},
"type": "card",
"attributes": {
"tags": ["software-factory-brief", "adjust", "mortgage-calculator"],
"sourceCardUrl": "http://localhost:4201/catalog/04868f-mortgage-calculator/mortgage-calculator",
"content": "## Adjust the Mortgage Calculator card\n\n`sourceCardUrl` above points at the Mortgage Calculator card in the catalog.\n\n## The changes\n\nTwo things:\n\n1. **Add an extra-monthly-payment input, and show its impact on the loan.** Borrowers constantly ask: *what if I pay a bit extra toward the principal each month?* The calculator can't answer that today.\n\n2. **Restyle it to look like a 90s-era corporate insurance app.** Think the beige, boxy, all-business desktop software an insurance office ran back then \u2014 chunky bordered panels, system fonts, dense form layout, that kind of vibe. Lean into it.\n\nWork the details out yourself from how the card already behaves \u2014 it already computes the full amortization (loan amount, monthly payment, lifetime interest, and so on). Decide what fields, math, and presentation make sense, and keep everything the card already does working.\n\n## Done when\n\nSomeone can enter an extra monthly payment and see how it changes the payoff, and the calculator has that 90s corporate-insurance look.",
"cardInfo": {
"name": "Adjust Mortgage Calculator: extra-payment input + 90s insurance-app restyle",
"notes": null,
"summary": "Add an extra-monthly-payment input to the catalog Mortgage Calculator and restyle it as a 90s-era corporate insurance app \u2014 details left to the implementer.",
"cardThumbnailURL": null
}
},
"relationships": {
"relatedPages": {
"links": {
"self": null
}
},
"cardInfo.theme": {
"links": {
"self": null
}
}
}
}
}
81 changes: 81 additions & 0 deletions packages/software-factory/tests/factory-seed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ const stickyNoteBrief: FactoryBrief = {
tags: ['documents-content', 'sticky', 'note'],
};

// Mirrors realm/Wiki/adjust-mortgage-test.json: a brief that carries a
// `sourceCardUrl`, which flips seed creation into the adjust flow.
const adjustMortgageBrief: FactoryBrief = {
title: 'Adjust Mortgage Calculator',
sourceUrl:
'https://briefs.example.test/software-factory/Wiki/adjust-mortgage-test',
sourceCardUrl:
'http://localhost:4201/catalog/04868f-mortgage-calculator/mortgage-calculator',
content: [
'## Adjust the Mortgage Calculator card',
'',
'Add an extra-monthly-payment input and show its impact on the loan,',
'and restyle it to look like a 90s-era corporate insurance app.',
].join('\n'),
contentSummary:
'Add an extra-monthly-payment input to the catalog Mortgage Calculator and restyle it as a 90s-era corporate insurance app.',
tags: ['software-factory-brief', 'adjust', 'mortgage-calculator'],
};

test.use({ realmDir: bootstrapTargetDir });
test.use({ realmServerMode: 'isolated' });

Expand Down Expand Up @@ -166,6 +185,68 @@ test('creates bootstrap seed issue in a live realm', async ({ realm }) => {
}
});

test('creates an adjust-flavored bootstrap seed when the brief carries a sourceCardUrl', async ({
realm,
}) => {
let { client, cleanup, workspaceDir, seedOptions } = buildSeedContext(realm);

try {
let result = await createSeedIssue(adjustMortgageBrief, seedOptions);

expect(result.issueId).toBe('Issues/bootstrap-seed');
expect(result.status).toBe('created');

let syncResult = await client.sync(realm.realmURL.href, workspaceDir, {
preferLocal: true,
});
expect(syncResult.hasError).toBe(false);
let indexed = await client.waitForFile(
realm.realmURL.href,
'Issues/bootstrap-seed.json',
{
pollMs: 300,
timeoutMs: 30_000,
},
);
expect(indexed).toBe(true);

let issueResponse = await client.authedFetch(
realm.cardURL('Issues/bootstrap-seed'),
{ headers: { Accept: SupportedMimeType.CardSource } },
);
expect(issueResponse.ok).toBe(true);

let issueJson = (await issueResponse.json()) as {
data: {
attributes: { issueType: string; summary: string; description: string };
};
};

// Still a bootstrap issue — the adjust/greenfield fork lives in the
// seed's instructions, not in its issueType.
expect(issueJson.data.attributes.issueType).toBe('bootstrap');

// Adjust-specific summary (greenfield is "Process brief and create
// project artifacts").
expect(issueJson.data.attributes.summary).toBe(
'Seed the source card and create adjustment issues',
);

// The seed instructions are the adjust flavor and carry the source card
// through to the agent.
let { description } = issueJson.data.attributes;
expect(description).toContain('Mode: ADJUST EXISTING CARD');
expect(description).toContain(
`**Source card to adjust:** ${adjustMortgageBrief.sourceCardUrl}`,
);
expect(description).toContain(
`boxel realm ingest-card "${adjustMortgageBrief.sourceCardUrl}"`,
);
} finally {
cleanup();
}
});

test('seed issue creation is idempotent', async ({ realm }) => {
let { cleanup, seedOptions } = buildSeedContext(realm);

Expand Down