Skip to content

A2: Behavioral Patterns

A2 adds one feature to a real, unfamiliar codebase. You will produce two design proposals for the same feature: one written by you, one generated by an AI agent. You will then compare them, choose or combine them, implement the result with AI, and report on how you decided.

The order in which you produce the two proposals is assigned to you. Some students design first and then ask the agent. Others ask the agent first and then design. Both orders are legitimate. The assignment asks you to notice what the order did to your thinking.

Submit on Gradescope by Sunday, September 13, 11:59 pm. There is also a checkpoint submission partway through (Step 3).

The Codebase and the Feature

The codebase is Dnote, a command-line notebook written in Go and backed by SQLite. Every note lives in exactly one book, Dnote's name for a notebook (for example, dnote add work -c "..." adds a note to the book work). The CLI already supports dnote add, dnote view, and dnote find. You will work on the CLI only. Ignore the sync server and the web assets.

Clone the course copy of the repository: https://github.com/CMU-17695/a2-dnote. It is Dnote at a fixed commit (a07a751). Do not update it to a newer upstream version.

Build and test with these commands, not the upstream Makefile:

go build -tags fts5 -o dnote ./pkg/cli
go test -tags fts5 ./pkg/cli/...

You need Go 1.25 or newer and a C compiler.

The feature: dnote export

Add a command that prints the user's notes to standard output.

dnote export [--format markdown|json] [--book <name>] [--since YYYY-MM-DD]

Required behavior:

  • --format selects the output shape. Markdown is the default.
  • --book limits the export to one book, matched by its exact name.
  • --since limits the export to notes added on or after the given date, with the day starting at 00:00 UTC.
  • The two filters are independent and can be combined.
  • Deleted notes are never exported.
  • Output is deterministic: the same database and flags produce byte-identical output on every run. Order notes by book name, then by the time they were added, then by note UUID.
  • Every note includes its UUID, added and edited timestamps, and full body. Timestamps use RFC 3339 in UTC. Dnote stores them as Unix nanoseconds. A note that has never been edited stores 0, and your export reports its added time as its edited time.
  • Markdown output uses a level-one heading per book and a level-two heading per note.
  • JSON output is one document: an array of books, each an object with a name and a notes array. Each note has uuid, added_on, edited_on, and body. Formatting beyond the keys is yours.
  • A book with no matching notes is omitted. An export that matches nothing succeeds with an empty document ([] for JSON, empty output for Markdown).
  • An unknown format, a date that does not parse, or a book that does not exist is an error. Print a clear message to standard error, exit with a nonzero status, and print nothing to standard output. (Careful: Dnote's default error handler prints to standard output. Route your errors deliberately.)

The brief describes behavior, not structure. How you represent formats, compose filters, place queries, and stream or collect results is your design. Do not add a tag filter (Dnote has no tags), a database migration, or changes to sync, the server, or the web assets.

Your Assigned Order

Your order depends on your last name.

  • Last names A to L: design first. Write your own proposal, lock it, then ask the agent for its proposal.
  • Last names M to Z: AI first. Ask the agent for its proposal, lock it, then write your own.

Follow your assigned order. Swapping it costs points on the protocol component.

Steps

  1. Onboard with AI and your IDE. Build the project and run its tests. Use an agent and any IDE tools to understand the build, the architecture, how an existing command such as dnote view works, and where notes and books live. Diagnose setup or test failures with whatever help you like. Do not ask the agent to design or implement dnote export. When you are done, export the transcript and close the session (in either order). Every later AI session starts fresh.

  2. Produce your first proposal, in the order assigned to you.

    • Your own proposal is written without AI.
    • The AI proposal is produced in a fresh session. Give the agent the repository and the feature brief above and ask it for a proposal that follows "Proposal Format". Do not rewrite its proposal. In either order, the agent sees only the repository and the brief. Do not show the agent your own proposal.
  3. Lock the first proposal. Submit the first proposal as a PDF to the Gradescope assignment "A2 checkpoint" before you begin the second. The copy in your final zip must be identical to it.

  4. Produce your second proposal, under the same rules as Step 2. Export it as a PDF before you compare the two. It also stays unchanged from then on. Later insights go in the report.

  5. Compare and choose, without AI. Read both proposals side by side. Select one, or synthesize a third direction. Record what you selected, combined, or rejected, and why. This becomes the first section of your report.

  6. Implement the design you chose, with AI. Implement dnote export once, following your selection. Write tests for your export logic: at least one normal path and at least one boundary, composition, or error case. Keep to the feature boundary. Export the transcript of every implementation session.

  7. Write the report, without AI. Use the sections and caps in "Report Format". Apply the three change scenarios below to your own proposal, the AI proposal, and the final implementation:

    1. Add a third export format without changing the existing Markdown and JSON behavior.
    2. Add another filter that composes with both --book and --since.
    3. Export a notebook large enough that latency and memory use become design concerns.

    For each scenario and each design, name the quality attributes that matter, cite concrete design evidence (which parts a change touches, where conditionals accumulate, whether behavior can be tested on its own), and say what the design buys and what it costs. Current simplicity is a legitimate benefit. If the two proposals converge, say so, explain why, and analyze the differences that remain.

Proposal Format

Both proposals use the same headings, in this order:

  1. Proposed structure and responsibilities
  2. Data and control flow
  3. The principal behavioral design decision
  4. One credible alternative and why it was not selected
  5. The expected change surface
  6. One diagram

Aim for a proposal that answers these questions:

  • What varies in this feature (formats, filters), and where does your design decide each one?
  • Which existing code does export reuse, and what does it add?
  • What happens between reading notes from the database and writing to standard output?
  • If another format or filter arrived, which parts would change?
  • What is one other reasonable structure, and why not that one?

Your own proposal does not need to be sophisticated. A simple, concrete design grounded in the code will suffice.

Each proposal is at most 500 words plus one diagram. Diagram labels and signatures do not count toward the cap. Prose callouts do.

The diagram

A1 allowed informal diagrams. From here on, draw a class diagram, using the notation from the second studio session (selectively). If a decision in your design lives inside a conditional rather than a structure, you can mark the method that decides with a short callout. The diagram must:

  • fit legibly on one page, with at most 10 nodes and three short callouts
  • cover only the part of Dnote involved in export
  • distinguish existing, changed, and new elements
  • name a node's kind where it helps (package, struct, interface, function)
  • show the relevant responsibilities, operations, or fields, not a complete member inventory
  • label relationships (calls, passes data to, owns, holds, implements)
  • make the format and filter decision points visible, whether the design uses interfaces, functions, a pipeline, or conditionals

Use interface realization, cardinality, and filled or open diamonds where the distinction is important. Include a small legend for any symbol that is not standard. Hand-drawn or digital is fine. Visual polish is not graded. No diagram of the final implementation is required.

Report Format

The report is written without AI and is at most 1,500 words, excluding captions and references.

  1. Selection or synthesis (250 words): what you selected, combined, or rejected, and why.
  2. Change-scenario analysis (three sections, 250 words each): one section per scenario from Step 7.
  3. Implementation trace (300 words): where the implementation follows or departs from each proposal, and where each consequential decision came from (your proposal, the AI proposal, the comparison, or an implementation-time choice).
  4. Process reflection (200 words): how the order of the proposals, and seeing the AI proposal, affected your thinking, or did not. Report on yourself only. Do not guess at a class-wide result.

There are no minimum word counts. Use 3 to 6 file-and-line references to connect claims to your implementation. If you need code excerpts, include at most three, each at most 15 lines. An excerpt does not replace the explanation.

AI Use

Work AI allowed?
Onboarding (Step 1) Yes, except designing or implementing the feature
Your own proposal No
The AI proposal The agent writes it. Do not edit it.
Comparison and selection No
Implementation and tests Yes
Report No

Every AI session is exported in full. See the transcript policy for formats and instructions.

Submission

Checkpoint: the PDF of your first proposal, to the Gradescope assignment "A2 checkpoint", before you begin the second proposal.

Final: one zip file to the Gradescope assignment "A2", containing:

proposal-human.pdf
proposal-ai.pdf
report.pdf
transcripts/
<your working Dnote source tree, including tests>
  • Whichever proposal you submitted at the checkpoint must be identical here.
  • transcripts/ holds one complete export per AI session, including onboarding, the AI proposal, and implementation. Screenshots and edited excerpts are not transcripts. (Redacting accidentally included private information is fine, though.)
  • Include the source the CLI needs to build and test: go.mod, go.sum, pkg/cli, pkg/assert, pkg/clock, pkg/dirs, and pkg/prompt. Leave out pkg/server, pkg/e2e, .git, compiled binaries, generated databases, caches, and other build output. Gradescope rejects uploads with more than 256 files, and the full Dnote tree alone has over 300.

The easiest way to build the zip is git archive, which exports only committed files and doesn't include .git. Put the three PDFs and transcripts/ inside your cloned repo, then run:

echo '/dnote' >> .gitignore
git add -A
git commit -m "A2 submission"
git archive --format=zip --output=a2.zip HEAD go.mod go.sum pkg/cli pkg/assert pkg/clock pkg/dirs pkg/prompt proposal-human.pdf proposal-ai.pdf report.pdf transcripts

No push is needed. The first line makes sure that the dnote binary that go build produces (not gitignored by default) is not committed by git add -A. The result should be well under a megabyte and about 120 files. Gradescope unpacks the zip on upload. That is expected.

A submission without transcripts is incomplete. The late policy applies.

Grading

We grade your proposals, comparison, and reasoning more heavily than whether the feature works. No points depend on using a named pattern, on the two proposals differing, on selecting your own proposal, or on reaching any particular conclusion about AI. A conditional design, convergent proposals, an unfinished implementation, or "the order made no difference" can all earn full credit when the claims are specific and backed by evidence. The AI proposal is graded only on being complete, unedited, and produced under the rules above, not on being a good design. Your assigned order does not affect your grade. Both proposals are graded the same way for either cohort.

Component Weight Graded on
Proposal artifacts and protocol (Steps 2 to 4) 20% Two complete, comparable proposals with usable diagrams. A concrete proposal of your own grounded in Dnote. The assigned order and the checkpoint followed.
Selection or synthesis (Step 5) 10% A clear decision supported by concrete differences between the proposals and their trade-offs.
Implementation and tests (Step 6) 20% 10 points for the required behavior, checked automatically. 5 for meaningful tests. 5 for staying within the feature boundary with understandable responsibilities.
Change-scenario analysis (Step 7) 30% 10 points per scenario: applied to all three designs, with justified quality attributes, concrete evidence, and both benefits and costs.
Implementation trace (Step 7) 10% Accurate, checkable links between the proposals and the code, including divergences and where decisions came from.
Process reflection (Step 7) 10% A concrete, individual account of how proposal order and exposure affected your thinking, or did not.
Transcripts required Ungraded, but the submission is incomplete without them.

A build or behavior failure costs points only in the implementation component.