feat: Add MoU Drafter — AI-powered MoU & vendor-contract drafting with LaTeX/PDF output agentkit-challenge#174
Conversation
…-default select boxes with Radix custom Select components
… enhance glassmorphic card contrast
…to slate-950/deep-obsidian with 1.2% opacity grid lines
… ultra-minimal developer aesthetic
…ss background for a refined minimal aesthetic
… asterisks to required input labels
…hite-gray for a high-contrast clean layout
… POST + UX polish In-browser PDF rendering via SwiftLaTeX no longer works — their texlive2 CDN went offline and the wasm engine can't fetch its .fmt or packages. Replace it with a real pdflatex compile route used only in development, since Vercel serverless functions can't run pdflatex. In production the preview card is tree-shaken out and users go straight to Overleaf or .tex download. - Add /api/compile-latex route: spawns pdflatex in a mkdtemp dir, returns PDF bytes on success or the extracted error blocks from the log on failure. 45s timeout, 512KB body cap, ENOENT-aware error message, configurable via PDFLATEX_BIN. Guarded by NODE_ENV so it returns 503 in prod unless ENABLE_PDF_COMPILE=1. - Rewrite LatexPreview to POST to that route and show the returned PDF in an iframe via blob URL, with a structured error card + collapsible pdflatex log + Overleaf/.tex fallbacks. - Gate the preview card in page.tsx on NODE_ENV === "development" so the prod bundle ships no preview code at all. - Fix Overleaf 414 by switching from ?snip_uri=data:base64,... GET to a hidden-form POST with the snip field — no URL length cap. - Add cursor: pointer globally to buttons, links, Radix Select triggers, switches, tabs, role-based interactive elements, and date-picker icons. - Bump generation timeout from 3 to 4 minutes (orchestrate.ts + page.tsx). - Leave swiftlatex.ts in place but unused (in case the CDN ever revives); it's no longer imported anywhere. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ance cleanup-time conflict, and section 19 sub-numbering - prompts/system_0: rewrite commercialTerms schema description to enforce a single payment-deadline anchor and forbid the "within N days of invoice receipt" restatement that was conflicting with the "N days before Event Date" deadline. - prompts/system_0: extend pattern #2 (acceptance-window) guidance — event-day on-site / clean-up Deliverables must adopt the same clean-up time used in event-logistics (24-hour notation), not invent an earlier cutoff. - scripts/assemble-latex: post-process the governing-law-venue-severability clause to force \begin{enumerate}[label=\thesection.\arabic*.] so the General Provisions subclauses render as 19.1, 19.2 ... instead of restarting at 1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[kit] Add MoU Drafter — AI-powered MoU & vendor-contract drafting with LaTeX/PDF output
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a complete “MoU Drafter” kit: Next.js form UI, Zod validation, Lamatic flow/prompt wiring, deterministic LaTeX assembly scripts, sandboxed pdflatex API, Overleaf/.tex helpers, E2E test/sample output, and kit documentation/registry entries. ChangesMoU Drafter end-to-end kit
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
:robot_face: AgentKit Structural ValidationNew Contributions Detected
Check Results
🎉 All checks passed! This contribution follows the AgentKit structure. |
Suggested improvements by github actions bot
more fixes for vercel
more vercel fixes
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
kits/mou-drafter/apps/components/MoUForm.tsx (1)
303-303: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winMission briefing: Tighten type safety in form helper signatures.
The
anytypes forcontrol,register, anderrorsparameters bypass TypeScript's type checking. This reduces IDE autocomplete and compile-time safety for consumers of these helpers.🎯 Recommended type improvements
+import type { Control, FieldErrors, UseFormRegister } from "react-hook-form"; function FormSelect({ id, label, options, labels, control, error, required, info, }: { id: string; label: string; options: readonly string[]; labels: Record<string, string>; - control: any; + control: Control<MoUFormData>; error?: string; required?: boolean; info?: ReactNode; }) { function PartyFields({ prefix, title, register, control, errors, }: { prefix: "partyA" | "partyB"; title: string; - register: any; - control: any; - errors: any; + register: UseFormRegister<MoUFormData>; + control: Control<MoUFormData>; + errors: FieldErrors<MoUFormData>; }) {Also applies to: 433-433
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/components/MoUForm.tsx` at line 303, Replace the unsafe any types on form helper parameters with concrete react-hook-form types: import and use Control<T>, UseFormRegister<T>, and FieldErrors<T> (from 'react-hook-form') instead of any for the parameters named control, register, and errors; apply the generic using your form data interface (e.g., MoUFormValues) so signatures become Control<MoUFormValues>, UseFormRegister<MoUFormValues>, FieldErrors<MoUFormValues> for the helpers referenced around the symbols control/register/errors at lines ~303 and ~433 and update the helper function/type declarations to accept those typed parameters.kits/mou-drafter/apps/components/ui/form.tsx (1)
45-75:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winMission critical: Guards must fire before accessing context values.
Agent, lines 48-49 access
formContextandfieldContext?.namebefore the validation guards at lines 51-61 confirm these contexts exist. This creates a temporal dead zone whereuseFormState({ name: undefined })executes whenfieldContextis missing, and the error only fires afterward. Additionally,useFormContext()throws its own error if used outside<Form>, creating duplicate error paths.Reorder the guards to execute immediately after reading contexts, before any property access or dependent hook calls.
🎯 Proposed tactical adjustment
const useFormField = () => { const fieldContext = React.useContext(FormFieldContext) const itemContext = React.useContext(FormItemContext) - const formContext = useFormContext() - const formState = useFormState({ name: fieldContext?.name }) if (!fieldContext) { throw new Error('useFormField should be used within <FormField>') } if (!itemContext) { throw new Error('useFormField should be used within <FormItem>') } + const formContext = useFormContext() + if (!formContext) { throw new Error('useFormField should be used within <Form>') } + const formState = useFormState({ name: fieldContext.name }) const fieldState = formContext.getFieldState(fieldContext.name, formState) const { id } = itemContext🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/components/ui/form.tsx` around lines 45 - 75, The bug is that useFormState is called and fieldContext?.name is accessed before the null-check guards run in useFormField; reorder so you read contexts (React.useContext(FormFieldContext), React.useContext(FormItemContext)) and call useFormContext() as now, then immediately run the three guards that throw if fieldContext, itemContext or formContext are missing, and only after those guards call useFormState({ name: fieldContext.name }) and then call formContext.getFieldState(fieldContext.name, formState); this ensures no property access or dependent hook logic runs before the existence checks while preserving hook call order in useFormField.registry.json (1)
2738-2773:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winAgent, the registry entry is critically incomplete. Mission metadata is missing.
The
mou-drafterentry has multiple empty required fields that prevent users from discovering and deploying this kit:Critical missing fields:
description(line 2740): Empty string. Should describe the kit's purpose.Suggested value (based on PR description):
"description": "AI-powered MoU & vendor-contract drafting with LaTeX/PDF output. Converts 30-field structured form into LaTeX-typeset Memorandum of Understanding / small-vendor contract first draft (explicitly not legal advice)."
tags(line 2743): Empty array. Reduces discoverability.Suggested values (based on PR context and similar kits):
"tags": ["legal", "documents", "generative", "LaTeX", "contracts"]
author.name(line 2745): Empty. Missing attribution.Suggested value (PR author):
"author": { "name": "rohith0110" }
steps(line 2747): Empty array. Should define flow steps.Suggested value (based on PR description and lamatic.config.ts):
"steps": [ { "id": "mou-drafter", "type": "mandatory", "envKey": "MOU_DRAFTER_FLOW_ID" } ]
links(line 2748): Empty object. Should include deployment/demo/docs links.Suggested value (based on PR description):
"links": { "github": "https://github.com/Lamatic/AgentKit/tree/main/kits/mou-drafter", "deploy": "https://vercel.com/new/clone?repository-url=https://github.com/Lamatic/AgentKit&root-directory=kits%2Fmou-drafter%2Fapps&env=MOU_DRAFTER_FLOW_ID,LAMATIC_API_URL,LAMATIC_PROJECT_ID,LAMATIC_API_KEY" }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@registry.json` around lines 2738 - 2773, The registry entry for slug "mou-drafter" is missing required metadata; update the object to fill description, tags, author.name, steps, and links: set description to the provided MoU/contract drafting summary, add tags ["legal","documents","generative","LaTeX","contracts"], set author.name to "rohith0110", populate steps with a single step object { id: "mou-drafter", type: "mandatory", envKey: "MOU_DRAFTER_FLOW_ID" }, and add links including the GitHub and deploy URLs shown in the review so the kit is discoverable and deployable.kits/mou-drafter/apps/test-e2e.js (3)
199-208:⚠️ Potential issue | 🟠 Major | ⚡ Quick winCritical: Flow execution lacks timeout protection.
Agent, the production code wraps
executeFlowin a timeout guard (perorchestrate.tscontext snippet 3), but this test doesn't. If the flow hangs or the LLM is overloaded, the test will block indefinitely, potentially stalling CI/CD pipelines.Add a timeout wrapper or use a test framework timeout. Example:
const TIMEOUT_MS = 120_000; // 2 minutes function withTimeout(promise, ms, message) { return Promise.race([ promise, new Promise((_, reject) => setTimeout(() => reject(new Error(message)), ms) ) ]); } // Then in main(): try { resData = await withTimeout( client.executeFlow(FLOW_ID, flatInputs), TIMEOUT_MS, "Flow execution timed out after 2 minutes" ); } catch (err) { console.error("[FAIL] Flow call threw:", err.message); process.exit(1); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/test-e2e.js` around lines 199 - 208, The test currently awaits client.executeFlow(FLOW_ID, flatInputs) with no timeout, which can hang CI; add a timeout wrapper function (e.g., withTimeout) that races the executeFlow promise against a setTimeout rejection (suggested TIMEOUT_MS = 120_000) and replace the direct await with awaiting the timed promise; ensure the catch block for the timed await still logs the error via the existing console.error("[FAIL] Flow call threw:", ...) and exits, and reference the same client.executeFlow and FLOW_ID when invoking the timeout wrapper.
115-173: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoffAgent, the duplicated
flattenFormToTriggerlogic presents a maintenance hazard.This function duplicates the production logic from
orchestrate.ts. While this decoupling is intentional for E2E testing, it creates a synchronization risk: if the production implementation changes (e.g., new fields, different defaults), this test won't detect the divergence unless manually updated.Consider one of these strategies:
- Add a comment referencing the source implementation with a warning to keep them synchronized
- Extract the flattening logic to a shared utility that both production and test can import
- Add a separate unit test that validates the flattening contract, so this E2E test can focus on flow execution
For now, at minimum, add a comment:
// IMPORTANT: Keep synchronized with apps/actions/orchestrate.ts flattenFormToTrigger // Any changes to the production flattening logic must be mirrored here function flattenFormToTrigger(form) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/test-e2e.js` around lines 115 - 173, The test defines a local duplicate of the production flattening logic (flattenFormToTrigger) which can drift from the implementation in orchestrate.ts; add a clear top-of-function comment warning to keep it synchronized (e.g., "IMPORTANT: Keep synchronized with apps/actions/orchestrate.ts flattenFormToTrigger — mirror any changes to production logic or move to a shared util"), and as follow-ups consider extracting the flattening into a shared utility used by both the production code and this test or add a unit test to assert the flattening contract so E2E stays focused on flow execution.
29-112: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winMission briefing: Test coverage scope is limited to catering engagement.
Agent, this test only validates the catering engagement path. The mou-drafter flow supports multiple engagement types (consulting, creative, etc.), but this E2E test won't catch regressions in those alternate paths.
Consider adding test cases for other engagement types to ensure full coverage of the flow's capabilities.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/test-e2e.js` around lines 29 - 112, The E2E test only exercises the catering path by using the formData object with engagementType: "catering", so add additional test cases that submit formData variants for other engagement types (e.g., "consulting", "creative", "events") to cover alternate flows; duplicate the existing formData template in test-e2e.js and modify the engagementType and any type-specific fields (e.g., deliverables, paymentPreset, event* fields) for each variant, then call the same submission/assertion logic used for the catering case so the test suite validates all engagementType branches.kits/mou-drafter/apps/actions/orchestrate.ts (1)
130-135:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMission: keep contract titles out of server logs.
agreementTitleis still raw user-supplied legal-document metadata. In this kit it can easily contain party names or matter identifiers, so this log statement is still leaking sensitive content.🔧 Minimal redaction patch
console.log("[mou-drafter] Sending flat inputs to flow:", { - agreementTitle: flatInputs.agreementTitle, + agreementTitle_present: Boolean(flatInputs.agreementTitle), deliverables_type: typeof flatInputs.deliverables, deliverables_is_string: typeof flatInputs.deliverables === "string", partyAName: "[redacted]", partyBName: "[redacted]", });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/actions/orchestrate.ts` around lines 130 - 135, The console.log in orchestrate.ts is printing raw user-supplied agreementTitle (sensitive) — change the logging in the block that prints flatInputs (the console.log that includes agreementTitle, deliverables_type, deliverables_is_string, partyAName, partyBName) to avoid logging the raw title: instead log a redacted placeholder or a non-sensitive derivative (e.g., "REDACTED_AGREEMENT_TITLE" or a hash/length) for agreementTitle, keeping the rest of the diagnostics (deliverables_type, deliverables_is_string, partyAName, partyBName) unchanged; update the message to clearly indicate the title was redacted so future readers know it was intentional.
♻️ Duplicate comments (1)
kits/mou-drafter/apps/actions/orchestrate.ts (1)
124-139:⚠️ Potential issue | 🟠 MajorMission: route this action through the parent
lamatic.config.tscontract, not an env-only flow id.
generateMoUstill callsexecuteFlowwithprocess.env.MOU_DRAFTER_FLOW_ID, so the app can drift away from the kit’s declared step definitions. Import the parent config and resolve the MoU drafter step from there, with env only as deployment wiring if you truly need an override.As per coding guidelines,
kits/*/apps/actions/orchestrate.tsmust “import and use../../lamatic.configto read step definitions from the parent kit.” Based on learnings, the same contract applies here.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/actions/orchestrate.ts` around lines 124 - 139, The current generateMoU path directly uses process.env.MOU_DRAFTER_FLOW_ID when calling lamaticClient.executeFlow, which bypasses the parent kit's step definitions; update orchestrate.ts to import the parent lamatic.config (../../lamatic.config) and resolve the MoU drafter step ID from that config (falling back to process.env.MOU_DRAFTER_FLOW_ID only as an override), then pass the resolved step ID into lamaticClient.executeFlow along with the flattened inputs from flattenFormToTrigger; ensure references to generateMoU and the call site of lamaticClient.executeFlow are updated to use the config-derived ID so the app follows the kit’s declared contract.Sources: Coding guidelines, Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@kits/mou-drafter/apps/app/api/compile-latex/route.ts`:
- Around line 85-95: The current route swallows chmod failures on outputDir
which hides when the sandbox output mount isn’t writable; change the
chmod(outputDir, 0o777).catch(() => undefined) to propagate the error (remove
the catch) or explicitly throw a descriptive error if chmod fails so the request
fails fast; adjust the code around inputDir/outputDir setup (where chmod is
called) to log/throw a clear permission error before calling runPdflatex so
runPdflatex(inputDir, outputDir) isn’t invoked when /output isn’t writable.
In `@kits/mou-drafter/apps/lib/lamatic-client.ts`:
- Around line 19-23: The top-level instantiation export "lamaticClient = new
Lamatic(...)" causes Lamatic to validate env at module import time and can crash
imports; change to lazy initialization so env validation happens inside the call
path (e.g., create a getLamaticClient or initLamaticClient function used by
generateMoU) instead of at module scope. Specifically, remove the module-scope
"new Lamatic(...)" usage and implement a factory that checks
process.env.LAMATIC_API_URL / LAMATIC_PROJECT_ID / LAMATIC_API_KEY and either
returns a constructed Lamatic instance or throws/returns an error that
generateMoU can catch and convert into the { success: false, error } response;
update generateMoU to call this factory (not the exported lamaticClient) so
missing secrets produce a controlled failure rather than an import-time crash.
In `@kits/mou-drafter/prompts/mou-drafter_clause-generator_system.md`:
- Line 168: Update the "Numbered or bulleted lists" style example in
mou-drafter_clause-generator_system.md so the LaTeX commands in the example (the
begin{itemize}, item and end{itemize} fragments) use JSON-escaped backslashes to
match the double-escaped backslash contract described at line 16; replace the
current single-backslash example with the double-escaped form used in JSON
values, keep the one-level-only/no-nesting requirement, and ensure the change is
applied to the example text referenced in the "Numbered or bulleted lists" rule.
---
Outside diff comments:
In `@kits/mou-drafter/apps/actions/orchestrate.ts`:
- Around line 130-135: The console.log in orchestrate.ts is printing raw
user-supplied agreementTitle (sensitive) — change the logging in the block that
prints flatInputs (the console.log that includes agreementTitle,
deliverables_type, deliverables_is_string, partyAName, partyBName) to avoid
logging the raw title: instead log a redacted placeholder or a non-sensitive
derivative (e.g., "REDACTED_AGREEMENT_TITLE" or a hash/length) for
agreementTitle, keeping the rest of the diagnostics (deliverables_type,
deliverables_is_string, partyAName, partyBName) unchanged; update the message to
clearly indicate the title was redacted so future readers know it was
intentional.
In `@kits/mou-drafter/apps/components/MoUForm.tsx`:
- Line 303: Replace the unsafe any types on form helper parameters with concrete
react-hook-form types: import and use Control<T>, UseFormRegister<T>, and
FieldErrors<T> (from 'react-hook-form') instead of any for the parameters named
control, register, and errors; apply the generic using your form data interface
(e.g., MoUFormValues) so signatures become Control<MoUFormValues>,
UseFormRegister<MoUFormValues>, FieldErrors<MoUFormValues> for the helpers
referenced around the symbols control/register/errors at lines ~303 and ~433 and
update the helper function/type declarations to accept those typed parameters.
In `@kits/mou-drafter/apps/components/ui/form.tsx`:
- Around line 45-75: The bug is that useFormState is called and
fieldContext?.name is accessed before the null-check guards run in useFormField;
reorder so you read contexts (React.useContext(FormFieldContext),
React.useContext(FormItemContext)) and call useFormContext() as now, then
immediately run the three guards that throw if fieldContext, itemContext or
formContext are missing, and only after those guards call useFormState({ name:
fieldContext.name }) and then call formContext.getFieldState(fieldContext.name,
formState); this ensures no property access or dependent hook logic runs before
the existence checks while preserving hook call order in useFormField.
In `@kits/mou-drafter/apps/test-e2e.js`:
- Around line 199-208: The test currently awaits client.executeFlow(FLOW_ID,
flatInputs) with no timeout, which can hang CI; add a timeout wrapper function
(e.g., withTimeout) that races the executeFlow promise against a setTimeout
rejection (suggested TIMEOUT_MS = 120_000) and replace the direct await with
awaiting the timed promise; ensure the catch block for the timed await still
logs the error via the existing console.error("[FAIL] Flow call threw:", ...)
and exits, and reference the same client.executeFlow and FLOW_ID when invoking
the timeout wrapper.
- Around line 115-173: The test defines a local duplicate of the production
flattening logic (flattenFormToTrigger) which can drift from the implementation
in orchestrate.ts; add a clear top-of-function comment warning to keep it
synchronized (e.g., "IMPORTANT: Keep synchronized with
apps/actions/orchestrate.ts flattenFormToTrigger — mirror any changes to
production logic or move to a shared util"), and as follow-ups consider
extracting the flattening into a shared utility used by both the production code
and this test or add a unit test to assert the flattening contract so E2E stays
focused on flow execution.
- Around line 29-112: The E2E test only exercises the catering path by using the
formData object with engagementType: "catering", so add additional test cases
that submit formData variants for other engagement types (e.g., "consulting",
"creative", "events") to cover alternate flows; duplicate the existing formData
template in test-e2e.js and modify the engagementType and any type-specific
fields (e.g., deliverables, paymentPreset, event* fields) for each variant, then
call the same submission/assertion logic used for the catering case so the test
suite validates all engagementType branches.
In `@registry.json`:
- Around line 2738-2773: The registry entry for slug "mou-drafter" is missing
required metadata; update the object to fill description, tags, author.name,
steps, and links: set description to the provided MoU/contract drafting summary,
add tags ["legal","documents","generative","LaTeX","contracts"], set author.name
to "rohith0110", populate steps with a single step object { id: "mou-drafter",
type: "mandatory", envKey: "MOU_DRAFTER_FLOW_ID" }, and add links including the
GitHub and deploy URLs shown in the review so the kit is discoverable and
deployable.
---
Duplicate comments:
In `@kits/mou-drafter/apps/actions/orchestrate.ts`:
- Around line 124-139: The current generateMoU path directly uses
process.env.MOU_DRAFTER_FLOW_ID when calling lamaticClient.executeFlow, which
bypasses the parent kit's step definitions; update orchestrate.ts to import the
parent lamatic.config (../../lamatic.config) and resolve the MoU drafter step ID
from that config (falling back to process.env.MOU_DRAFTER_FLOW_ID only as an
override), then pass the resolved step ID into lamaticClient.executeFlow along
with the flattened inputs from flattenFormToTrigger; ensure references to
generateMoU and the call site of lamaticClient.executeFlow are updated to use
the config-derived ID so the app follows the kit’s declared contract.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: df946695-eddd-4d45-8dae-28d548e85e4e
⛔ Files ignored due to path filters (1)
kits/mou-drafter/apps/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (21)
kits/mou-drafter/README.mdkits/mou-drafter/agent.mdkits/mou-drafter/apps/.gitignorekits/mou-drafter/apps/actions/orchestrate.tskits/mou-drafter/apps/app/api/compile-latex/route.tskits/mou-drafter/apps/app/page.tsxkits/mou-drafter/apps/components/LatexPreview.tsxkits/mou-drafter/apps/components/MoUForm.tsxkits/mou-drafter/apps/components/ui/button.tsxkits/mou-drafter/apps/components/ui/form.tsxkits/mou-drafter/apps/components/ui/textarea.tsxkits/mou-drafter/apps/hooks/use-toast.tskits/mou-drafter/apps/lib/lamatic-client.tskits/mou-drafter/apps/next-env.d.tskits/mou-drafter/apps/next.config.mjskits/mou-drafter/apps/package.jsonkits/mou-drafter/apps/test-e2e.jskits/mou-drafter/apps/tsconfig.jsonkits/mou-drafter/prompts/mou-drafter_clause-generator_system.mdkits/mou-drafter/prompts/mou-drafter_llmnode-842_system_0.mdregistry.json
💤 Files with no reviewable changes (1)
- kits/mou-drafter/apps/tsconfig.json
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
kits/mou-drafter/apps/package.json (2)
37-37:⚠️ Potential issue | 🟠 MajorMission accepted: align this kit’s dependencies to the documented stack (or justify the deviation).
nextis pinned to16.2.6(present on npm; latest dist-tag16.2.7), but kit guidance calls for Next.js 14–15.react/react-domare pinned to19.2.6(present on npm; latest dist-tag19.2.7), but kit guidance calls for React 18.Update the versions to match the kit spec, or add a clear rationale for using Next 16 + React 19.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/package.json` at line 37, The package.json currently pins dependencies to unsupported stack versions (next, react, react-dom); either update the dependency entries for "next" to a supported 14.x or 15.x range and set "react" and "react-dom" to React 18 (e.g., ^18.2.0) to match the kit guidance, or add a short, explicit justification in the repo (package.json comment is not allowed—add a clear rationale to the PR description or README) explaining why you intentionally require Next 16 and React 19 and any compatibility workarounds; target the "next", "react", and "react-dom" identifiers when making the change so reviewers can verify alignment with the kit spec.Source: Learnings
39-40:⚠️ Potential issue | 🟡 MinorAgent handler directive: React 19.2.6 pin—compatibility OK; align with kit React 18 guidance
"react": "19.2.6", "react-dom": "19.2.6",
react@19.2.6andreact-dom@19.2.6exist on npm.- React 19.2.6 is compatible with Next.js (Next.js manages its own React wiring), so the compatibility verification concern is covered.
- Next action: if the kit briefing/policy mandates React 18, switch these pins to React 18.x or add a documented justification for intentionally using React 19 in this kit.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/package.json` around lines 39 - 40, The package.json currently pins "react" and "react-dom" to "19.2.6"; align with the kit policy by either (A) changing these dependency entries in package.json to the approved React 18.x pin (e.g., "react": "18.x", "react-dom": "18.x") or (B) add a short documented justification in the repo (e.g., README or a new DEPENDENCY_DECISIONS.md) explaining why React 19 is intentionally used for this kit and noting compatibility with Next.js; update the package.json dependencies (react/react-dom) or add the justification file accordingly and ensure the change references the same dependency keys.Source: Learnings
registry.json (1)
2738-2773:⚠️ Potential issue | 🟠 MajorFix
mou-draftermetadata parsing soregistry.jsonisn’t left blank.
registry.jsonentry forslug: "mou-drafter"is missingdescription,author,steps,links, and even reportstype: "template"—butkits/mou-drafter/lamatic.config.tsdoes containname,author,steps, andlinks.Root cause: the registry update script parses
lamatic.config.tsusing regex that expects unquoted JS keys likename:,author: { name: ..., email: ... },steps: [{ id: ..., type: ... }], andlinks: { github: ..., deploy: ... }. Your config uses JSON-style quoted keys everywhere ("name":,"id":,"type":,"github":), so the parser doesn’t match them—leaving registry fields empty (anddeploy: ""can’t be captured either).
- Update
kits/mou-drafter/lamatic.config.tsto use unquoted keys (JS object syntax) and ensurelinks.deployis a real URL (not"").- Fill
description(currently"") and set non-emptytagsif you want discoverability.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@registry.json` around lines 2738 - 2773, Update kits/mou-drafter/lamatic.config.ts so the config uses unquoted JS object keys (e.g., name:, author: { name:, email: }, steps: [{ id:, type:, ... }], links: { github:, deploy: ... }) instead of JSON-style quoted keys so the registry parser regex will match; populate description with a meaningful string, add non-empty tags, ensure author has name/email, and set links.deploy to a real URL (not an empty string) so registry.json will be written with description, author, steps, links and tags populated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@kits/mou-drafter/apps/package.json`:
- Line 37: The package.json currently pins dependencies to unsupported stack
versions (next, react, react-dom); either update the dependency entries for
"next" to a supported 14.x or 15.x range and set "react" and "react-dom" to
React 18 (e.g., ^18.2.0) to match the kit guidance, or add a short, explicit
justification in the repo (package.json comment is not allowed—add a clear
rationale to the PR description or README) explaining why you intentionally
require Next 16 and React 19 and any compatibility workarounds; target the
"next", "react", and "react-dom" identifiers when making the change so reviewers
can verify alignment with the kit spec.
- Around line 39-40: The package.json currently pins "react" and "react-dom" to
"19.2.6"; align with the kit policy by either (A) changing these dependency
entries in package.json to the approved React 18.x pin (e.g., "react": "18.x",
"react-dom": "18.x") or (B) add a short documented justification in the repo
(e.g., README or a new DEPENDENCY_DECISIONS.md) explaining why React 19 is
intentionally used for this kit and noting compatibility with Next.js; update
the package.json dependencies (react/react-dom) or add the justification file
accordingly and ensure the change references the same dependency keys.
In `@registry.json`:
- Around line 2738-2773: Update kits/mou-drafter/lamatic.config.ts so the config
uses unquoted JS object keys (e.g., name:, author: { name:, email: }, steps: [{
id:, type:, ... }], links: { github:, deploy: ... }) instead of JSON-style
quoted keys so the registry parser regex will match; populate description with a
meaningful string, add non-empty tags, ensure author has name/email, and set
links.deploy to a real URL (not an empty string) so registry.json will be
written with description, author, steps, links and tags populated.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: d9af7d8c-c2bf-4f10-b8de-54e2ba53083d
📒 Files selected for processing (3)
kits/mou-drafter/apps/next.config.mjskits/mou-drafter/apps/package.jsonregistry.json
💤 Files with no reviewable changes (1)
- kits/mou-drafter/apps/next.config.mjs
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
kits/mou-drafter/apps/tsconfig.json (2)
36-37: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueIntel suggests redundant path entry.
Agent, you've included both forward-slash and backslash variants of the
.next/dev/typespath. Modern Node.js normalizes paths cross-platform—the backslash entry is redundant. Consider removing line 37 for cleaner config.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/tsconfig.json` around lines 36 - 37, Remove the redundant Windows-style path entry ".next\\dev/types/**/*.ts" from tsconfig.json since Node/TypeScript path resolution handles cross-platform separators; keep the forward-slash entry ".next/dev/types/**/*.ts" and ensure any other similar duplicated backslash entries are cleaned up so only normalized paths remain.
11-11: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winMission brief: Enable strict mode for enhanced type safety.
Agent, your TypeScript configuration has
strict: false. For a new 2026 deployment, this disables critical type-checking safeguards (strict null checks, no implicit any, etc.). This mission requires stricter discipline.🎯 Recommended upgrade
- "strict": false, + "strict": true,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/mou-drafter/apps/tsconfig.json` at line 11, The project tsconfig.json currently has "strict": false; change the TypeScript compiler option "strict" to true in tsconfig.json to enable all strict checks (including strictNullChecks and noImplicitAny), then run a full type-check (tsc --noEmit) and fix resultant type errors (address implicit anys, nullable types, and incorrect function signatures) in affected modules; ensure any per-folder or extends-based tsconfig overrides do not re-disable strict and update those (or add local compilerOptions) so strict mode is globally active.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@kits/mou-drafter/apps/tsconfig.json`:
- Around line 36-37: Remove the redundant Windows-style path entry
".next\\dev/types/**/*.ts" from tsconfig.json since Node/TypeScript path
resolution handles cross-platform separators; keep the forward-slash entry
".next/dev/types/**/*.ts" and ensure any other similar duplicated backslash
entries are cleaned up so only normalized paths remain.
- Line 11: The project tsconfig.json currently has "strict": false; change the
TypeScript compiler option "strict" to true in tsconfig.json to enable all
strict checks (including strictNullChecks and noImplicitAny), then run a full
type-check (tsc --noEmit) and fix resultant type errors (address implicit anys,
nullable types, and incorrect function signatures) in affected modules; ensure
any per-folder or extends-based tsconfig overrides do not re-disable strict and
update those (or add local compilerOptions) so strict mode is globally active.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: e13bd01e-2092-4e88-9e8f-64765e3bfb6e
⛔ Files ignored due to path filters (1)
kits/mou-drafter/apps/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
kits/mou-drafter/apps/global.d.tskits/mou-drafter/apps/next-env.d.tskits/mou-drafter/apps/package.jsonkits/mou-drafter/apps/tsconfig.json
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
|
@rohith0110 can you resolve the above coderabbit comments? also you can also remove the registry.json file too from the PR. This registry gets updated automatically via our GitHub actions checks. |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hey, I made the minor fixes and removed the registry from the PR, but the issue was that when I opened a PR from my fork's feature branch to the main branch, it triggered the GitHub Action on my fork. The action is configured to auto-update the registry on merge, so when I merged feat/mou-drafter into my fork's main via PR, the bot ran and pushed registry changes. That's what caused the registry to show up as modified. |
- lamatic-client: export singleton lamaticClient instead of factory function - compile-latex route: fail fast on chmod errors rather than silently swallowing them; the sandbox user (65534:65534) requires a world-writable /output mount - orchestrate: derive flow ID from lamatic.config step definition (falls back to MOU_DRAFTER_FLOW_ID env override); redact agreementTitle in diagnostic log - MoUForm: replace any types on FormSelect.control and PartyFields (register/control/errors) with concrete react-hook-form generics - form.tsx/useFormField: guard checks now run before useFormState so fieldContext is guaranteed non-null when its name is passed to the hook - test-e2e: add withTimeout (120s) around executeFlow to prevent CI hangs; add sync warning comment on local flattenFormToTrigger; add services and design variants alongside catering so all three engagement-type branches are exercised
…actory Switch orchestrate.ts from the removed lamaticClient singleton import to the getLamaticClient() factory exported by the updated lamatic-client.ts.
…build lamatic.config.ts: - Switch from JSON-style quoted keys to unquoted JS object keys so the registry parser regex matches - Add meaningful description and tags - Add envKey: MOU_DRAFTER_FLOW_ID to the mandatory step so orchestrate.ts resolves the flow ID from config rather than always falling back to the env var - Set a real Vercel deploy URL and a full GitHub link apps/tsconfig.json: - Add ../../lamatic.config.ts to the include array so TypeScript (and therefore Next.js/webpack) can resolve the ../../lamatic.config import in actions/orchestrate.ts; without this entry the file is outside the compilation scope and Vercel fails with "Module not found"
|
Hey @akshatvirmani, I've made all the fixes CodeRabbit suggested. Let me know if there's anything else you'd like changed. Thanks! |
|
Great! @rohith0110 just one thing can you remove the additional line change in the registry.json file. It is still showing in the PR. We can merge after that
|
|
Hey @akshatvirmani, is it okay now? Let me know if there's anything else you'd like changed. Thanks! |
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
|
Merged! @rohith0110 if you want you add add https://mou.itsrohith.dev/ in the "deploy" field in the lamatic.config.ts file |
|
Hey @akshatvirmani, got the merge notification and just wanted to say thanks. Building this kit was genuinely fun, and the challenge format made it worth doing properly. Glad to have been part of it. I will open a new PR with the link added to the deploy field. |

Problem
Drafting a Memorandum of Understanding or a small-vendor service contract is one of those tasks where the typing is fast but the thinking is expensive. A founder, event organiser, or operations lead has to:
Most people end up either copy-pasting a stale template they don't fully understand, or paying a lawyer for a first draft that was always going to be a first draft anyway.
Solution
MoU Drafter is an AgentKit kit that turns a structured 30-field form into a professionally-typeset PDF contract, automatically applying a curated set of 21 protective clause patterns based on the engagement context. It is explicitly a first-draft generator for human review, not legal advice.
The flow runs entirely on Lamatic:
jurisdictionFamilyfrom the free-text governing-law field, and surfaces upstream warnings (lump-sum risk, missing event dates, signatory-role collisions).\write18,\input,\loop, …), verifies that every expected pattern anchor is present via% PATTERN:<anchor>markers, and renders into a hand-maintainedarticle-class template with a real signature block and a confidential footer.pdflatexon the dev host, with download-only fallback in production), a drafting-notes panel for warnings, a pattern report, and one-click download.tex/.pdfplus Open in Overleaf for further negotiation.The result is a single page where a non-lawyer can produce a clean, protective, jurisdiction-aware MoU draft in under a minute — and a reviewer can verify why each clause is there by reading the
patternReportreturned alongside the document.Project Links
Source Code
https://github.com/rohith0110/AgentKit/tree/feat/mou-drafter
Branch:
feat/mou-drafterKit path:
kits/mou-drafter/Live Demo
https://mou.itsrohith.dev
Video Walkthrough
https://youtu.be/rqpECF_buuI
Tech Stack
articleclass) — deterministic typesettingpdflatex(dev) viaapps/app/api/compile-latex/route.ts— live PDF preview only on local builds with MiKTeX installedlamaticnpm SDK — server-action client (apps/lib/lamatic-client.ts)Features
liquidated-damagesonly for US/Canada governing law;no-publicityonly when explicitly required;guest-count-adjustmentsonly for catering engagements with a finalisation date).<<<USER_INPUT>>>delimiters; the system prompt treats anything inside as data, never instructions.texEscape; model prose passes through a selective escaper that preserves intended LaTeX commands but neutralises stray& $ _ # %.Impact
patternReport+ the% PATTERN:<anchor>markers in the rendered LaTeX), instead of trusting the document blindly.PR Checklist
1. Select Contribution Type
kits/mou-drafter/)bundles/<bundle-name>/)templates/<template-name>/)2. General Requirements
kebab-caseand matches the flow ID (mou-drafter)README.md(purpose, setup, usage)3. File Structure
lamatic.config.tspresent with valid metadata (name, description, tags, steps, author, env keys, links)agent.mdpresent (LLM-generated agent identity & capability doc)flows/mou-drafter.tspresent, self-contained (meta + inputs + references + nodes + edges)@referencedfrom the flow:prompts/mou-drafter_llmnode-842_system_0.md(system prompt)prompts/mou-drafter_llmnode-842_user_1.md(user prompt)scripts/mou-drafter_code-node-316_code.ts(validate-input)scripts/mou-drafter_code-node-138_code.ts(assemble-latex)model-configs/mou-drafter_llmnode-842_generative-model-name.tsconstitutions/default.mdapps/.env.examplepresent with placeholder values only (no real keys)@referencetargets edited in this repo)4. Validation
npm install && npm run devworks locally (run fromkits/mou-drafter/apps/)[kit] Add MoU Drafter — AI-powered MoU & vendor-contract drafting with LaTeX/PDF output)agentkit-challengeDisclaimer
This kit generates a first-draft document using software. It is not legal advice and does not substitute for review by a licensed attorney in the relevant jurisdiction. Every generated draft includes a verbatim disclaimer footer and a drafting-notes panel listing any caveats the validator surfaced.
Flow overview (kits/mou-drafter/flows/mou-drafter.ts)
Files added (grouped, concise)
Key functional highlights (condensed)
Outstanding / PR notes