# Project Import — PeopleCode Diff vs Database

LLMS index: [llms.txt](/llms.txt)

---

<div id="pslens-context-panel" class="card border-info mb-4 d-none">
  <div class="card-header bg-light text-info py-2 fw-bold d-flex align-items-center border-bottom border-info-subtle">
    <i class="bi bi-info-circle-fill me-2"></i>
    <span>Tailored Operational Context</span>
  </div>
  <div class="card-body p-0">
    <ul class="list-group list-group-flush">
      <li id="row-db" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Target Database:</strong>
        <span id="ctx-db" class="badge bg-secondary font-monospace">&mdash;</span>
      </li>
      <li id="row-type" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Context Type:</strong>
        <span id="ctx-type" class="badge bg-light text-dark border font-monospace text-uppercase">&mdash;</span>
      </li>
      <li id="row-severity" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Alert Severity:</strong>
        <span id="ctx-severity" class="badge">&mdash;</span>
      </li>
      <li id="row-time" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Triggered Time:</strong>
        <span id="ctx-time" class="text-muted small">&mdash;</span>
      </li>
      <li id="row-details" class="list-group-item py-2 d-none">
        <strong id="label-details" class="d-block mb-1">Firing Context:</strong>
        <code id="ctx-details" class="d-block p-2 bg-light border rounded small" style="white-space: pre-wrap; word-break: break-all;">&mdash;</code>
      </li>
    </ul>
  </div>
</div>

<script>
  (function() {
    const params = new URLSearchParams(window.location.search);
    const metadata = params.get('metadata');
    if (!metadata) return;

    try {
      
      const base64 = metadata.replace(/-/g, '+').replace(/_/g, '/');
      const jsonStr = decodeURIComponent(escape(window.atob(base64)));
      const data = JSON.parse(jsonStr);

      if (data) {
        let hasData = false;

        if (data.db) {
          document.getElementById('ctx-db').textContent = data.db;
          document.getElementById('row-db').classList.remove('d-none');
          hasData = true;
        }

        if (data.type) {
          document.getElementById('ctx-type').textContent = data.type;
          document.getElementById('row-type').classList.remove('d-none');
          hasData = true;
        }

        if (data.severity) {
          const severityBadge = document.getElementById('ctx-severity');
          const severity = data.severity.toLowerCase();
          severityBadge.textContent = severity.toUpperCase();
          if (severity === 'critical') {
            severityBadge.className = 'badge bg-danger';
          } else if (severity === 'warning') {
            severityBadge.className = 'badge bg-warning text-dark';
          } else {
            severityBadge.className = 'badge bg-info';
          }
          document.getElementById('row-severity').classList.remove('d-none');
          hasData = true;
        }

        if (data.t) {
          const date = new Date(data.t * 1000);
          document.getElementById('ctx-time').textContent = date.toLocaleString();
          document.getElementById('row-time').classList.remove('d-none');
          hasData = true;
        }

        if (data.details) {
          document.getElementById('ctx-details').textContent = data.details;

          
          const labelDetails = document.getElementById('label-details');
          if (data.type === 'object') {
            labelDetails.textContent = 'Object Metadata Details:';
          } else if (data.type === 'report') {
            labelDetails.textContent = 'Report Description:';
          } else {
            labelDetails.textContent = 'Firing Context:';
          }

          document.getElementById('row-details').classList.remove('d-none');
          hasData = true;
        }

        if (hasData) {
          document.getElementById('pslens-context-panel').classList.remove('d-none');
        }
      }
    } catch (e) {
      console.error('Failed to parse operational context metadata:', e);
    }
  })();
</script>


## Project Import — PeopleCode Diff vs Database

**Report ID:** `project-import-diff`
**Category:** Objects

## Purpose

You uploaded a PeopleSoft project XML on the **Project Import** page, and you want to know — line-by-line — how every PeopleCode program inside that file compares to the same program in a live database.

The Project Import results page itself shows a quick **Same / Different / Not in DB** badge per object (powered by a content-hash compare against `PSPCMTXT`). That's enough for triage. When you need to see what actually changed, run this report; it emits a full markdown document with file source, database source, and a unified diff for every PeopleCode object that differs.

The output is designed to be reviewed by hand **or fed directly to an LLM** — the per-object structure (file block, DB block, diff block) is what most assistants need to reason about the change.

## What It Compares

This report only looks at PeopleCode-bearing object types:

- Record PeopleCode (type 8)
- Menu PeopleCode (type 9)
- Message PeopleCode (type 39)
- App Engine PeopleCode (type 43)
- Page PeopleCode (type 44)
- Component PeopleCode (type 46)
- Component Record PeopleCode (type 47)
- Component Record Field PeopleCode (type 48)
- Application Package PeopleCode (type 58)

For each PeopleCode item in the project, the report:

1. Reads the source from the uploaded XML (`peoplecode_text` node parsed at upload time).
2. Fetches the current source from the target database's `PSPCMTXT` table, concatenating multi-row `PCTEXT` payloads in `PROGSEQ` order.
3. Normalizes both sides (line-ending normalization, trailing-whitespace strip, blank-line collapse) so cosmetic differences don't show up as content changes.
4. Classifies the item as **Same**, **Different**, **Not in DB**, **No XML Source**, or **Error**.
5. For **Different** items, renders both sources and a line-level diff inline.

Non-PeopleCode object types in the same project are not included in this report — use the Project Import results page for those (it uses `LASTUPDDTTM` comparison, which is reliable for non-PeopleCode types).

## Parameters

|   Parameter    | Required | Default |                                                                                                                                  Description                                                                                                                                  |
| -------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `project_id`   | Yes      | —       | The file-store ID of the uploaded project. The Project Import results page provides a "PeopleCode Diff Report" button that pre-fills this.                                                                                                                                    |
| `max_objects`  | No       | `100`   | Cap on how many **Different** objects are rendered with full source + diff. Excess Different objects are mentioned in a footer line; raise the cap if you need them all inline. Prevents the report from blowing up on projects with hundreds of changed PeopleCode programs. |
| `include_same` | No       | `false` | Set to `true` to append a table listing every PeopleCode object that matched. Off by default since this is usually the noise, not the signal.                                                                                                                                 |

The **target database** is the standard psLens database selector on the Reports page — the report runs against whichever database you have selected.

## Output Structure

The report is a single markdown document with these sections in order:

1. **Header** — project name, source DB (from the XML export), target DB, export date, exporter ID, uploaded filename, upload time.
2. **Summary** — counts of Same / Different / Not in DB / No XML Source / Errors.
3. **Different** — one section per Different object containing:
   - **File source** — code fence with `peoplecode` language hint.
   - **Database source** — code fence with `peoplecode` language hint.
   - **Line diff (file → DB)** — code fence with `diff` language hint; lines unchanged on both sides appear with two-space prefix, removed-from-file lines with `-`, added-in-DB lines with `+`.
4. **Not in Database** — one section per item, with the file source rendered. These are typically programs the project would create on import.
5. **No XML Source** — table of programs the DB has but the XML didn't inline. Usually means the project listed the PJM entry without the PCM payload.
6. **Errors** — table of programs whose DB query failed, with the underlying error.
7. **Same** (optional, `include_same=true`) — table of matching programs.

## Tips

- **Feed it to an LLM.** The structure (file block + DB block + diff block per object) is what assistants need to reason about a change. Download the markdown and paste into your assistant of choice, or use the `Download .md` button on the report run page.
- **Pair with the Cross-Database Comparison report.** `project-compare` covers *two databases*; this one covers *file vs database*. Different problems.
- **Run before a project import.** Knowing exactly what will change in PeopleCode terms is the question this report answers — not "what does the timestamp say" but "what code lines will end up different."
